From ab5018695aa120ed7b6edacfa9be0c0d063c848c Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 23 Jul 2024 22:31:42 +0100 Subject: [PATCH 001/142] deprecate `tread` & `@[` --- builtins/core/io/read.go | 2 ++ builtins/core/ranges/ranges.go | 7 +++- integrations/docker_any.mx | 4 +-- integrations/microk8s_any.mx | 2 +- integrations/systemctl_linux.mx | 63 +++++++++++++++++++-------------- integrations/yarn_any.mx | 4 +-- 6 files changed, 50 insertions(+), 32 deletions(-) diff --git a/builtins/core/io/read.go b/builtins/core/io/read.go index 649f5ac5c..b97865be5 100644 --- a/builtins/core/io/read.go +++ b/builtins/core/io/read.go @@ -24,6 +24,8 @@ func cmdRead(p *lang.Process) error { } func cmdTread(p *lang.Process) error { + lang.DeprecatedBuiltin(p) + dt, err := p.Parameters.String(0) if err != nil { return err diff --git a/builtins/core/ranges/ranges.go b/builtins/core/ranges/ranges.go index 88a15b7e9..458c4fb18 100644 --- a/builtins/core/ranges/ranges.go +++ b/builtins/core/ranges/ranges.go @@ -12,7 +12,7 @@ import ( ) func init() { - lang.DefineMethod("@[", CmdRange, types.ReadArray, types.WriteArray) + lang.DefineMethod("@[", deprecatedRange, types.ReadArray, types.WriteArray) } const usage = "\nUsage: [start..end] / [start..end]se\n(start or end can be omitted)" @@ -21,6 +21,11 @@ const usage = "\nUsage: [start..end] / [start..end]se\n(start or end can be omit // /home/lau/dev/go/src/github.com/lmorg/murex/lang/parameters.go var RxSplitRange = regexp.MustCompile(`^\s*(.*?)\s*\.\.\s*(.*?)\s*\]([bt8ernsiu]*)\s*$`) +func deprecatedRange(p *lang.Process) error { + lang.DeprecatedBuiltin(p) + return CmdRange(p) +} + func CmdRange(p *lang.Process) (err error) { dt := p.Stdin.GetDataType() p.Stdout.SetDataType(dt) diff --git a/integrations/docker_any.mx b/integrations/docker_any.mx index ac235aa2b..334648e31 100644 --- a/integrations/docker_any.mx +++ b/integrations/docker_any.mx @@ -1,7 +1,7 @@ autocomplete: set docker %[ { DynamicDesc: '{ - docker help -> @[^Usage:..]re -> tabulate: --split-comma --map + docker help -> [^Usage:..]re -> tabulate: --split-comma --map }' ListView: true @@ -9,7 +9,7 @@ autocomplete: set docker %[ FlagValues: { "": [{ DynamicDesc: '{ - docker help $1 -> @[^Usage:..]re -> tabulate: --split-comma --map + docker help $1 -> [^Usage:..]re -> tabulate: --split-comma --map }' }] } diff --git a/integrations/microk8s_any.mx b/integrations/microk8s_any.mx index 326d41c82..f89102724 100644 --- a/integrations/microk8s_any.mx +++ b/integrations/microk8s_any.mx @@ -40,7 +40,7 @@ test: unit private autocomplete.microk8s.kubectl { private autocomplete.microk8s.kubectl.dyndesc { # Dynamic completion for microk8s kubectl - microk8s kubectl help $ARGS[1] -> @[^Options..^Usage]re -> regexp "s/:/\t/" -> tabulate: --key-inc-hint --map --split-comma + microk8s kubectl help $ARGS[1] -> [^Options..^Usage]re -> regexp "s/:/\t/" -> tabulate: --key-inc-hint --map --split-comma } autocomplete: set microk8s {[ diff --git a/integrations/systemctl_linux.mx b/integrations/systemctl_linux.mx index 372b3a279..10bd7899a 100644 --- a/integrations/systemctl_linux.mx +++ b/integrations/systemctl_linux.mx @@ -1,10 +1,10 @@ -!if { which: systemctl } then { +!if { which systemctl } then { return } private autocomplete.systemctl { # Returns all known systemd unit files - systemctl: list-unit-files -> !regexp m/unit files listed/ -> [:0] -> cast str + systemctl list-unit-files -> !regexp m/unit files listed/ -> [:0] -> cast str } test unit private autocomplete.systemctl %{ @@ -16,35 +16,46 @@ test unit private autocomplete.systemctl %{ function autocomplete.systemctl.flags { # Parses `systemctl --help` looking for flags then returns `autocomplete` config based on those flags - systemctl: --help -> regexp %(m/PATTERN/) -> tabulate: --map --key-inc-hint -> formap key val { - out ("$key": [{ - "Dynamic": ({ autocomplete.systemctl }), - "ListView": true, - "Optional": false, - "AllowMultiple": true - }],) + + cast json + + systemctl --help \ + -> regexp %(m/PATTERN/) \ + -> tabulate --map --key-inc-hint \ + -> formap key val { + json <~ %{ + $key: [{ + Dynamic: '{ autocomplete.systemctl }' + ListView: true + Optional: false + AllowMultiple: true + }] + } } - out ("": [{}]) # dummy value so there's no trailing comma + + $json } -autocomplete set systemctl ([ +autocomplete set systemctl %[ { - "DynamicDesc": ({ - systemctl: --help -> @[..Unit Commands:]s -> tabulate: --column-wraps --map --key-inc-hint --split-space - }), - "Optional": true, - "AllowMultiple": false - }, + DynamicDesc: '{ + systemctl --help \ + -> [..Unit Commands:]s \ + -> tabulate --column-wraps --map --key-inc-hint --split-space + }' + Optional: true + AllowMultiple: false + } { - "DynamicDesc": ({ - systemctl: --help -> @[Unit Commands:..]s -> tabulate: --column-wraps --map --key-inc-hint - }), - "Optional": false, - "AllowMultiple": false, - "FlagValues": { - ${ autocomplete.systemctl.flags } - } + DynamicDesc: '{ + systemctl --help \ + -> [Unit Commands:..]s \ + -> tabulate --column-wraps --map --key-inc-hint + }' + Optional: false + AllowMultiple: false + FlagValues: ${ autocomplete.systemctl.flags } } -]) +] !function autocomplete.systemctl.flags \ No newline at end of file diff --git a/integrations/yarn_any.mx b/integrations/yarn_any.mx index 20f158bed..11d760463 100644 --- a/integrations/yarn_any.mx +++ b/integrations/yarn_any.mx @@ -33,13 +33,13 @@ autocomplete: set yarn ({[ { "Flags": ${ trypipe { - yarn help -> @[Commands..Run]re -> [:1] -> cast str -> format json + yarn help -> [Commands..Run]re -> [:1] -> cast str -> format json } }, "FlagValues": { ${ trypipe { - yarn help -> @[Commands..Run]re -> [:1] -> foreach MOD_cmd { + yarn help -> [Commands..Run]re -> [:1] -> foreach MOD_cmd { out ("$MOD_cmd": [{ "DynamicDesc": ({ From 2dee45ef963d6f39df1d64ecc7de09f21717532b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 24 Jul 2024 14:49:21 +0100 Subject: [PATCH 002/142] deprecate `@[` --- integrations/git_any.mx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/git_any.mx b/integrations/git_any.mx index 148a16912..e872300c5 100644 --- a/integrations/git_any.mx +++ b/integrations/git_any.mx @@ -21,7 +21,7 @@ autocomplete set git %[{ cast json # extract git commands from `git help` - git help -a -> @[..^Ancillary]re -> tabulate: --map -> set commands + git help -a -> [..^Ancillary]re -> tabulate --map -> set commands # list all the git aliases git config --list -> regexp %(f/alias\.(.*)$/) -> foreach --jmap alias { From 0c54d3befbb12e18793b6e8938a25c528d5b27a0 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 30 Jul 2024 23:24:59 +0100 Subject: [PATCH 003/142] #840 `~` should fail if username not found --- app/app.go | 4 +- lang/expressions/parse_array.go | 6 ++- lang/expressions/parse_expression.go | 6 ++- lang/expressions/parse_object.go | 6 ++- lang/expressions/parse_quotes.go | 7 ++- lang/expressions/parse_statement.go | 6 ++- lang/expressions/parse_switch.go | 6 ++- lang/expressions/parse_vars.go | 19 ++++--- lang/expressions/parse_vars_exec_test.go | 69 +++++++++++++++++++----- shell/variables/expand.go | 8 ++- utils/home/home.go | 10 ---- utils/home/home_test.go | 15 ------ version.svg | 2 +- 13 files changed, 109 insertions(+), 55 deletions(-) diff --git a/app/app.go b/app/app.go index 898b85650..0e0b6ac3a 100644 --- a/app/app.go +++ b/app/app.go @@ -14,8 +14,8 @@ const Name = "murex" const ( version = "%d.%d.%d" Major = 6 - Minor = 2 - Revision = 4000 + Minor = 3 + Revision = 1000 ) // Copyright is the copyright owner string diff --git a/lang/expressions/parse_array.go b/lang/expressions/parse_array.go index cf824e799..6a3f4fc17 100644 --- a/lang/expressions/parse_array.go +++ b/lang/expressions/parse_array.go @@ -141,7 +141,11 @@ func (tree *ParserT) parseArray(exec bool) ([]rune, *primitives.DataType, error) case '~': // tilde - slice = append(slice, tree.parseVarTilde(exec)) + home, err := tree.parseVarTilde(exec) + if err != nil { + return nil, nil, err + } + slice = append(slice, home) case '@': // inline array diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 71019c3c2..46acc3db5 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -154,9 +154,13 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { tree.charPos++ default: // tilde + home, err := tree.parseVarTilde(exec) + if err!=nil { + return err + } tree.appendAstWithPrimitive(symbols.Calculated, primitives.NewPrimitive( primitives.String, - tree.parseVarTilde(exec), + home, )) } diff --git a/lang/expressions/parse_object.go b/lang/expressions/parse_object.go index ad644fe6d..2eb36d8b8 100644 --- a/lang/expressions/parse_object.go +++ b/lang/expressions/parse_object.go @@ -163,7 +163,11 @@ func (tree *ParserT) parseObject(exec bool) ([]rune, *primitives.DataType, error case '~': // tilde - err := o.AppendRune([]rune(tree.parseVarTilde(exec))...) + home, err := tree.parseVarTilde(exec) + if err != nil { + return nil, nil, err + } + err = o.AppendRune([]rune(home)...) if err != nil { return nil, nil, err } diff --git a/lang/expressions/parse_quotes.go b/lang/expressions/parse_quotes.go index a014a7965..f0e2fe16d 100644 --- a/lang/expressions/parse_quotes.go +++ b/lang/expressions/parse_quotes.go @@ -149,8 +149,11 @@ func (tree *ParserT) parseStringInfix(qEnd rune, exec bool) ([]rune, error) { case r == '~': // tilde - tilde := tree.parseVarTilde(exec) - value = append(value, []rune(tilde)...) + home, err := tree.parseVarTilde(exec) + if err != nil { + return nil, err + } + value = append(value, []rune(home)...) case r == '(' && qEnd == ')': v, err := tree.parseParenthesis(exec) diff --git a/lang/expressions/parse_statement.go b/lang/expressions/parse_statement.go index 2d39cd8ac..15abb9499 100644 --- a/lang/expressions/parse_statement.go +++ b/lang/expressions/parse_statement.go @@ -158,7 +158,11 @@ func (tree *ParserT) parseStatement(exec bool) error { case '~': // tilde tree.statement.validFunction = false - appendToParam(tree, []rune(tree.parseVarTilde(exec))...) + home, err := tree.parseVarTilde(exec) + if err != nil { + return err + } + appendToParam(tree, []rune(home)...) case '<': tree.statement.validFunction = false diff --git a/lang/expressions/parse_switch.go b/lang/expressions/parse_switch.go index f3b9f7820..429eaaedb 100644 --- a/lang/expressions/parse_switch.go +++ b/lang/expressions/parse_switch.go @@ -137,7 +137,11 @@ func (tree *ParserT) parseSwitch() (int, error) { case '~': // tilde - appendToParam(tree, []rune(tree.parseVarTilde(true))...) + home, err := tree.parseVarTilde(true) + if err != nil { + return 0, err + } + appendToParam(tree, []rune(home)...) if err := tree.nextParameter(); err != nil { return 0, err } diff --git a/lang/expressions/parse_vars.go b/lang/expressions/parse_vars.go index 1bbc1c6c6..a4565291d 100644 --- a/lang/expressions/parse_vars.go +++ b/lang/expressions/parse_vars.go @@ -2,6 +2,8 @@ package expressions import ( "errors" + "fmt" + "os/user" "github.com/lmorg/murex/lang/expressions/primitives" "github.com/lmorg/murex/lang/types" @@ -262,7 +264,7 @@ func isUserNameChar(r rune) bool { return isBareChar(r) || r == '.' || r == '-' } -func (tree *ParserT) parseVarTilde(exec bool) string { +func (tree *ParserT) parseVarTilde(exec bool) (string, error) { tree.charPos++ start := tree.charPos @@ -278,16 +280,21 @@ func (tree *ParserT) parseVarTilde(exec bool) string { } endTilde: - user := string(tree.expression[start:tree.charPos]) + username := string(tree.expression[start:tree.charPos]) tree.charPos-- if !exec { - return "~" + user + return "~" + username, nil } - if len(user) == 0 { - return home.MyDir + if len(username) == 0 { + return home.MyDir, nil } - return home.UserDir(user) + usr, err := user.Lookup(username) + if err != nil { + return "", fmt.Errorf("cannot expand variable `~%s`: %s", username, err.Error()) + } + + return usr.HomeDir, nil } diff --git a/lang/expressions/parse_vars_exec_test.go b/lang/expressions/parse_vars_exec_test.go index a93a9a4a6..643cc3717 100644 --- a/lang/expressions/parse_vars_exec_test.go +++ b/lang/expressions/parse_vars_exec_test.go @@ -2,6 +2,7 @@ package expressions_test import ( "fmt" + "os/user" "testing" _ "github.com/lmorg/murex/builtins" @@ -139,37 +140,79 @@ func TestParseVarsTilder(t *testing.T) { test.RunMurexTests(tests, t) } -func TestParseVarsTilderPlusName(t *testing.T) { +func TestParseVarsTilderPlusNamePositive(t *testing.T) { + usr, err := user.Current() + if err != nil { + t.Errorf("cannot run tests: %s", err.Error()) + return + } + tests := []test.MurexTest{ { - Block: `TestParseVarsTilderPlusName0= ~TestParseVarsTilderPlusName0;$TestParseVarsTilderPlusName0`, - Stdout: home.UserDir("TestParseVarsTilderPlusName0"), + Block: fmt.Sprintf(`TestParseVarsTilderPlusName0= ~%s;$TestParseVarsTilderPlusName0`, usr.Username), + Stdout: home.MyDir, }, { - Block: `TestParseVarsTilderPlusName1="~TestParseVarsTilderPlusName1";$TestParseVarsTilderPlusName1`, - Stdout: home.UserDir("TestParseVarsTilderPlusName1"), + Block: fmt.Sprintf(`TestParseVarsTilderPlusName1="~%s";$TestParseVarsTilderPlusName1`, usr.Username), + Stdout: home.MyDir, }, { - Block: `TestParseVarsTilderPlusName2='~TestParseVarsTilderPlusName2';$TestParseVarsTilderPlusName2`, - Stdout: `~TestParseVarsTilderPlusName2`, + Block: fmt.Sprintf(`TestParseVarsTilderPlusName2='~%s';$TestParseVarsTilderPlusName2`, usr.Username), + Stdout: fmt.Sprintf(`~%s`, usr.Username), }, { - Block: `%[~TestParseVarsTilderPlusName3]`, - Stdout: fmt.Sprintf(`["%s"]`, home.UserDir("TestParseVarsTilderPlusName3")), + Block: `%[~` + usr.Username + `]`, + Stdout: fmt.Sprintf(`["%s"]`, home.MyDir), }, { - Block: `%{~TestParseVarsTilderPlusName4: a}`, - Stdout: fmt.Sprintf(`{"%s":"a"}`, home.UserDir("TestParseVarsTilderPlusName4")), + Block: `%{~` + usr.Username + `: a}`, + Stdout: fmt.Sprintf(`{"%s":"a"}`, home.MyDir), }, { - Block: `%{a: ~TestParseVarsTilderPlusName5}`, - Stdout: fmt.Sprintf(`{"a":"%s"}`, home.UserDir("TestParseVarsTilderPlusName5")), + Block: `%{a: ~` + usr.Username + `}`, + Stdout: fmt.Sprintf(`{"a":"%s"}`, home.MyDir), }, } test.RunMurexTests(tests, t) } +func TestParseVarsTilderPlusNameNegative(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `TestParseVarsTilderPlusName0= ~TestParseVarsTilderPlusName0;$TestParseVarsTilderPlusName0`, + Stderr: "cannot expand variable", + ExitNum: 1, + }, + { + Block: `TestParseVarsTilderPlusName1="~TestParseVarsTilderPlusName1";$TestParseVarsTilderPlusName1`, + Stderr: "cannot expand variable", + ExitNum: 1, + }, + { + Block: `TestParseVarsTilderPlusName2='~TestParseVarsTilderPlusName2';$TestParseVarsTilderPlusName2`, + Stdout: `~TestParseVarsTilderPlusName2`, + }, + { + Block: `%[~TestParseVarsTilderPlusName3]`, + Stderr: "cannot expand variable", + ExitNum: 1, + }, + { + Block: `%{~TestParseVarsTilderPlusName4: a}`, + Stderr: "cannot expand variable", + ExitNum: 1, + }, + { + Block: `%{a: ~TestParseVarsTilderPlusName5}`, + Stderr: "cannot expand variable", + ExitNum: 1, + }, + } + + test.RunMurexTestsRx(tests, t) +} + func TestParseVarsIndex(t *testing.T) { tests := []test.MurexTest{ { diff --git a/shell/variables/expand.go b/shell/variables/expand.go index 749d6cf52..c472cc247 100644 --- a/shell/variables/expand.go +++ b/shell/variables/expand.go @@ -1,6 +1,7 @@ package variables import ( + "os/user" "regexp" "strings" @@ -32,7 +33,12 @@ func ExpandString(line string) string { match = rxHome.FindAllString(line, -1) for i := range match { - line = rxHome.ReplaceAllString(line, home.UserDir(match[i][1:])) + var home string + usr, err := user.Lookup((match[i][1:])) + if err == nil { + home = usr.HomeDir + } + line = rxHome.ReplaceAllString(line, home) } line = strings.Replace(line, "~", home.MyDir, -1) diff --git a/utils/home/home.go b/utils/home/home.go index 9d379a114..438861037 100644 --- a/utils/home/home.go +++ b/utils/home/home.go @@ -25,13 +25,3 @@ func init() { MyDir = usr.HomeDir } - -// UserDir is the home directory of a `username`. -func UserDir(username string) string { - usr, err := user.Lookup(username) - if err != nil { - return consts.PathSlash - } - - return usr.HomeDir -} diff --git a/utils/home/home_test.go b/utils/home/home_test.go index 600929429..29bd1c24f 100644 --- a/utils/home/home_test.go +++ b/utils/home/home_test.go @@ -4,7 +4,6 @@ package home import ( - "os/user" "testing" "github.com/lmorg/murex/test/count" @@ -17,17 +16,3 @@ func TestMyHome(t *testing.T) { t.Error("MyDir not set (murex will still function)") } } - -// TestUserHome tests a users home directory can be derived -func TestUserHome(t *testing.T) { - count.Tests(t, 1) - - u, err := user.Current() - if err != nil { - t.Error("Error querying user.Current: " + err.Error() + " (murex will still function)") - } - - if UserDir(u.Username) == "" { - t.Error("UserDir returning empty string (murex will still function)") - } -} diff --git a/version.svg b/version.svg index 43019cc1a..a74827684 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.2.4000Version6.2.4000 +Version: 6.3.1000Version6.3.1000 From e98d2d533a48e1c7bfd5874edcd3a30686224b38 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 31 Jul 2024 21:37:22 +0100 Subject: [PATCH 004/142] removed reference to deprecated function @[] --- utils/parser/unsafe_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/parser/unsafe_test.go b/utils/parser/unsafe_test.go index 3d1656de9..d3a3588f0 100644 --- a/utils/parser/unsafe_test.go +++ b/utils/parser/unsafe_test.go @@ -9,7 +9,7 @@ import ( ) func TestIsCmdUnsafe(t *testing.T) { - trues := []string{">", ">>", "$var", "@g", "rm"} + trues := []string{">", ">>", "$var", "rm"} falses := append(safeCmds, "open", "regexp", "match", "cast", "format", "[", "[[", From ea2655241e7c91b40e87b196f9385451e167f88c Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 31 Jul 2024 23:39:14 +0100 Subject: [PATCH 005/142] config: dynamic errors better surfaced + tests --- builtins/core/config/dynamic.go | 36 ++++------- builtins/core/config/dynamic_test.go | 47 +++++++++++++++ builtins/core/config/eval.go | 4 +- builtins/core/config/eval_test.go | 33 ++++++++++ config/config.go | 90 ++++++++++++++++------------ 5 files changed, 147 insertions(+), 63 deletions(-) create mode 100644 builtins/core/config/dynamic_test.go create mode 100644 builtins/core/config/eval_test.go diff --git a/builtins/core/config/dynamic.go b/builtins/core/config/dynamic.go index c0ffbfa9b..3aa71ca8f 100644 --- a/builtins/core/config/dynamic.go +++ b/builtins/core/config/dynamic.go @@ -1,17 +1,15 @@ package cmdconfig import ( - "errors" + "fmt" - "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/lang/types" - "github.com/lmorg/murex/utils" ) -func getDynamic(block []rune, args []string, fileRef *ref.File) func() (interface{}, error) { - return func() (interface{}, error) { +func getDynamic(block []rune, args []string, fileRef *ref.File) func() (interface{}, int, error) { + return func() (interface{}, int, error) { block = block[1 : len(block)-1] fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_NEW_MODULE | lang.F_NO_STDIN | lang.F_CREATE_STDOUT) @@ -21,26 +19,20 @@ func getDynamic(block []rune, args []string, fileRef *ref.File) func() (interfac exitNum, err := fork.Execute(block) if err != nil { - return nil, errors.New("Dynamic config code could not compile: " + err.Error()) - } - if exitNum != 0 && debug.Enabled { - lang.ShellProcess.Stderr.Writeln([]byte("Dynamic config returned a none zero exit number." + utils.NewLineString)) + return nil, exitNum, fmt.Errorf("dynamic config code could not compile: %s", err.Error()) } b, err := fork.Stdout.ReadAll() if err != nil { - return nil, err + return nil, exitNum, err } - return string(b), nil + return string(b), exitNum, nil } } -func setDynamic(block []rune, args []string, fileRef *ref.File, dataType string) func(interface{}) error { - return func(value interface{}) error { - //if !types.IsBlock([]byte(stringblock)) { - // return nil, errors.New("Dynamic config reader is not a code block") - //} +func setDynamic(block []rune, args []string, fileRef *ref.File, dataType string) func(interface{}) (int, error) { + return func(value interface{}) (int, error) { block = block[1 : len(block)-1] fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_NEW_MODULE | lang.F_CREATE_STDIN) fork.Name.Set("config") @@ -48,24 +40,20 @@ func setDynamic(block []rune, args []string, fileRef *ref.File, dataType string) fork.FileRef = fileRef s, err := types.ConvertGoType(value, types.String) if err != nil { - return err + return 1, err } fork.Stdin.SetDataType(dataType) _, err = fork.Stdin.Write([]byte(s.(string))) if err != nil { - return err + return 1, err } exitNum, err := fork.Execute(block) - if err != nil { - return errors.New("Dynamic config code could not compile: " + err.Error()) - } - if exitNum != 0 && debug.Enabled { - lang.ShellProcess.Stderr.Writeln([]byte("Dynamic config returned a none zero exit number." + utils.NewLineString)) + return exitNum, fmt.Errorf("dynamic config code could not compile: %s", err.Error()) } - return nil + return exitNum, nil } } diff --git a/builtins/core/config/dynamic_test.go b/builtins/core/config/dynamic_test.go new file mode 100644 index 000000000..643c7ba9c --- /dev/null +++ b/builtins/core/config/dynamic_test.go @@ -0,0 +1,47 @@ +package cmdconfig_test + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestDynamic(t *testing.T) { + const ( + readMsg = "returned from dynamic reader" + ) + + tests := []test.MurexTest{ + { + Block: ` + config define test-dynamic 00 %{ + Description: "This is only a test" + DataType: str + Global: true + Dynamic: { + Read: '{ + out "` + readMsg + `" + }' + Write: '{ + -> regexp m/^foobar$/ + }' + } + Default: "default string" + }`, + }, + { + Block: `config get test-dynamic 00`, + Stdout: readMsg + "\n\n", + }, + { + Block: `config set test-dynamic 00 foobar`, + }, + { + Block: `config set test-dynamic 00 baz`, + Stderr: `Error`, + ExitNum: 1, + }, + } + + test.RunMurexTestsRx(tests, t) +} diff --git a/builtins/core/config/eval.go b/builtins/core/config/eval.go index 8b97ec8be..fcc50337f 100644 --- a/builtins/core/config/eval.go +++ b/builtins/core/config/eval.go @@ -1,7 +1,7 @@ package cmdconfig import ( - "errors" + "fmt" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" @@ -37,7 +37,7 @@ func evalConfig(p *lang.Process) error { _, err = fork.Stdin.Write([]byte(v.(string))) if err != nil { - return errors.New("Couldn't write to eval's stdin: " + err.Error()) + return fmt.Errorf("couldn't write to eval's stdin: %s", err.Error()) } p.ExitNum, err = fork.Execute(block) diff --git a/builtins/core/config/eval_test.go b/builtins/core/config/eval_test.go new file mode 100644 index 000000000..1ba045400 --- /dev/null +++ b/builtins/core/config/eval_test.go @@ -0,0 +1,33 @@ +package cmdconfig_test + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestEval(t *testing.T) { + tests := []test.MurexTest{ + { + Block: ` + config define test-eval 00 %{ + Description: "This is only a test" + DataType: json + Global: true + Default: %{foo: bar, hello: world} + }`, + }, + { + Block: `config get test-eval 00`, + Stdout: `{"foo":"bar","hello":"world"}`, + }, + { + Block: ` + config eval test-eval 00 { -> alter /foo baz } + config get test-eval 00`, + Stdout: `{"foo":"baz","hello":"world"}`, + }, + } + + test.RunMurexTestsRx(tests, t) +} diff --git a/config/config.go b/config/config.go index 38f7119cb..2a334f25b 100644 --- a/config/config.go +++ b/config/config.go @@ -15,7 +15,7 @@ var InitConf = newGlobal() // Properties is the Config defaults and descriptions type Properties struct { Description string - Default interface{} + Default any DataType string Options []string Global bool @@ -24,34 +24,39 @@ type Properties struct { FileRefDef *ref.File } +type getDynamicT func() (any, int, error) +type setDynamicT func(any) (int, error) + // DynamicProperties is used for dynamic values written in murex type DynamicProperties struct { Read string Write string - GetDynamic func() (interface{}, error) `json:"-"` - SetDynamic func(interface{}) error `json:"-"` + GetDynamic getDynamicT `json:"-"` + SetDynamic setDynamicT `json:"-"` } // GoFuncProperties are used for dynamic values written in Go type GoFuncProperties struct { - Read func() (interface{}, error) `json:"-"` - Write func(interface{}) error `json:"-"` + Read func() (any, error) `json:"-"` + Write func(any) error `json:"-"` } // Config is used to store all the configuration settings, `config`, in a thread-safe API type Config struct { mutex sync.RWMutex - properties map[string]map[string]Properties // This will be the main configuration metadata for each configuration option - fileRefSet map[string]map[string]*ref.File // This is separate from Properties because it gets updated more frequently (eg custom setters) - values map[string]map[string]interface{} // This stores the values when no custom getter and setter have been defined + properties map[string]map[string]Properties // This will be the main configuration metadata for each configuration option + fileRefSet map[string]map[string]*ref.File // This is separate from Properties because it gets updated more frequently (eg custom setters) + values map[string]map[string]any // This stores the values when no custom getter and setter have been defined global *Config } +const errNonZeroExit = "non-zero exit number: %d" + func newGlobal() *Config { conf := new(Config) conf.properties = make(map[string]map[string]Properties) conf.fileRefSet = make(map[string]map[string]*ref.File) - conf.values = make(map[string]map[string]interface{}) + conf.values = make(map[string]map[string]any) return conf } @@ -59,7 +64,7 @@ func newConfiguration(global *Config) *Config { conf := new(Config) conf.properties = make(map[string]map[string]Properties) conf.fileRefSet = make(map[string]map[string]*ref.File) - conf.values = make(map[string]map[string]interface{}) + conf.values = make(map[string]map[string]any) conf.global = global return conf } @@ -87,13 +92,13 @@ func (conf *Config) ExistsAndGlobal(app, key string) (exists, global bool) { // app == tooling name // key == name of setting // dataType == what `types.dataType` to cast the return value into -func (conf *Config) Get(app, key, dataType string) (interface{}, error) { +func (conf *Config) Get(app, key, dataType string) (any, error) { v, _, err := conf.GetFileRef(app, key, dataType) return v, err } // GetFileRef retrieves a setting from the Config. Returns an interface{} for the value and err for any failures -func (conf *Config) GetFileRef(app, key, dataType string) (interface{}, *ref.File, error) { +func (conf *Config) GetFileRef(app, key, dataType string) (any, *ref.File, error) { conf.mutex.RLock() if conf.global != nil && conf.values[app] != nil && conf.values[app][key] != nil { @@ -114,18 +119,22 @@ func (conf *Config) GetFileRef(app, key, dataType string) (interface{}, *ref.Fil } var ( - v interface{} + v any + exitNum int err error fileRef = conf.fileRefSet[app][key] ) switch { case conf.properties[app][key].Dynamic.GetDynamic != nil: - v, err = conf.properties[app][key].Dynamic.GetDynamic() + v, exitNum, err = conf.properties[app][key].Dynamic.GetDynamic() conf.mutex.RUnlock() if err != nil { return nil, nil, err } + if exitNum != 0 { + return nil, nil, fmt.Errorf(errNonZeroExit, exitNum) + } case conf.properties[app][key].GoFunc.Read != nil: v, err = conf.properties[app][key].GoFunc.Read() @@ -151,7 +160,7 @@ func (conf *Config) GetFileRef(app, key, dataType string) (interface{}, *ref.Fil // app == tooling name // key == name of setting // value == the setting itself -func (conf *Config) Set(app string, key string, value interface{}, fileRef *ref.File) error { +func (conf *Config) Set(app string, key string, value any, fileRef *ref.File) error { // first check if we're in a global, and whether we should be if conf.global != nil { exists, global := conf.global.ExistsAndGlobal(app, key) @@ -172,31 +181,38 @@ func (conf *Config) Set(app string, key string, value interface{}, fileRef *ref. switch { case conf.properties[app][key].Dynamic.SetDynamic != nil: conf.mutex.Unlock() - err := conf.properties[app][key].Dynamic.SetDynamic(value) - if err == nil { - conf.mutex.Lock() - conf.fileRefSet[app][key] = fileRef - conf.mutex.Unlock() + exitNum, err := conf.properties[app][key].Dynamic.SetDynamic(value) + if err != nil { + return err + } + if exitNum != 0 { + return fmt.Errorf(errNonZeroExit, exitNum) } - return err + + conf.mutex.Lock() + conf.fileRefSet[app][key] = fileRef + conf.mutex.Unlock() + return nil case conf.properties[app][key].GoFunc.Write != nil: conf.mutex.Unlock() err := conf.properties[app][key].GoFunc.Write(value) - if err == nil { - conf.mutex.Lock() - conf.fileRefSet[app][key] = fileRef - conf.mutex.Unlock() + if err != nil { + return err } - return err + + conf.mutex.Lock() + conf.fileRefSet[app][key] = fileRef + conf.mutex.Unlock() + return nil default: if len(conf.values) == 0 { - conf.values = make(map[string]map[string]interface{}) + conf.values = make(map[string]map[string]any) conf.fileRefSet = make(map[string]map[string]*ref.File) } if len(conf.values[app]) == 0 { - conf.values[app] = make(map[string]interface{}) + conf.values[app] = make(map[string]any) conf.fileRefSet[app] = make(map[string]*ref.File) } @@ -254,7 +270,7 @@ func (conf *Config) Define(app string, key string, properties Properties) { if conf.properties[app] == nil { conf.properties[app] = make(map[string]Properties) conf.fileRefSet[app] = make(map[string]*ref.File) - conf.values[app] = make(map[string]interface{}) + conf.values[app] = make(map[string]any) } // don't set the value to the default if it's a dynamic property @@ -270,17 +286,17 @@ func (conf *Config) Define(app string, key string, properties Properties) { // DumpRuntime returns an object based on Config which is optimised for JSON // serialisation for the `runtime --config` CLI command -func (conf *Config) DumpRuntime() (obj map[string]map[string]map[string]interface{}) { +func (conf *Config) DumpRuntime() (obj map[string]map[string]map[string]any) { if conf.global != nil { return conf.global.DumpRuntime() } conf.mutex.RLock() - obj = make(map[string]map[string]map[string]interface{}) + obj = make(map[string]map[string]map[string]any) for app := range conf.properties { - obj[app] = make(map[string]map[string]interface{}) + obj[app] = make(map[string]map[string]any) for key := range conf.properties[app] { - obj[app][key] = make(map[string]interface{}) + obj[app][key] = make(map[string]any) obj[app][key]["Description"] = conf.properties[app][key].Description obj[app][key]["Data-Type"] = conf.properties[app][key].DataType obj[app][key]["Default"] = conf.properties[app][key].Default @@ -315,17 +331,17 @@ func (conf *Config) DumpRuntime() (obj map[string]map[string]map[string]interfac // DumpConfig returns an object based on Config which is optimised for JSON // serialisation for the `config` CLI command -func (conf *Config) DumpConfig() (obj map[string]map[string]map[string]interface{}) { +func (conf *Config) DumpConfig() (obj map[string]map[string]map[string]any) { if conf.global != nil { return conf.global.DumpConfig() } conf.mutex.RLock() - obj = make(map[string]map[string]map[string]interface{}) + obj = make(map[string]map[string]map[string]any) for app := range conf.properties { - obj[app] = make(map[string]map[string]interface{}) + obj[app] = make(map[string]map[string]any) for key := range conf.properties[app] { - obj[app][key] = make(map[string]interface{}) + obj[app][key] = make(map[string]any) obj[app][key]["Description"] = conf.properties[app][key].Description obj[app][key]["Data-Type"] = conf.properties[app][key].DataType obj[app][key]["Default"] = conf.properties[app][key].Default From c1288a8b9afbb73d19daa7f66b3636068cce0f89 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 09:28:03 +0100 Subject: [PATCH 006/142] new builtin: `~>` --- app/app.go | 2 +- builtins/core/datatools/alter.go | 36 ++++++++++++++++++++++++++ builtins/core/datatools/alter_doc.yaml | 20 ++++++++++++++ builtins/docs/summaries.go | 2 ++ docs/commands/alter.md | 24 +++++++++++++++++ lang/expressions/exp04.go | 20 ++++++++++++-- lang/expressions/parse_block.go | 24 +++++++++++++---- lang/expressions/parse_statement.go | 31 ++++++++++++++++++---- version.svg | 2 +- 9 files changed, 147 insertions(+), 14 deletions(-) diff --git a/app/app.go b/app/app.go index 0e0b6ac3a..6cbcf4ca6 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1000 + Revision = 1100 ) // Copyright is the copyright owner string diff --git a/builtins/core/datatools/alter.go b/builtins/core/datatools/alter.go index 383549fb4..e559a6d35 100644 --- a/builtins/core/datatools/alter.go +++ b/builtins/core/datatools/alter.go @@ -5,10 +5,12 @@ import ( "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/alter" + "github.com/lmorg/murex/utils/json" ) func init() { lang.DefineMethod("alter", cmdAlter, types.Unmarshal, types.Marshal) + lang.DefineMethod("~>", opMerge, types.Unmarshal, types.Marshal) defaults.AppendProfile(` autocomplete: set alter { [{ @@ -139,3 +141,37 @@ func cmdAlter(p *lang.Process) error { _, err = p.Stdout.Write(b) return err } + +func opMerge(p *lang.Process) error { + dt := p.Stdin.GetDataType() + p.Stdout.SetDataType(dt) + + if err := p.ErrIfNotAMethod(); err != nil { + return err + } + + stdin, err := lang.UnmarshalData(p, dt) + if err != nil { + return err + } + + b := p.Parameters.ByteAll() + var merge any + err = json.UnmarshalMurex(b, &merge) + if err != nil { + return err + } + + v, err := alter.Merge(p.Context, stdin, nil, merge) + if err != nil { + return err + } + + b, err = lang.MarshalData(p, dt, v) + if err != nil { + return err + } + + _, err = p.Stdout.Write(b) + return err +} diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index 76f1ba2f7..294fb98fa 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -20,6 +20,8 @@ Usage: |- ``` -> alter [ -m | --merge | -s | --sum ] /path value -> + + ~> value -> ``` Examples: |- ### Altering an objects value @@ -143,12 +145,30 @@ ``` Marshallers are enabled at compile time from the `builtins/data-types` directory. + + ### Alter operator + + `~>` is a synonym for `alter --merge /`, for example: + + ``` + » tout json %[1 2 3] ~> %[4 5 6] + [ + 1, + 2, + 3, + 4, + 5, + 6 + ] + ``` Flags: "--merge": Merge data structures rather than overwrite "-m" : Alias for `--merge` "--sum" : Sum values in a map, merge items in an array "-s" : Alias for `--sum` Synonyms: + - alter + - "~>" Related: - item-index - element diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 99e9772b9..f62eb1ee8 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -428,6 +428,7 @@ func init() { "alias": "alias", "!alias": "alias", "alter": "alter", + "~>": "alter", "and": "and", "!and": "and", "append": "append", @@ -650,6 +651,7 @@ func init() { "commands/alias": "commands/alias", "commands/!alias": "commands/alias", "commands/alter": "commands/alter", + "commands/~>": "commands/alter", "commands/and": "commands/and", "commands/!and": "commands/and", "commands/append": "commands/append", diff --git a/docs/commands/alter.md b/docs/commands/alter.md index dc52ff50a..bd8120fcd 100644 --- a/docs/commands/alter.md +++ b/docs/commands/alter.md @@ -20,6 +20,8 @@ The **value** must always be supplied as JSON. ``` -> alter [ -m | --merge | -s | --sum ] /path value -> + + ~> value -> ``` ## Examples @@ -159,6 +161,28 @@ runtime --marshallers Marshallers are enabled at compile time from the `builtins/data-types` directory. +### Alter operator + +`~>` is a synonym for `alter --merge /`, for example: + +``` +» tout json %[1 2 3] ~> %[4 5 6] +[ + 1, + 2, + 3, + 4, + 5, + 6 +] +``` + +## Synonyms + +* `alter` +* `~>` + + ## See Also * [`<~` Assign Or Merge](../parser/assign-or-merge.md): diff --git a/lang/expressions/exp04.go b/lang/expressions/exp04.go index e11390543..fd3295e59 100644 --- a/lang/expressions/exp04.go +++ b/lang/expressions/exp04.go @@ -44,6 +44,8 @@ func expSubtract(tree *ParserT) error { }) } +const errCannotMergeWith = "cannot merge %s with %s: %s" + func expMergeInto(tree *ParserT) error { leftNode, rightNode, err := tree.getLeftAndRightSymbols() if err != nil { @@ -59,10 +61,24 @@ func expMergeInto(tree *ParserT) error { return err } - merged, err := alter.Merge(tree.p.Context, right.Value, nil, left.Value) + if left.Primitive != primitives.Array && left.Primitive != primitives.Object { + return raiseError(tree.expression, leftNode, 0, fmt.Sprintf( + errCannotMergeWith, + right.Primitive.String(), left.Primitive.String(), + "left side needs to be an array or object")) + } + + if right.Primitive != primitives.Array && right.Primitive != primitives.Object { + return raiseError(tree.expression, rightNode, 0, fmt.Sprintf( + errCannotMergeWith, + right.Primitive.String(), left.Primitive.String(), + "right side needs to be an array or object")) + } + + merged, err := alter.Merge(tree.p.Context, left.Value, nil, right.Value) if err != nil { return raiseError(tree.expression, leftNode, 0, fmt.Sprintf( - "cannot perform merge '%s' into '%s': %s", + errCannotMergeWith, right.Value, left.Value, err.Error())) } diff --git a/lang/expressions/parse_block.go b/lang/expressions/parse_block.go index 56f062fa1..0dcb4dc8e 100644 --- a/lang/expressions/parse_block.go +++ b/lang/expressions/parse_block.go @@ -293,12 +293,26 @@ func (blk *BlockT) ParseBlock() error { case '>': switch { case blk.nextChar() == '>': - /*if len(blk.Functions) > 0 && - len(blk.Functions[len(blk.Functions)-1].Raw) == 0 && - !blk.Functions[len(blk.Functions)-1].Properties.Method() { - panic("ugh") - }*/ + err := blk.append(tree, fn.P_PIPE_OUT, fn.P_FOLLOW_ON|fn.P_METHOD) + if err != nil { + return err + } + tree, err = blk.parseStatementWithKnownCommand('>', '>') + if err != nil { + return err + } + default: + tree = NewParser(nil, blk.expression[blk.charPos:], blk.charPos-1) + newPos, err := tree.preParser() + if err != nil { + return err + } + blk.charPos += newPos + } + case '~': + switch { + case blk.nextChar() == '>': err := blk.append(tree, fn.P_PIPE_OUT, fn.P_FOLLOW_ON|fn.P_METHOD) if err != nil { return err diff --git a/lang/expressions/parse_statement.go b/lang/expressions/parse_statement.go index 15abb9499..a56a6f789 100644 --- a/lang/expressions/parse_statement.go +++ b/lang/expressions/parse_statement.go @@ -156,13 +156,34 @@ func (tree *ParserT) parseStatement(exec bool) error { } case '~': - // tilde tree.statement.validFunction = false - home, err := tree.parseVarTilde(exec) - if err != nil { - return err + switch tree.nextChar() { + case '>': + // redirect (merge into) + if len(tree.statement.command) == 0 && len(tree.statement.paramTemp) == 0 { + appendToParam(tree, r, '>') + tree.charPos++ + if err := tree.nextParameter(); err != nil { + return err + } + } else { + if len(tree.statement.paramTemp) > 0 { + tree.statement.paramTemp = tree.statement.paramTemp[:len(tree.statement.paramTemp)-2] + if err := tree.nextParameter(); err != nil { + return err + } + } + tree.charPos-- + return nil + } + default: + // tilde + home, err := tree.parseVarTilde(exec) + if err != nil { + return err + } + appendToParam(tree, []rune(home)...) } - appendToParam(tree, []rune(home)...) case '<': tree.statement.validFunction = false diff --git a/version.svg b/version.svg index a74827684..3fe8c64a5 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1000Version6.3.1000 +Version: 6.3.1100Version6.3.1100 From cb1d58ed083181604eb4d5712397d767dbd754e1 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 18:03:25 +0100 Subject: [PATCH 007/142] #850 nil pointer error in `alter --merge` --- app/app.go | 2 +- builtins/core/config/config_doc.inc.md | 17 ++- builtins/core/config/config_doc.yaml | 114 +++++++++++--------- builtins/core/datatools/alter_op_test.go | 19 ++++ docs/commands/config.md | 130 ++++++++++++----------- lang/expressions/parse_block_test.go | 11 ++ utils/alter/alter.go | 17 +-- utils/alter/alter_test.go | 13 +++ utils/alter/merge.go | 7 +- utils/alter/merge_test.go | 48 +++++++++ utils/alter/sum_test.go | 13 +++ version.svg | 2 +- 12 files changed, 259 insertions(+), 134 deletions(-) create mode 100644 builtins/core/datatools/alter_op_test.go diff --git a/app/app.go b/app/app.go index 6cbcf4ca6..37952c433 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1100 + Revision = 1200 ) // Copyright is the copyright owner string diff --git a/builtins/core/config/config_doc.inc.md b/builtins/core/config/config_doc.inc.md index 0fe7f9c61..3d3735d70 100644 --- a/builtins/core/config/config_doc.inc.md +++ b/builtins/core/config/config_doc.inc.md @@ -1,9 +1,10 @@ -The directives for `config define` are listed below. +> This section relates to creating custom configs via `config define`. +> You do not need to refer to this for any regular usage of `config`. {{ if env "DOCGEN_TARGET=" }}
- [DataType](#datatype) -- [Description"](#description) +- [Description](#description) - [Global](#global) - [Default](#default) - [Options](#options) @@ -14,10 +15,6 @@ The directives for `config define` are listed below.
{{ end }} -``` -"DirectiveName": json data-type (default value) -``` - Where "default value" is what will be auto-populated if you don't include that directive (or "required" if the directive must be included). @@ -27,7 +24,7 @@ directive (or "required" if the directive must be included). This is the Murex data-type for the value. -### Description" +### Description > Value: `str` (required) @@ -40,9 +37,9 @@ enabling the discoverability of settings within Murex. This defines whether this setting is global or scoped. -All **Dynamic** settings _must_ also be **Global**. This is because **Dynamic** -settings rely on a state that likely isn't scoped (eg the contents of a config -file). +All **Dynamic** config must also be **Global**. This is because **Dynamic** +config rely on a state that likely isn't scoped (eg the contents of a file on +disk or environmental variable). ### Default diff --git a/builtins/core/config/config_doc.yaml b/builtins/core/config/config_doc.yaml index 0fd2995bf..6785fd60f 100644 --- a/builtins/core/config/config_doc.yaml +++ b/builtins/core/config/config_doc.yaml @@ -10,84 +10,93 @@ `config` command. This means any preferences and/or runtime config becomes centralised and discoverable. - Usage: |- - List all settings: + ## Terminology + The following terms have special means with regards to `config`: + + ### app + + _app_ refers to a grouped category of settings. For example the name of an + integration or builtin. + + Other _app_ names include + + * `shell`: for "global" (system wide) Murex settings + * `proc`: for scoped Murex settings + * `http`: for settings that are applied to any processes which use the builtin + HTTP user agent (eg `open`, `get`, `getfile`, `post`) + * `test`: settings for Murex's test frameworks + * `index`: settings for `[` (index) + + ### key + + _key_ refers to the config setting itself. For example the _app_ might be `http` + but the _key_ might be `timeout` - where the _key_, in this instance, holds the + value for how long any HTTP user agents might wait before timing out. + + ### value + + _value_ is the actual value of a setting. So the value for _app_: `http`, _key_: + `timeout` might be `10`. eg + ``` - config -> + » config get http timeout + 10 ``` - - Get a setting: + Usage: |- + ### Get value ``` config get app key -> ``` - Set a setting: + ### Set value ``` - config set app key value - - -> config set app key - - config eval app key { -> code-block } + config set app key value + -> config set app key + config eval app key { code-block } ``` - Define a new config setting: + ### Reset to default ``` - config define app key { json } + !config app key + config default app key ``` - Reset a setting to it's default value: + ### Define custom configs ``` - !config app key - - config default app key + config define app key { json } ``` Examples: |- + ### eval + Using `eval` to append to an array (in this instance, adding a function - name to the list of "safe" commands) + name to the list of "safe" commands): ``` - » function foobar { -> match foobar } - » config eval shell safe-commands { -> append foobar } + » config eval shell safe-commands { -> append function-name } ``` - Flags: - Detail: |- - With regards to `config`, the following terms are applied: - - ### app - - This refers to a grouped category of settings. For example the name of a built - in. - - Other app names include - - * `shell`: for "global" (system wide) Murex settings - * `proc`: for scoped Murex settings - * `http`: for settings that are applied to any processes which use the builtin - HTTP user agent (eg `open`, `get`, `getfile`, `post`) - * `test`: settings for Murex's test frameworks - * `index`: settings for `[` (index) - - ### key - This refers to the config setting itself. For example the "app" might be `http` - but the "key" might be `timeout` - where the "key", in this instance, holds the - value for how long any HTTP user agents might wait before timing out. - - ### value - - Value is the actual value of a setting. So the value for "app": `http`, "key": - `timeout` might be `10`. eg + You could also use the `~>` operator too: ``` - » config get http timeout - 10 + » config eval shell safe-commands { ~> %[function-name] } ``` - + Flags: + get: >- + Output the currently held config _value_ without changing it + set: >- + Change the _value_ of an _app_'s _key_. `set` does not print any output + default: >- + Reset a the value of _app_'s _key_ to its default _value_ + (the default _value_ is defined by the same process that defines the config field) + define: >- + Allows you to create custom config options. + See {{bookmark "Custom Config Directives" "config" "custom-config-directives"}} to learn how to use `define` + Detail: |- ### scope Settings in `config`, by default, are scoped per function and module. Any @@ -95,14 +104,12 @@ child functions that then change the settings will only change settings for it's own function and not the parent caller. - Please note that `config` settings are scoped differently to local variables. - ### global Global settings defined inside a function will affect settings queried inside another executing function (same concept as global variables). - ## Directives + ## Custom Config Directives {{ include "builtins/core/config/config_doc.inc.md" }} Synonyms: @@ -121,4 +128,5 @@ - item-index - element - create-object + - alter diff --git a/builtins/core/datatools/alter_op_test.go b/builtins/core/datatools/alter_op_test.go new file mode 100644 index 000000000..3363a0783 --- /dev/null +++ b/builtins/core/datatools/alter_op_test.go @@ -0,0 +1,19 @@ +package datatools_test + +import ( + "testing" + + _ "github.com/lmorg/murex/builtins/core/io" + "github.com/lmorg/murex/test" +) + +func TestAlterOp(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `tout json %{a:1, b:2, c:3} ~> %{b:4}`, + Stdout: `{"a":1,"b":4,"c":3}`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/docs/commands/config.md b/docs/commands/config.md index 39f833679..0bc177666 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -9,87 +9,98 @@ variables, Murex instead supports a registry of config defined via the `config` command. This means any preferences and/or runtime config becomes centralised and discoverable. -## Usage +## Terminology -List all settings: +The following terms have special means with regards to `config`: -``` -config -> -``` +### app -Get a setting: +_app_ refers to a grouped category of settings. For example the name of an +integration or builtin. + +Other _app_ names include -``` -config get app key -> -``` +* `shell`: for "global" (system wide) Murex settings +* `proc`: for scoped Murex settings +* `http`: for settings that are applied to any processes which use the builtin + HTTP user agent (eg `open`, `get`, `getfile`, `post`) +* `test`: settings for Murex's test frameworks +* `index`: settings for `[` (index) + +### key -Set a setting: +_key_ refers to the config setting itself. For example the _app_ might be `http` +but the _key_ might be `timeout` - where the _key_, in this instance, holds the +value for how long any HTTP user agents might wait before timing out. + +### value + +_value_ is the actual value of a setting. So the value for _app_: `http`, _key_: +`timeout` might be `10`. eg ``` -config set app key value +» config get http timeout +10 +``` - -> config set app key +## Usage + +### Get value -config eval app key { -> code-block } +``` +config get app key -> ``` -Define a new config setting: +### Set value ``` -config define app key { json } + config set app key value + -> config set app key + config eval app key { code-block } ``` -Reset a setting to it's default value: +### Reset to default ``` !config app key - config default app key ``` -## Examples - -Using `eval` to append to an array (in this instance, adding a function -name to the list of "safe" commands) +### Define custom configs ``` -» function foobar { -> match foobar } -» config eval shell safe-commands { -> append foobar } +config define app key { json } ``` -## Detail +## Examples -With regards to `config`, the following terms are applied: +### eval -### app +Using `eval` to append to an array (in this instance, adding a function +name to the list of "safe" commands): -This refers to a grouped category of settings. For example the name of a built -in. - -Other app names include +``` +» config eval shell safe-commands { -> append function-name } +``` -* `shell`: for "global" (system wide) Murex settings -* `proc`: for scoped Murex settings -* `http`: for settings that are applied to any processes which use the builtin - HTTP user agent (eg `open`, `get`, `getfile`, `post`) -* `test`: settings for Murex's test frameworks -* `index`: settings for `[` (index) +You could also use the `~>` operator too: -### key - -This refers to the config setting itself. For example the "app" might be `http` -but the "key" might be `timeout` - where the "key", in this instance, holds the -value for how long any HTTP user agents might wait before timing out. +``` +» config eval shell safe-commands { ~> %[function-name] } +``` -### value +## Flags -Value is the actual value of a setting. So the value for "app": `http`, "key": -`timeout` might be `10`. eg +* `default` + Reset a the value of _app_'s _key_ to its default _value_ (the default _value_ is defined by the same process that defines the config field) +* `define` + Allows you to create custom config options. See [Custom Config Directives](/docs/commands/config.md#custom-config-directives) to learn how to use `define` +* `get` + Output the currently held config _value_ without changing it +* `set` + Change the _value_ of an _app_'s _key_. `set` does not print any output -``` -» config get http timeout -10 -``` +## Detail ### scope @@ -98,21 +109,20 @@ functions called will inherit the settings of it's caller parent. However any child functions that then change the settings will only change settings for it's own function and not the parent caller. -Please note that `config` settings are scoped differently to local variables. - ### global Global settings defined inside a function will affect settings queried inside another executing function (same concept as global variables). -## Directives +## Custom Config Directives -The directives for `config define` are listed below. +> This section relates to creating custom configs via `config define`. +> You do not need to refer to this for any regular usage of `config`.
- [DataType](#datatype) -- [Description"](#description) +- [Description](#description) - [Global](#global) - [Default](#default) - [Options](#options) @@ -123,10 +133,6 @@ The directives for `config define` are listed below.
-``` -"DirectiveName": json data-type (default value) -``` - Where "default value" is what will be auto-populated if you don't include that directive (or "required" if the directive must be included). @@ -136,7 +142,7 @@ directive (or "required" if the directive must be included). This is the Murex data-type for the value. -### Description" +### Description > Value: `str` (required) @@ -149,9 +155,9 @@ enabling the discoverability of settings within Murex. This defines whether this setting is global or scoped. -All **Dynamic** settings _must_ also be **Global**. This is because **Dynamic** -settings rely on a state that likely isn't scoped (eg the contents of a config -file). +All **Dynamic** config must also be **Global**. This is because **Dynamic** +config rely on a state that likely isn't scoped (eg the contents of a file on +disk or environmental variable). ### Default @@ -235,6 +241,8 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure +* [`alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [`append`](../commands/append.md): Add data to the end of an array * [`event`](../commands/event.md): diff --git a/lang/expressions/parse_block_test.go b/lang/expressions/parse_block_test.go index 3bc00384f..8618d7638 100644 --- a/lang/expressions/parse_block_test.go +++ b/lang/expressions/parse_block_test.go @@ -376,3 +376,14 @@ func TestParseBlockArrayPanicBugFix(t *testing.T) { test.RunMurexTestsRx(tests, t) } + +func TestAlterOp(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `tout json %{a:1, b:2, c:3} ~> %{b:4}`, + Stdout: `{"a":1,"b":4,"c":3}`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/utils/alter/alter.go b/utils/alter/alter.go index 93a7176bc..a1ebd12aa 100644 --- a/utils/alter/alter.go +++ b/utils/alter/alter.go @@ -6,6 +6,7 @@ import ( "fmt" "strconv" + "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/types" ) @@ -17,7 +18,7 @@ const ( // Alter a data structure. Requires a path (pre-split) and new structure as a // JSON string. A more seasoned developer will see plenty of room for -// optimisation however this function was largely thrown together in a "let's +// optimization however this function was largely thrown together in a "let's // create something that works first and worry about performance later" kind of // sense (much like a lot of murex's code base). That being said, I will accept // any pull requests from other developers wishing to improve this - or other - @@ -56,12 +57,14 @@ const ( ) func loop(ctx context.Context, v interface{}, i int, path []string, new *interface{}, action int) (ret interface{}, err error) { - defer func() { - r := recover() - if r != nil { - err = fmt.Errorf("unhandled error in type conversion: %v", r) - } - }() + if !debug.Enabled { + defer func() { + r := recover() + if r != nil { + err = fmt.Errorf("unhandled error in type conversion: %v", r) + } + }() + } select { case <-ctx.Done(): diff --git a/utils/alter/alter_test.go b/utils/alter/alter_test.go index 6cfaa6825..8510e0715 100644 --- a/utils/alter/alter_test.go +++ b/utils/alter/alter_test.go @@ -14,6 +14,7 @@ type plan struct { path string change string expected string + error bool } func alterTest(t *testing.T, test *plan) { @@ -331,3 +332,15 @@ func TestUpdateArrayFloat(t *testing.T) { alterTest(t, &test) } + +// https://github.com/lmorg/murex/issues/850 +func TestUpdateIssue850(t *testing.T) { + test := plan{ + original: `{}`, + path: "/", + change: `{ "key": [{"hello": "world"}] }`, + expected: `{"":{"key":[{"hello":"world"}]}}`, + } + + alterTest(t, &test) +} diff --git a/utils/alter/merge.go b/utils/alter/merge.go index 90d6a4936..17721b74f 100644 --- a/utils/alter/merge.go +++ b/utils/alter/merge.go @@ -59,7 +59,12 @@ func mergeMap(v interface{}, new *interface{}) (ret interface{}, err error) { case string, int, float64, bool, nil: ret.(map[string]interface{})[key] = t default: - oldKind := reflect.TypeOf(ret.(map[string]interface{})[key]).Kind() + mapVal, ok := ret.(map[string]interface{})[key] + if !ok { + ret.(map[string]interface{})[key] = t + return + } + oldKind := reflect.TypeOf(mapVal).Kind() newKind := reflect.TypeOf(val).Kind() switch { case oldKind != newKind: diff --git a/utils/alter/merge_test.go b/utils/alter/merge_test.go index 95c0ec1dd..f109bfccf 100644 --- a/utils/alter/merge_test.go +++ b/utils/alter/merge_test.go @@ -369,3 +369,51 @@ func TestMergeNestedMapMap(t *testing.T) { mergeTest(t, &test) } + +// https://github.com/lmorg/murex/issues/850 +func TestMergeIssue850_1(t *testing.T) { + test := plan{ + original: `{}`, + path: "/", + change: `{ "key": [{"hello": "world"}] }`, + expected: `{"key":[{"hello":"world"}]}`, + } + + mergeTest(t, &test) +} + +// https://github.com/lmorg/murex/issues/850 +func TestMergeIssue850_2(t *testing.T) { + test := plan{ + original: `{"key":[{"hello":"world"}]}`, + path: "/", + change: `{ "key": [{"hello": "earth"}] }`, + expected: `{"key":[{"hello":"world"},{"hello":"earth"}]}`, + } + + mergeTest(t, &test) +} + +// https://github.com/lmorg/murex/issues/850 +func TestMergeIssue850_3(t *testing.T) { + test := plan{ + original: `{"key":[{"hello":"world"}]}`, + path: "/", + change: `{ "key": [] }`, + expected: `{"key":[{"hello":"world"}]}`, + } + + mergeTest(t, &test) +} + +// https://github.com/lmorg/murex/issues/850 +func TestMergeIssue850_4(t *testing.T) { + test := plan{ + original: `{"key":[{"hello":"world"}]}`, + path: "/", + change: `{ "key2": [{"hello":"earth"}] }`, + expected: `{"key":[{"hello":"world"}],"key2":[{"hello":"earth"}]}`, + } + + mergeTest(t, &test) +} diff --git a/utils/alter/sum_test.go b/utils/alter/sum_test.go index de05eab6d..40e090ab5 100644 --- a/utils/alter/sum_test.go +++ b/utils/alter/sum_test.go @@ -154,3 +154,16 @@ func TestSumMapInterface(t *testing.T) { sumTest(t, &test) } + +// https://github.com/lmorg/murex/issues/850 +func TestSumIssue850(t *testing.T) { + test := plan{ + original: `{}`, + path: "/", + change: `{ "key": [{"hello": "world"}] }`, + //expected: `{"key":[{"hello":"world"}]}`, + expected: ``, // should error + } + + sumTest(t, &test) +} diff --git a/version.svg b/version.svg index 3fe8c64a5..17a5c44dc 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1100Version6.3.1100 +Version: 6.3.1200Version6.3.1200 From ae8ac32dea1f94c350d235a2564ea454aa3775ce Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 18:14:03 +0100 Subject: [PATCH 008/142] #850 alter: fix failing test --- utils/alter/alter_test.go | 1 + utils/alter/sum_test.go | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/utils/alter/alter_test.go b/utils/alter/alter_test.go index 8510e0715..aca2c48f9 100644 --- a/utils/alter/alter_test.go +++ b/utils/alter/alter_test.go @@ -344,3 +344,4 @@ func TestUpdateIssue850(t *testing.T) { alterTest(t, &test) } + diff --git a/utils/alter/sum_test.go b/utils/alter/sum_test.go index 40e090ab5..ff2591803 100644 --- a/utils/alter/sum_test.go +++ b/utils/alter/sum_test.go @@ -19,14 +19,16 @@ func sumTest(t *testing.T, test *plan) { } var expV interface{} - if err := json.Unmarshal([]byte(test.expected), &expV); err != nil { - panic(err) - } - b, err := json.Marshal(expV) - if err != nil { - panic(err) + if !test.error { + if err := json.Unmarshal([]byte(test.expected), &expV); err != nil { + panic(err) + } + b, err := json.Marshal(expV) + if err != nil { + panic(err) + } + test.expected = string(b) } - test.expected = string(b) var old interface{} err = json.Unmarshal([]byte(test.original), &old) @@ -43,7 +45,7 @@ func sumTest(t *testing.T, test *plan) { new := alter.StrToInterface(test.change) v, err := alter.Sum(context.TODO(), old, pathS, new) - if err != nil { + if (err != nil) != test.error { t.Error("Error received from alter.Sum()") t.Logf(" original: %s", test.original) t.Logf(" path: %s: %v", test.path, pathS) @@ -66,6 +68,9 @@ func sumTest(t *testing.T, test *plan) { return } + if test.error { + return + } if string(actual) != test.expected { t.Error("Expected does not match actual") t.Logf(" original: %s.(%T)", test.original, old) @@ -161,8 +166,7 @@ func TestSumIssue850(t *testing.T) { original: `{}`, path: "/", change: `{ "key": [{"hello": "world"}] }`, - //expected: `{"key":[{"hello":"world"}]}`, - expected: ``, // should error + error: true, } sumTest(t, &test) From bb27a0f8990dc4771fbfc775149fd4daccb401b8 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 20:26:11 +0100 Subject: [PATCH 009/142] integration: systemctl auto-completion --- builtins/docs/summaries.go | 4 -- docs/changelog/v2.7.md | 4 +- docs/commands/README.md | 2 - docs/commands/autoglob.md | 55 ----------------------- docs/user-guide/README.md | 2 - integrations/systemctl_linux.mx | 11 ++--- lang/expressions/noglob/autoglob_doc.yaml | 42 ----------------- 7 files changed, 8 insertions(+), 112 deletions(-) delete mode 100644 docs/commands/autoglob.md delete mode 100644 lang/expressions/noglob/autoglob_doc.yaml diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index f62eb1ee8..19adfd2e9 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -10,7 +10,6 @@ func init() { "2darray": "Create a 2D JSON array from multiple input sources", "namedpipe": "Reads from a Murex named pipe", "stdin": "Read the stdin belonging to the parent code block", - "autoglob": "Command prefix to expand globbing (deprecated)", "a": "A sophisticated yet simple way to build an array or list", "addheading": "Adds headings to a table", "alias": "Create an alias for a command", @@ -140,7 +139,6 @@ func init() { "commands/2darray": "Create a 2D JSON array from multiple input sources", "commands/namedpipe": "Reads from a Murex named pipe", "commands/stdin": "Read the stdin belonging to the parent code block", - "commands/autoglob": "Command prefix to expand globbing (deprecated)", "commands/a": "A sophisticated yet simple way to build an array or list", "commands/addheading": "Adds headings to a table", "commands/alias": "Create an alias for a command", @@ -422,7 +420,6 @@ func init() { "<>": "namedpipe", "read-named-pipe": "namedpipe", "": "stdin", - "autoglob": "autoglob", "a": "a", "addheading": "addheading", "alias": "alias", @@ -645,7 +642,6 @@ func init() { "commands/<>": "commands/namedpipe", "commands/read-named-pipe": "commands/namedpipe", "commands/": "commands/stdin", - "commands/autoglob": "commands/autoglob", "commands/a": "commands/a", "commands/addheading": "commands/addheading", "commands/alias": "commands/alias", diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index a93a5c249..1d9f86c30 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -82,8 +82,6 @@ Published: 15.05.2022 at 22:49 Special variables reserved by Murex * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes -* [`@g` (autoglob) ](../commands/autoglob.md): - Command prefix to expand globbing (deprecated) * [`config`](../commands/config.md): Query or define Murex runtime settings * [`event`](../commands/event.md): @@ -96,6 +94,8 @@ Published: 15.05.2022 at 22:49 `read` a line of input from the user and store as a variable * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [autoglob](../changelog/autoglob.md): +
diff --git a/docs/commands/README.md b/docs/commands/README.md index c8ef47ad0..20d2bbcb4 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -44,8 +44,6 @@ murex-docs trypipe Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`@g` (autoglob) ](../commands/autoglob.md): - Command prefix to expand globbing (deprecated) * [`a` (mkarray)](../commands/a.md): A sophisticated yet simple way to build an array or list * [`addheading` ](../commands/addheading.md): diff --git a/docs/commands/autoglob.md b/docs/commands/autoglob.md deleted file mode 100644 index 88939ae15..000000000 --- a/docs/commands/autoglob.md +++ /dev/null @@ -1,55 +0,0 @@ -# `@g` (autoglob) - -> Command prefix to expand globbing (deprecated) - -## Description - -**This feature is now deprecated and only applies to murex version 2:** - -By default Murex does not expand globbing (`*` and `?` wildcards) instead -encouraging the use of `g` (and similar) inside a subshell. While the aim of -this is to promote correctness, it can be a little annoying while working in -the interactive shell. For this reason you can prefix any command with `@g` to -enable Bash-like globbing. - -## Usage - -``` -@g command ... -``` - -## Examples - -``` -@g echo * -``` - -## Detail - -As of Murex `2.9` and above it is possible to enable automatic globbing in -the interactive shell without having to prefix the command with `@g` by -enabling the following `config` option: - -``` -config: set shell auto-glob true -``` - -It is enabled by default on from version 3.x onwards (and renamed to -`expand-glob`) - -## See Also - -* [Profile Files](../user-guide/profile.md): - A breakdown of the different files loaded on start up -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`f`](../commands/f.md): - Lists or filters file system objects (eg files) -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [`rx`](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) - -
- -This document was generated from [lang/expressions/noglob/autoglob_doc.yaml](https://github.com/lmorg/murex/blob/master/lang/expressions/noglob/autoglob_doc.yaml). \ No newline at end of file diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index ad0e373d6..52079330d 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -153,8 +153,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`@g` (autoglob) ](../commands/autoglob.md): - Command prefix to expand globbing (deprecated) * [`a` (mkarray)](../commands/a.md): A sophisticated yet simple way to build an array or list * [`addheading` ](../commands/addheading.md): diff --git a/integrations/systemctl_linux.mx b/integrations/systemctl_linux.mx index 10bd7899a..d2cd426e6 100644 --- a/integrations/systemctl_linux.mx +++ b/integrations/systemctl_linux.mx @@ -14,13 +14,13 @@ test unit private autocomplete.systemctl %{ StdoutIsArray: true } -function autocomplete.systemctl.flags { +private autocomplete.systemctl.flags { # Parses `systemctl --help` looking for flags then returns `autocomplete` config based on those flags cast json systemctl --help \ - -> regexp %(m/PATTERN/) \ + -> regexp %(m/UNIT/) \ -> tabulate --map --key-inc-hint \ -> formap key val { json <~ %{ @@ -36,7 +36,7 @@ function autocomplete.systemctl.flags { $json } -autocomplete set systemctl %[ +autocomplete = %[ { DynamicDesc: '{ systemctl --help \ @@ -54,8 +54,9 @@ autocomplete set systemctl %[ }' Optional: false AllowMultiple: false - FlagValues: ${ autocomplete.systemctl.flags } } ] -!function autocomplete.systemctl.flags \ No newline at end of file +tout json $autocomplete \ +-> alter /1/FlagValues fexec(private /builtin/integrations_systemctl_linux/autocomplete.systemctl.flags) \ +-> autocomplete set systemctl \ No newline at end of file diff --git a/lang/expressions/noglob/autoglob_doc.yaml b/lang/expressions/noglob/autoglob_doc.yaml deleted file mode 100644 index 9ddebed7e..000000000 --- a/lang/expressions/noglob/autoglob_doc.yaml +++ /dev/null @@ -1,42 +0,0 @@ -- DocumentID: autoglob - Title: >+ - `@g` (autoglob) - CategoryID: commands - Summary: >- - Command prefix to expand globbing (deprecated) - Description: |- - **This feature is now deprecated and only applies to murex version 2:** - - By default Murex does not expand globbing (`*` and `?` wildcards) instead - encouraging the use of `g` (and similar) inside a subshell. While the aim of - this is to promote correctness, it can be a little annoying while working in - the interactive shell. For this reason you can prefix any command with `@g` to - enable Bash-like globbing. - Usage: |- - ``` - @g command ... - ``` - Examples: |- - ``` - @g echo * - ``` - Detail: |- - As of Murex `2.9` and above it is possible to enable automatic globbing in - the interactive shell without having to prefix the command with `@g` by - enabling the following `config` option: - - ``` - config: set shell auto-glob true - ``` - - It is enabled by default on from version 3.x onwards (and renamed to - `expand-glob`) - Synonyms: - Related: - - g - - rx - - f - - config - - profile - - From 9ccefb524fc3ce89d26a30b2c47ceb8418d3c48d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 20:50:20 +0100 Subject: [PATCH 010/142] website: remove reference to autoglob --- docs/changelog/v2.7.md | 2 -- gen/changelog/v2.7_doc.yaml | 1 - 2 files changed, 3 deletions(-) diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index 1d9f86c30..2795d35ba 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -94,8 +94,6 @@ Published: 15.05.2022 at 22:49 `read` a line of input from the user and store as a variable * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [autoglob](../changelog/autoglob.md): -
diff --git a/gen/changelog/v2.7_doc.yaml b/gen/changelog/v2.7_doc.yaml index 3f036dd6f..4350e33ef 100644 --- a/gen/changelog/v2.7_doc.yaml +++ b/gen/changelog/v2.7_doc.yaml @@ -81,7 +81,6 @@ - event - config - openagent - - autoglob - read - function - reserved-vars From fcee7a294fed7f0cf4bfb14751c92ae3ea478b59 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 1 Aug 2024 23:47:28 +0100 Subject: [PATCH 011/142] bugfix: terminal hangs if is term && --- builtins/core/processes/bgfg_test.go | 4 +- lang/exec.go | 2 +- lang/exec_test.go | 59 ++++++++++++++++++++++++++++ test/murex.go | 8 ++++ utils/alter/merge_test.go | 8 ++-- 5 files changed, 74 insertions(+), 7 deletions(-) diff --git a/builtins/core/processes/bgfg_test.go b/builtins/core/processes/bgfg_test.go index 8517226c4..5564e44aa 100644 --- a/builtins/core/processes/bgfg_test.go +++ b/builtins/core/processes/bgfg_test.go @@ -10,11 +10,11 @@ import ( func TestBg(t *testing.T) { tests := []test.MurexTest{ { - Block: `bg { out "bg" }; sleep 3; out "fg"`, + Block: `bg { out "bg" }; sleep 2; out "fg"`, Stdout: "bg\nfg\n", }, { - Block: `bg { sleep 3; out "bg" }; out "fg"; sleep 6`, + Block: `bg { sleep 2; out "bg" }; out "fg"; sleep 5`, Stdout: "fg\nbg\n", }, } diff --git a/lang/exec.go b/lang/exec.go index 2519ab2d6..e743b1878 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -90,7 +90,7 @@ func execute(p *Process) error { cmd.Env = append(os.Environ(), envMurexPid, envMethodFalse, envBackgroundTrue, envDataType+p.Stdin.GetDataType()) default: cmd.Stdin = os.Stdin - cmd.Env = append(os.Environ(), envMurexPid, envMethodFalse, envBackgroundFalse, envDataType+p.Stdin.GetDataType()) + cmd.Env = append(os.Environ(), envMurexPid, envMethodFalse, envBackgroundFalse, envDataType+"") } if len(p.Exec.Env) > 0 { diff --git a/lang/exec_test.go b/lang/exec_test.go index e51381af0..5943385d9 100644 --- a/lang/exec_test.go +++ b/lang/exec_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/test" "github.com/lmorg/murex/test/count" ) @@ -38,3 +39,61 @@ func TestProcessExecStruct(t *testing.T) { t.Errorf("Expecting a non-nil cmd, instead got %v", cmd) } } + +func TestExecPipeRedirect(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `out exec_test.go`, + Stdout: "", + }, + { + Block: `ls exec_test.go`, + Stdout: "", + }, + { + Block: `exec ls exec_test.go`, + Stdout: "", + }, + ///// + { + Block: `out exec_test.go`, + Stdout: "exec_test.go\n", + }, + { + Block: `ls exec_test.go`, + Stdout: "exec_test.go\n", + }, + { + Block: `exec ls exec_test.go`, + Stdout: "exec_test.go\n", + }, + ///// + { + Block: `out exec_test.go`, + Stdout: "exec_test.go\n", + }, + { + Block: `ls exec_test.go`, + Stdout: "exec_test.go\n", + }, + { + Block: `exec ls exec_test.go`, + Stdout: "exec_test.go\n", + }, + ///// + { + Block: `out exec_test.go`, + Stderr: "exec_test.go\n", + }, + { + Block: `ls exec_test.go`, + Stderr: "exec_test.go\n", + }, + { + Block: `exec ls exec_test.go`, + Stderr: "exec_test.go\n", + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/test/murex.go b/test/murex.go index b7124e956..f597307ee 100644 --- a/test/murex.go +++ b/test/murex.go @@ -5,6 +5,7 @@ import ( "regexp" "strings" "testing" + "time" "github.com/lmorg/murex/config" "github.com/lmorg/murex/config/defaults" @@ -34,6 +35,13 @@ func RunMurexTests(tests []MurexTest, t *testing.T) { hasError := false fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_NEW_MODULE | lang.F_NO_STDIN | lang.F_CREATE_STDOUT | lang.F_CREATE_STDERR) + go func(testNum int) { + time.Sleep(30 * time.Second) + if !fork.Process.HasCancelled() { + panic(fmt.Sprintf("timeout in %s() test %d", t.Name(), testNum)) + } + }(i) + fork.Name.Set("RunMurexTests()") fork.FileRef = &ref.File{Source: &ref.Source{Module: fmt.Sprintf("murex/%s-%d", t.Name(), i)}} exitNum, err := fork.Execute([]rune(tests[i].Block)) diff --git a/utils/alter/merge_test.go b/utils/alter/merge_test.go index f109bfccf..cddb21bd7 100644 --- a/utils/alter/merge_test.go +++ b/utils/alter/merge_test.go @@ -371,7 +371,7 @@ func TestMergeNestedMapMap(t *testing.T) { } // https://github.com/lmorg/murex/issues/850 -func TestMergeIssue850_1(t *testing.T) { +func TestMergeIssue850n1(t *testing.T) { test := plan{ original: `{}`, path: "/", @@ -383,7 +383,7 @@ func TestMergeIssue850_1(t *testing.T) { } // https://github.com/lmorg/murex/issues/850 -func TestMergeIssue850_2(t *testing.T) { +func TestMergeIssue850n2(t *testing.T) { test := plan{ original: `{"key":[{"hello":"world"}]}`, path: "/", @@ -395,7 +395,7 @@ func TestMergeIssue850_2(t *testing.T) { } // https://github.com/lmorg/murex/issues/850 -func TestMergeIssue850_3(t *testing.T) { +func TestMergeIssue850n3(t *testing.T) { test := plan{ original: `{"key":[{"hello":"world"}]}`, path: "/", @@ -407,7 +407,7 @@ func TestMergeIssue850_3(t *testing.T) { } // https://github.com/lmorg/murex/issues/850 -func TestMergeIssue850_4(t *testing.T) { +func TestMergeIssue850n4(t *testing.T) { test := plan{ original: `{"key":[{"hello":"world"}]}`, path: "/", From 0c5ff13407672e6bc9eec45dea7da35115d16582 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 3 Aug 2024 19:48:07 +0100 Subject: [PATCH 012/142] integration: remove deprecated `?` from git completion --- integrations/git_any.mx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/git_any.mx b/integrations/git_any.mx index e872300c5..37c225ebf 100644 --- a/integrations/git_any.mx +++ b/integrations/git_any.mx @@ -71,7 +71,7 @@ autocomplete set git %[{ config: [{ DynamicDesc: '{ # `git config` flags and associated descriptions - git config ? tabulate --split-comma --map --key-inc-hint + git config tabulate --split-comma --map --key-inc-hint }' }] From 68b49a22e71bd129d41fd09a0ef380fe649c0f82 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 3 Aug 2024 23:31:52 +0100 Subject: [PATCH 013/142] count: added support for `--bytes` & `--runes` --- builtins/core/datatools/count.go | 35 ++++++- builtins/core/datatools/count_doc.yaml | 10 ++ builtins/core/datatools/count_test.go | 128 +++++++++++++++++++++++++ docs/commands/count.md | 9 ++ 4 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 builtins/core/datatools/count_test.go diff --git a/builtins/core/datatools/count.go b/builtins/core/datatools/count.go index 6065e872f..c0f9d6ee5 100644 --- a/builtins/core/datatools/count.go +++ b/builtins/core/datatools/count.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" "strings" + "unicode/utf8" "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" @@ -23,9 +24,11 @@ func init() { FlagsDesc: { "--duplications": "Output a JSON map of items and the number of their occurrences in a list or array" "--unique": "Print the number of unique elements in a list or array" - "--sum": "Read an array, list or map from STDIN and output the sum of all the values (ignore non-numeric values)" - "--sum-strict": "Read an array, list or map from STDIN and output the sum of all the values (error on non-numeric values)" - "--total": "Read an array, list or map from STDIN and output the length for that array (default behaviour)" + "--sum": "Read an array, list or map from stdin and output the sum of all the values (ignore non-numeric values)" + "--sum-strict": "Read an array, list or map from stdin and output the sum of all the values (error on non-numeric values)" + "--total": "Read an array, list or map from stdin and output the length for that array (default behaviour)" + "--bytes": "Count the total number of bytes read from stdin", + "--runes": "Count the total number of unicode characters (runes) read from stdin. Zero width symbols, wide characters and other non-typical graphemes are all each treated as a single rune" } }] `) @@ -37,6 +40,8 @@ const ( argSum = "--sum" argSumStrict = "--sum-strict" argTotal = "--total" + argBytes = "--bytes" + argRunes = "--runes" ) var argsCount = parameters.Arguments{ @@ -51,12 +56,14 @@ var argsCount = parameters.Arguments{ argSumStrict: types.Boolean, argTotal: types.Boolean, "-t": argTotal, + argBytes: types.Boolean, + "-b": argBytes, + argRunes: types.Boolean, + "-r": argRunes, }, } func cmdCount(p *lang.Process) error { - //p.Stdout.SetDataType(types.Json) - err := p.ErrIfNotAMethod() if err != nil { return err @@ -122,6 +129,24 @@ func cmdCount(p *lang.Process) error { p.Stdout.SetDataType(types.Number) _, err = p.Stdout.Write([]byte(types.FloatToString(f))) return err + + case argBytes: + p.Stdout.SetDataType(types.Integer) + b, err := p.Stdin.ReadAll() + if err != nil { + return err + } + _, err = p.Stdout.Write([]byte(fmt.Sprintf("%d", len(b)))) + return err + + case argRunes: + p.Stdout.SetDataType(types.Integer) + b, err := p.Stdin.ReadAll() + if err != nil { + return err + } + _, err = p.Stdout.Write([]byte(fmt.Sprintf("%d", utf8.RuneCount(b)))) + return err } } diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index f2da821ca..18ef06b72 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -115,6 +115,16 @@ Read an array, list or map from stdin and output the length for that array (default behaviour) "-t": >- Alias for `--total` + + "--bytes": >- + Count the total number of bytes read from stdin + "-b": >- + + Alias for `--bytes` + "--runes": >- + Count the total number of unicode characters (_runes_) read from stdin. Zero width symbols, wide characters and other non-typical graphemes are all each treated as a single _rune_ + "-r": >- + Alias for `--runes` Synonyms: - count - len diff --git a/builtins/core/datatools/count_test.go b/builtins/core/datatools/count_test.go new file mode 100644 index 000000000..dc897f69d --- /dev/null +++ b/builtins/core/datatools/count_test.go @@ -0,0 +1,128 @@ +package datatools_test + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestCountTotal(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `%[1..5,2,3] -> count`, + Stdout: `7`, + }, + { + Block: `%[1..5,2,3] -> count --total`, + Stdout: `7`, + }, + { + Block: `%[1..5,2,3] -> count -t`, + Stdout: `7`, + }, + ///// + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count`, + Stdout: `5`, + }, + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count --total`, + Stdout: `5`, + }, + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count -t`, + Stdout: `5`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestCountDuplication(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `%[1..5,2,3] -> count --duplications`, + Stdout: `^{"1":1,"2":2,"3":2,"4":1,"5":1}$`, + }, + { + Block: `%[1..5,2,3] -> count -d`, + Stdout: `^{"1":1,"2":2,"3":2,"4":1,"5":1}$`, + }, + ///// + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count --duplications`, + Stderr: `Error`, + ExitNum: 1, + }, + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count -d`, + Stderr: `Error`, + ExitNum: 1, + }, + } + + test.RunMurexTestsRx(tests, t) +} + +func TestCountSum(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `%[1..5,2,3] -> count --sum`, + Stdout: `20`, + }, + { + Block: `%[1..5,2,3] -> count -s`, + Stdout: `20`, + }, + ///// + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count --sum`, + Stdout: `9`, + }, + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count -s`, + Stdout: `9`, + }, + ///// + { + Block: `%[1..5,2,3] -> count --sum-strict`, + Stdout: `20`, + }, + { + Block: `%{a:1, b:2, c:3, d:1, e:2} -> count --sum-strict`, + Stdout: `9`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestCountBytes(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `out "举手之劳就可以使办公室更加环保,比如,使用再生纸" -> count --bytes`, + Stdout: `73`, + }, + { + Block: `out "举手之劳就可以使办公室更加环保,比如,使用再生纸" -> count -b`, + Stdout: `73`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestCountRunes(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `out "举手之劳就可以使办公室更加环保,比如,使用再生纸" -> count --runes`, + Stdout: `25`, + }, + { + Block: `out "举手之劳就可以使办公室更加环保,比如,使用再生纸" -> count -r`, + Stdout: `25`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/docs/commands/count.md b/docs/commands/count.md index edf83fa17..6f21f9442 100644 --- a/docs/commands/count.md +++ b/docs/commands/count.md @@ -23,8 +23,12 @@ Count number of items in a map, list or array: ## Flags +* `--bytes` + Count the total number of bytes read from stdin * `--duplications` Output a JSON map of items and the number of their occurrences in a list or array +* `--runes` + Count the total number of unicode characters (_runes_) read from stdin. Zero width symbols, wide characters and other non-typical graphemes are all each treated as a single _rune_ * `--sum` Read an array, list or map from stdin and output the sum of all the values (ignore non-numeric values) * `--sum-strict` @@ -33,8 +37,13 @@ Count number of items in a map, list or array: Read an array, list or map from stdin and output the length for that array (default behaviour) * `--unique` Print the number of unique elements in a list or array +* `-b` + +Alias for `--bytes` * `-d` Alias for `--duplications` +* `-r` + Alias for `--runes` * `-s` Alias for `--sum` * `-t` From 51afc6ad6e98104d2f5103bb7286e3b7632810ab Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 00:03:07 +0100 Subject: [PATCH 014/142] #834 sub-expression support inside object and array builders --- lang/expressions/parse_array.go | 7 +++++++ lang/expressions/parse_array_test.go | 23 +++++++++++++++++++++ lang/expressions/parse_expression.go | 29 ++++++++++++++++++++++++++- lang/expressions/parse_object.go | 10 +++++++++ lang/expressions/parse_object_test.go | 23 +++++++++++++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/lang/expressions/parse_array.go b/lang/expressions/parse_array.go index 6a3f4fc17..e3ef5df71 100644 --- a/lang/expressions/parse_array.go +++ b/lang/expressions/parse_array.go @@ -113,6 +113,13 @@ func (tree *ParserT) parseArray(exec bool) ([]rune, *primitives.DataType, error) slice = append(slice, v.Value) tree.charPos++ + case '(': + val, err := tree.parseSubExpression(exec) + if err != nil { + return nil, nil, err + } + slice = append(slice, val) + case '$': // inline scalar switch tree.nextChar() { diff --git a/lang/expressions/parse_array_test.go b/lang/expressions/parse_array_test.go index 2e8d85172..cbf510605 100644 --- a/lang/expressions/parse_array_test.go +++ b/lang/expressions/parse_array_test.go @@ -238,3 +238,26 @@ func TestParseArrayBugfix832(t *testing.T) { test.RunMurexTestsRx(tests, t) } + +func TestParseArrayNestedExpr(t *testing.T) { + tests := expTestsT{ + symbol: symbols.ArrayBegin, + tests: []expTestT{ + { + input: "%[(1+1),(2+2)]", + expected: `[2,4]`, + pos: 12, + }, + { + input: "%[(1+-),(2+2)]", + error: true, + }, + { + input: "%[(1+1),(2+-)]", + error: true, + }, + }, + } + + testParserObject(t, tests) +} diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 46acc3db5..fc6622e02 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -155,7 +155,7 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { default: // tilde home, err := tree.parseVarTilde(exec) - if err!=nil { + if err != nil { return err } tree.appendAstWithPrimitive(symbols.Calculated, primitives.NewPrimitive( @@ -468,3 +468,30 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { return nil } + +func (tree *ParserT) parseSubExpression(exec bool) (any, error) { + start := tree.charPos + tree.charPos++ + branch := NewParser(tree.p, tree.expression[tree.charPos:], 0) + branch.charOffset = tree.charPos + tree.charOffset + branch.subExp = true + err := branch.parseExpression(exec, true) + if err != nil { + return nil, err + } + tree.charPos += branch.charPos - 1 + if exec { + dt, err := branch.executeExpr() + if err != nil { + return nil, err + } + val, err := dt.GetValue() + if err != nil { + return nil, err + } + return val.Value, nil + } else { + return string(tree.expression[start:tree.charPos]), nil + } + +} diff --git a/lang/expressions/parse_object.go b/lang/expressions/parse_object.go index 2eb36d8b8..45b21d412 100644 --- a/lang/expressions/parse_object.go +++ b/lang/expressions/parse_object.go @@ -117,6 +117,16 @@ func (tree *ParserT) parseObject(exec bool) ([]rune, *primitives.DataType, error } tree.charPos++ + case '(': + val, err := tree.parseSubExpression(exec) + if err != nil { + return nil, nil, err + } + err = o.UpdateInterface(val) + if err != nil { + return nil, nil, err + } + case '$': switch { case tree.nextChar() == '{': diff --git a/lang/expressions/parse_object_test.go b/lang/expressions/parse_object_test.go index 19d5ab9a8..b2f1a4b50 100644 --- a/lang/expressions/parse_object_test.go +++ b/lang/expressions/parse_object_test.go @@ -225,3 +225,26 @@ func TestParseObjectNestedString(t *testing.T) { testParserObject(t, tests) } + +func TestParseObjectNestedExpr(t *testing.T) { + tests := expTestsT{ + symbol: symbols.ObjectBegin, + tests: []expTestT{ + { + input: "%{(1+1):(2+2)}", + expected: `{"2":4}`, + pos: 12, + }, + { + input: "%{(1+-):(2+2)}", + error: true, + }, + { + input: "%{(1+1):(2+-)}", + error: true, + }, + }, + } + + testParserObject(t, tests) +} From 58d7e6483f8027e1617188d49fb21b3e818647df Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 12:11:10 +0100 Subject: [PATCH 015/142] #853 sub-shell scalars should return objects inside object builders --- docs/parser/README.md | 2 +- docs/parser/scalar.md | 38 +++++++++++++++++++---- docs/user-guide/README.md | 2 +- lang/expressions/parse_function.go | 2 +- lang/expressions/parse_object.go | 6 ++-- lang/expressions/parse_subshell.go | 4 +-- lang/expressions/variables.go | 24 ++++++++++++--- lang/expressions/variables_test.go | 49 ++++++++++++++++++++++++++++++ version.svg | 2 +- 9 files changed, 109 insertions(+), 20 deletions(-) diff --git a/docs/parser/README.md b/docs/parser/README.md index 6bbd9d212..7c12c0c08 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -284,7 +284,7 @@ files. Inlined commands for expressions and statements * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) -* [`$Variable` Sigil](../parser/scalar.md): +* [`$Scalar` Sigil (eg variables)](../parser/scalar.md): Expand values as a scalar * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/parser/scalar.md b/docs/parser/scalar.md index 1882f1888..6fc9d05c4 100644 --- a/docs/parser/scalar.md +++ b/docs/parser/scalar.md @@ -1,4 +1,4 @@ -# `$Variable` Sigil +# `$Scalar` Sigil (eg variables) > Expand values as a scalar @@ -6,12 +6,38 @@ The scalar token is used to tell Murex to expand variables and sub-shells as a string (ie one single parameter) irrespective of the data that is stored in the -string. One handy common use case is file names where traditional POSIX shells -would treat spaces as a new file, whereas Murex treats spaces as a printable -character unless explicitly told to do otherwise. +string. -The string token must be followed with one of the following characters: -alpha, numeric, underscore (`_`) or a full stop / period (`.`). +One common use case where Murex's approach is better is with file names. +Traditional shells would treat spaces as a new file. Whereas Murex treats +spaces as any other printable character character. + +## Variable Syntax + +There are two basic syntaxes. Bare an enclosed. + +### Bare Syntax + +Bare syntax looks like the following: + +``` +$scalar +``` + +The variable token must be followed with one of the following characters: +alpha (`a` to `z`, upper and lower case), numeric (`0` to `1`), underscore +(`_`) and/or a full stop (`.`). + +### Enclosed Syntax + +Enclosed syntax looks like the following: + +``` +$(scalar) +``` + +Enclosed syntax supports any unicode characters however the variable name +needs to be surrounded by parenthesis. See examples below. diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 52079330d..4e4ade2a8 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -74,7 +74,7 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Inlined commands for expressions and statements * [`"Double Quote"`](parser/double-quote.md): Initiates or terminates a string (variables expanded) -* [`$Variable` Sigil](parser/scalar.md): +* [`$Scalar` Sigil (eg variables)](parser/scalar.md): Expand values as a scalar * [`%(Brace Quote)`](parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/lang/expressions/parse_function.go b/lang/expressions/parse_function.go index f42e5cf79..0f5188341 100644 --- a/lang/expressions/parse_function.go +++ b/lang/expressions/parse_function.go @@ -49,7 +49,7 @@ func (tree *ParserT) parseFunction(exec bool, cmd []rune, strOrVal varFormatting } b = utils.CrLfTrim(b) val.DataType = fork.Stdout.GetDataType() - val.Value, err = formatBytes(b, val.DataType, strOrVal) + val.Value, err = formatBytes(tree, b, val.DataType, strOrVal) if err != nil { return nil, fmt.Errorf("function `%s` STDOUT conversion error: %s", string(cmd), err.Error()) } diff --git a/lang/expressions/parse_object.go b/lang/expressions/parse_object.go index 45b21d412..2b9352cc8 100644 --- a/lang/expressions/parse_object.go +++ b/lang/expressions/parse_object.go @@ -130,7 +130,7 @@ func (tree *ParserT) parseObject(exec bool) ([]rune, *primitives.DataType, error case '$': switch { case tree.nextChar() == '{': - // inline subshell + // inline sub-shell strOrVal := varFormatting(o.stage) subshell, fn, err := tree.parseSubShell(exec, r, strOrVal) if err != nil { @@ -154,12 +154,12 @@ func (tree *ParserT) parseObject(exec bool) ([]rune, *primitives.DataType, error default: // inline scalar strOrVal := varFormatting(o.stage) - scalar, v, _, err := tree.parseVarScalar(exec, strOrVal) + scalar, val, _, err := tree.parseVarScalar(exec, strOrVal) if err != nil { return nil, nil, err } if exec { - err = o.UpdateInterface(v) + err = o.UpdateInterface(val) if err != nil { return nil, nil, err } diff --git a/lang/expressions/parse_subshell.go b/lang/expressions/parse_subshell.go index e8d895fd0..e526131ce 100644 --- a/lang/expressions/parse_subshell.go +++ b/lang/expressions/parse_subshell.go @@ -63,13 +63,13 @@ func execSubShellScalar(tree *ParserT, block []rune, strOrVal varFormatting) (*p } b, err := fork.Stdout.ReadAll() if err != nil { - return val, fmt.Errorf("cannot read from subshell's STDOUT: %s", err.Error()) + return val, fmt.Errorf("cannot read from sub-shell's stdout: %s", err.Error()) } b = utils.CrLfTrim(b) val.DataType = fork.Stdout.GetDataType() - val.Value, err = formatBytes(b, val.DataType, strOrVal) + val.Value, err = formatBytes(tree, b, val.DataType, strOrVal) return val, err } diff --git a/lang/expressions/variables.go b/lang/expressions/variables.go index c758ad8c3..cd63c805a 100644 --- a/lang/expressions/variables.go +++ b/lang/expressions/variables.go @@ -18,6 +18,8 @@ const ( var errEmptyRange = "range '@%s[%s]%s' is empty" +// getVar doesn't call formatBytes because variables already store both the +// string and object representations. func (tree *ParserT) getVar(name []rune, strOrVal varFormatting) (interface{}, string, error) { var ( value interface{} @@ -136,7 +138,7 @@ func (tree *ParserT) getVarIndexOrElement(getIorE *getVarIndexOrElementT) (inter b = utils.CrLfTrim(b) dataType := fork.Stdout.GetDataType() - v, err := formatBytes(b, dataType, getIorE.strOrVal) + v, err := formatBytes(tree, b, dataType, getIorE.strOrVal) return v, dataType, err } @@ -198,20 +200,32 @@ func (tree *ParserT) getVarRange(name, key, flags []rune) (interface{}, error) { } -func formatBytes(b []byte, dataType string, strOrVal varFormatting) (interface{}, error) { +// formatBytes this isn't used for variables because vars already store both +// the string and object representations. +func formatBytes(tree *ParserT, b []byte, dataType string, strOrVal varFormatting) (interface{}, error) { if strOrVal == varAsString { return string(b), nil } switch dataType { - case types.Number, types.String, types.Integer, types.Boolean, types.Null, types.Float: + case types.Number, types.String, types.Integer, types.Boolean, types.Float, types.Null: v, err := types.ConvertGoType(b, dataType) if err != nil { - return nil, err + return string(b), err } return v, nil default: - return string(b), nil + fork := tree.p.Fork(lang.F_CREATE_STDIN | lang.F_NO_STDOUT | lang.F_NO_STDERR) + defer fork.Kill() + _, err := fork.Stdin.Write(b) + if err != nil { + return string(b), err + } + v, err := lang.UnmarshalData(fork.Process, dataType) + if err != nil { + return string(b), nil + } + return v, nil } } diff --git a/lang/expressions/variables_test.go b/lang/expressions/variables_test.go index d88872df7..eb7aa475a 100644 --- a/lang/expressions/variables_test.go +++ b/lang/expressions/variables_test.go @@ -3,6 +3,7 @@ package expressions import ( "testing" + "github.com/lmorg/murex/test" "github.com/lmorg/murex/test/count" ) @@ -119,3 +120,51 @@ func TestCreateRangeBlock(t *testing.T) { } } } + +func TestFormatBytes(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `function test0 { %{a:1, b:2, c:3} }; %{${test0}: ${test0}}`, + Stdout: `{"{\"a\":1,\"b\":2,\"c\":3}":{"a":1,"b":2,"c":3}}`, + }, + { + Block: `function test1 { tout str "test1" }; %{${test1}: ${test1}}`, + Stdout: `{"test1":"test1"}`, + }, + { + Block: `function test2 { tout str 2 }; %{${test2}: ${test2}}`, + Stdout: `{"2":"2"}`, + }, + { + Block: `function test3 { tout int 3 }; %{${test3}: ${test3}}`, + Stdout: `{"3":3}`, + }, + { + Block: `function test4 { tout float 4.1 }; %{${test4}: ${test4}}`, + Stdout: `{"4.1":4.1}`, + }, + { + Block: `function test5 { tout num 5.2 }; %{${test5}: ${test5}}`, + Stdout: `{"5.2":5.2}`, + }, + { + Block: `function test6 { true }; %{${test6}: ${test6}}`, + Stdout: `{"true":true}`, + }, + { + Block: `function test7 { false }; %{${test7}: ${test7}}`, + Stdout: `{"false":false}`, + }, + ///// + { + Block: `function test8 { tout null "" }; %{${test8}: ${test8}}`, + Stdout: `{"":[null]}`, + }, + { + Block: `function test8 { null }; %{${test8}: ${test8}}`, + Stdout: `{"":[null]}`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/version.svg b/version.svg index 17a5c44dc..89d6903de 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1200Version6.3.1200 +Version: 6.3.1300Version6.3.1300 From d457996cd48f30d6045d20e41cfb346bb5fabe99 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 12:12:30 +0100 Subject: [PATCH 016/142] docs: updated scalar docs --- app/app.go | 2 +- gen/parser/variables_doc.yaml | 38 +++++++++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 37952c433..69679bfe4 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1200 + Revision = 1300 ) // Copyright is the copyright owner string diff --git a/gen/parser/variables_doc.yaml b/gen/parser/variables_doc.yaml index 49871fc62..ee6e30725 100644 --- a/gen/parser/variables_doc.yaml +++ b/gen/parser/variables_doc.yaml @@ -1,18 +1,44 @@ - DocumentID: scalar Title: >- - `$Variable` Sigil + `$Scalar` Sigil (eg variables) CategoryID: parser Summary: >- Expand values as a scalar Description: |- The scalar token is used to tell Murex to expand variables and sub-shells as a string (ie one single parameter) irrespective of the data that is stored in the - string. One handy common use case is file names where traditional POSIX shells - would treat spaces as a new file, whereas Murex treats spaces as a printable - character unless explicitly told to do otherwise. + string. + + One common use case where Murex's approach is better is with file names. + Traditional shells would treat spaces as a new file. Whereas Murex treats + spaces as any other printable character character. + + ## Variable Syntax + + There are two basic syntaxes. Bare an enclosed. + + ### Bare Syntax + + Bare syntax looks like the following: + + ``` + $scalar + ``` + + The variable token must be followed with one of the following characters: + alpha (`a` to `z`, upper and lower case), numeric (`0` to `1`), underscore + (`_`) and/or a full stop (`.`). + + ### Enclosed Syntax + + Enclosed syntax looks like the following: + + ``` + $(scalar) + ``` - The string token must be followed with one of the following characters: - alpha, numeric, underscore (`_`) or a full stop / period (`.`). + Enclosed syntax supports any unicode characters however the variable name + needs to be surrounded by parenthesis. See examples below. Examples: |- {{ include "gen/includes/parser-var-tokens.inc.md" }} From c2f530b5f07d74ac7d7fd0349ab75dab590296b8 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 12:18:14 +0100 Subject: [PATCH 017/142] core: add additional array builder tests --- lang/expressions/variables_test.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lang/expressions/variables_test.go b/lang/expressions/variables_test.go index eb7aa475a..527c2d366 100644 --- a/lang/expressions/variables_test.go +++ b/lang/expressions/variables_test.go @@ -121,7 +121,27 @@ func TestCreateRangeBlock(t *testing.T) { } } -func TestFormatBytes(t *testing.T) { +func TestFormatBytesArrayBuilder(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `function test0 { %{a:1, b:2, c:3} }; %[ ${test0} ]`, + Stdout: `[{"a":1,"b":2,"c":3}]`, + }, + ///// + { + Block: `function test8 { tout null "" }; %[ ${test8} ]`, + Stdout: `[[null]]`, // this is potentially unexpected behaviour + }, + { + Block: `function test9 { null }; %[ ${test9} ]`, + Stdout: `[[null]]`, // this is potentially unexpected behaviour + }, + } + + test.RunMurexTests(tests, t) +} + +func TestFormatBytesObjectBuilder(t *testing.T) { tests := []test.MurexTest{ { Block: `function test0 { %{a:1, b:2, c:3} }; %{${test0}: ${test0}}`, @@ -161,7 +181,7 @@ func TestFormatBytes(t *testing.T) { Stdout: `{"":[null]}`, }, { - Block: `function test8 { null }; %{${test8}: ${test8}}`, + Block: `function test9 { null }; %{${test9}: ${test9}}`, Stdout: `{"":[null]}`, }, } From b79c50f9b77175333bc2c3b0e725947aa65fe434 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 12:20:59 +0100 Subject: [PATCH 018/142] integrations: systemctl should use improved sub-shell inlining --- integrations/systemctl_linux.mx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/integrations/systemctl_linux.mx b/integrations/systemctl_linux.mx index d2cd426e6..48f0fd766 100644 --- a/integrations/systemctl_linux.mx +++ b/integrations/systemctl_linux.mx @@ -36,7 +36,7 @@ private autocomplete.systemctl.flags { $json } -autocomplete = %[ +autocomplete set systemctl %[ { DynamicDesc: '{ systemctl --help \ @@ -54,9 +54,6 @@ autocomplete = %[ }' Optional: false AllowMultiple: false + FlagValues: ${ private /builtin/integrations_systemctl_linux/autocomplete.systemctl.flags } } ] - -tout json $autocomplete \ --> alter /1/FlagValues fexec(private /builtin/integrations_systemctl_linux/autocomplete.systemctl.flags) \ --> autocomplete set systemctl \ No newline at end of file From 7a3a6c43173c178ec87daba55cf63819d4dfb198 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 17:14:33 +0100 Subject: [PATCH 019/142] test: correct deprecated tests --- lang/expressions/parse_block_test.go | 15 ++------------- lang/expressions/parse_function_test.go | 2 +- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/lang/expressions/parse_block_test.go b/lang/expressions/parse_block_test.go index 8618d7638..c4d8b3066 100644 --- a/lang/expressions/parse_block_test.go +++ b/lang/expressions/parse_block_test.go @@ -31,10 +31,10 @@ func TestParseBlock(t *testing.T) { Block: "out 1\nout 2\nout 3\nout 4\nout 5\n\n", Stdout: "1\n2\n3\n4\n5\n", }, - { + /*{ Block: `${err 1|err 2|err 3|err 4|err 5} ? msort`, Stdout: "1\n2\n3\n4\n5\n", - }, + },*/ { Block: "out:1\nout:2\nout:3\nout:4\nout:5", Stdout: "1\n2\n3\n4\n5\n", @@ -167,17 +167,6 @@ func TestParseBlockEscapedCrLf(t *testing.T) { test.RunMurexTests(tests, t) } -func TestParseBlockEqu(t *testing.T) { - tests := []test.MurexTest{ - { - Block: `= true`, - Stdout: `true`, - }, - } - - test.RunMurexTests(tests, t) -} - func TestParseBlockPipeOverwriteFile1(t *testing.T) { filename := fmt.Sprintf("%s-%d.testfile", t.Name(), time.Now().UnixNano()) tests := []test.MurexTest{ diff --git a/lang/expressions/parse_function_test.go b/lang/expressions/parse_function_test.go index 99518ce48..a5ccd7878 100644 --- a/lang/expressions/parse_function_test.go +++ b/lang/expressions/parse_function_test.go @@ -26,7 +26,7 @@ func TestParseFunction(t *testing.T) { }, { Block: `if({true}{out hello}{out world})`, - Stdout: "hello", + Stdout: "hello\n", }, { Block: `out(%({hello}{world}))`, From 8cd373d5dd6c1efed4b6e44434196d5245a67c14 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 20:00:37 +0100 Subject: [PATCH 020/142] fix systemctl integration --- integrations/systemctl_linux.mx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/systemctl_linux.mx b/integrations/systemctl_linux.mx index 48f0fd766..569c381ac 100644 --- a/integrations/systemctl_linux.mx +++ b/integrations/systemctl_linux.mx @@ -54,6 +54,6 @@ autocomplete set systemctl %[ }' Optional: false AllowMultiple: false - FlagValues: ${ private /builtin/integrations_systemctl_linux/autocomplete.systemctl.flags } + FlagValues: ${ fexec private /builtin/integrations_systemctl_linux/autocomplete.systemctl.flags } } ] From 830abd646e91aa4a2d4e6d76fde60dec6ffaf7d7 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 4 Aug 2024 22:51:21 +0100 Subject: [PATCH 021/142] #830 parenthesis can assign to variable values --- lang/expressions/exp14.go | 47 ++++++++++++++----- lang/expressions/parse_expression.go | 5 +- .../primitives/primitive_string.go | 4 +- lang/expressions/primitives/primitives.go | 6 +-- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/lang/expressions/exp14.go b/lang/expressions/exp14.go index e2f634310..c9d020228 100644 --- a/lang/expressions/exp14.go +++ b/lang/expressions/exp14.go @@ -36,12 +36,33 @@ func scalarNameDetokenised(r []rune) []rune { } } -func convertScalarToBareword(node *astNodeT) { - if node.key == symbols.Scalar && len(node.value) > 1 && - node.value[0] == '$' && node.value[1] != '{' { +func convertAssigneeToBareword(tree *ParserT, node *astNodeT) error { + switch { + case node.key == symbols.Scalar && len(node.value) > 1 && + node.value[0] == '$' && node.value[1] != '{': node.key = symbols.Bareword node.value = scalarNameDetokenised(node.value) + return nil + + case node.key == symbols.QuoteSingle && len(node.value) > 0 && node.value[0] == '(': + val, err := node.dt.GetValue() + if err != nil { + return raiseError(tree.expression, node, 0, fmt.Sprintf( + "cannot assign a value to %s: %s", node.key.String(), err.Error())) + } + s, err := types.ConvertGoType(val.Value, types.String) + if err != nil { + return raiseError(tree.expression, node, 0, fmt.Sprintf( + "cannot assign a value to %s: %s", node.key.String(), err.Error())) + } + node.key = symbols.Bareword + node.value = []rune(s.(string)) + return nil + + default: + return raiseError(tree.expression, node, 0, fmt.Sprintf( + "cannot assign a value to %s", node.key.String())) } } @@ -51,12 +72,8 @@ func expAssign(tree *ParserT, overwriteType bool) error { return err } - convertScalarToBareword(leftNode) - - if leftNode.key != symbols.Bareword { - return raiseError(tree.expression, leftNode, 0, fmt.Sprintf( - "left side of %s should be a bareword, instead got %s", - tree.currentSymbol().key, leftNode.key)) + if err = convertAssigneeToBareword(tree, leftNode); err != nil { + return err } if rightNode.key <= symbols.Bareword { @@ -140,7 +157,9 @@ func expAssignAdd(tree *ParserT) error { return err } - convertScalarToBareword(leftNode) + if err = convertAssigneeToBareword(tree, leftNode); err != nil { + return err + } right, err := rightNode.dt.GetValue() if err != nil { @@ -232,7 +251,9 @@ func expAssignAndOperate(tree *ParserT, operation assFnT) error { return err } - convertScalarToBareword(leftNode) + if err = convertAssigneeToBareword(tree, leftNode); err != nil { + return err + } right, err := rightNode.dt.GetValue() if err != nil { @@ -298,7 +319,9 @@ func expAssignMerge(tree *ParserT) error { return err } - convertScalarToBareword(leftNode) + if err = convertAssigneeToBareword(tree, leftNode); err != nil { + return err + } if leftNode.key != symbols.Bareword { return raiseError(tree.expression, leftNode, 0, fmt.Sprintf( diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index fc6622e02..5ed27f769 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -204,7 +204,7 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { if err != nil { return err } - tree.charPos += branch.charPos - 1 + if exec { dt, err := branch.executeExpr() if err != nil { @@ -214,10 +214,11 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { if err != nil { return err } - tree.appendAstWithPrimitive(symbols.Exp(val.Primitive), dt) + tree.appendAstWithPrimitive(symbols.Exp(val.Primitive), dt, '(') } else { tree.appendAst(symbols.SubExpressionBegin) } + tree.charPos += branch.charPos - 1 case ')': tree.charPos++ diff --git a/lang/expressions/primitives/primitive_string.go b/lang/expressions/primitives/primitive_string.go index 573e8ff40..4e1bf701b 100644 --- a/lang/expressions/primitives/primitive_string.go +++ b/lang/expressions/primitives/primitive_string.go @@ -20,13 +20,13 @@ func _() { } const ( - _Primitive_name_0 = "functions and subshellsotherbareword" + _Primitive_name_0 = "functions and sub-shellsotherbareword" _Primitive_name_1 = "objectarraystring" _Primitive_name_2 = "numberbooleannull" ) var ( - _Primitive_index_0 = [...]uint8{0, 23, 28, 36} + _Primitive_index_0 = [...]uint8{0, 24, 29, 37} _Primitive_index_1 = [...]uint8{0, 6, 11, 17} _Primitive_index_2 = [...]uint8{0, 6, 13, 17} ) diff --git a/lang/expressions/primitives/primitives.go b/lang/expressions/primitives/primitives.go index b42094e0c..86e98215e 100644 --- a/lang/expressions/primitives/primitives.go +++ b/lang/expressions/primitives/primitives.go @@ -19,7 +19,7 @@ const ( Null Primitive = Primitive(symbols.Null) // null Bareword Primitive = 0 // bareword Other Primitive = -1 // other - Function Primitive = -2 // functions and subshells + Function Primitive = -2 // functions and sub-shells ) func (primitive Primitive) IsComparable() bool { @@ -43,10 +43,6 @@ func NewPrimitive(primitive Primitive, value any) *DataType { } func NewFunction(fn FunctionT) *DataType { - /*if fn == nil { - panic("undefined function") - }*/ - return &DataType{ v: &Value{Primitive: Function}, fn: fn, From 57315ac86507d2340cf9cc21c3d344be49840579 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 6 Aug 2024 14:43:59 +0100 Subject: [PATCH 022/142] #830 fix regression with bareword assignment --- app/app.go | 2 +- lang/expressions/exp14.go | 3 +++ version.svg | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index 69679bfe4..52a686947 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1300 + Revision = 1301 ) // Copyright is the copyright owner string diff --git a/lang/expressions/exp14.go b/lang/expressions/exp14.go index c9d020228..a64ba7f71 100644 --- a/lang/expressions/exp14.go +++ b/lang/expressions/exp14.go @@ -38,6 +38,9 @@ func scalarNameDetokenised(r []rune) []rune { func convertAssigneeToBareword(tree *ParserT, node *astNodeT) error { switch { + case node.key == symbols.Bareword: + return nil + case node.key == symbols.Scalar && len(node.value) > 1 && node.value[0] == '$' && node.value[1] != '{': diff --git a/version.svg b/version.svg index 89d6903de..6aa02d1b2 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1300Version6.3.1300 +Version: 6.3.1301Version6.3.1301 From 9d02b4ce88b8644ee29225dccfb2f5dc4255413e Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 10 Aug 2024 09:20:49 +0100 Subject: [PATCH 023/142] core: merge op + minor validator refactor --- app/app.go | 2 +- docs/commands/expr.md | 12 +++++++++--- lang/expressions/exp04.go | 6 +++--- lang/expressions/expression.go | 12 +++++++++--- lang/expressions/parse_expression.go | 2 +- lang/expressions/symbols/exp.go | 5 ++++- lang/expressions/symbols/exp_string.go | 10 +++++----- lang/expressions/validate.go | 20 ++++++++++---------- version.svg | 2 +- 9 files changed, 43 insertions(+), 28 deletions(-) diff --git a/app/app.go b/app/app.go index 52a686947..385f9e4df 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1301 + Revision = 1400 ) // Copyright is the copyright owner string diff --git a/docs/commands/expr.md b/docs/commands/expr.md index ab0ccde5b..1770c0f36 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -167,6 +167,9 @@ var orderOfOperations = []symbols.Exp{ // 04. Addition and subtraction symbols.Add, + // 04.1 Merge + symbols.Merge, + // 05. Bitwise shift left and right // 06. Comparisons: less-than and greater-than symbols.GreaterThan, @@ -260,14 +263,17 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.LessThanOrEqual: err = expGtLt(tree, _ltEqF, _ltEqS) - // 05. Bitwise shift left and right + // 05. Bitwise shift left and right + + // 04.1 Merge + case symbols.Merge: + err = expMerge(tree) + // 04. Addition and subtraction case symbols.Add: err = expAdd(tree) case symbols.Subtract: err = expSubtract(tree) - case symbols.MergeInto: - err = expMergeInto(tree) // 03. Multiplication, division, modulo case symbols.Multiply: diff --git a/lang/expressions/exp04.go b/lang/expressions/exp04.go index fd3295e59..6c3eddaae 100644 --- a/lang/expressions/exp04.go +++ b/lang/expressions/exp04.go @@ -46,7 +46,7 @@ func expSubtract(tree *ParserT) error { const errCannotMergeWith = "cannot merge %s with %s: %s" -func expMergeInto(tree *ParserT) error { +func expMerge(tree *ParserT) error { leftNode, rightNode, err := tree.getLeftAndRightSymbols() if err != nil { return err @@ -61,7 +61,7 @@ func expMergeInto(tree *ParserT) error { return err } - if left.Primitive != primitives.Array && left.Primitive != primitives.Object { + /*if left.Primitive != primitives.Array && left.Primitive != primitives.Object { return raiseError(tree.expression, leftNode, 0, fmt.Sprintf( errCannotMergeWith, right.Primitive.String(), left.Primitive.String(), @@ -73,7 +73,7 @@ func expMergeInto(tree *ParserT) error { errCannotMergeWith, right.Primitive.String(), left.Primitive.String(), "right side needs to be an array or object")) - } + }*/ merged, err := alter.Merge(tree.p.Context, left.Value, nil, right.Value) if err != nil { diff --git a/lang/expressions/expression.go b/lang/expressions/expression.go index 0cc088d22..48eb92ea2 100644 --- a/lang/expressions/expression.go +++ b/lang/expressions/expression.go @@ -49,6 +49,9 @@ var orderOfOperations = []symbols.Exp{ // 04. Addition and subtraction symbols.Add, + // 04.1 Merge + symbols.Merge, + // 05. Bitwise shift left and right // 06. Comparisons: less-than and greater-than symbols.GreaterThan, @@ -142,14 +145,17 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.LessThanOrEqual: err = expGtLt(tree, _ltEqF, _ltEqS) - // 05. Bitwise shift left and right + // 05. Bitwise shift left and right + + // 04.1 Merge + case symbols.Merge: + err = expMerge(tree) + // 04. Addition and subtraction case symbols.Add: err = expAdd(tree) case symbols.Subtract: err = expSubtract(tree) - case symbols.MergeInto: - err = expMergeInto(tree) // 03. Multiplication, division, modulo case symbols.Multiply: diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 5ed27f769..271d68509 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -150,7 +150,7 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { tree.charPos++ case '>': // merge into - tree.appendAst(symbols.MergeInto) + tree.appendAst(symbols.Merge) tree.charPos++ default: // tilde diff --git a/lang/expressions/symbols/exp.go b/lang/expressions/symbols/exp.go index 74a6ea9d8..d3821f646 100644 --- a/lang/expressions/symbols/exp.go +++ b/lang/expressions/symbols/exp.go @@ -81,10 +81,13 @@ const ( LessThanOrEqual // 05. Bitwise shift left and right + + // 04.1 Marge + Merge + // 04. Addition and subtraction Add Subtract - MergeInto // 03. Multiplication, division, modulo Multiply diff --git a/lang/expressions/symbols/exp_string.go b/lang/expressions/symbols/exp_string.go index d9e625d16..d927f9889 100644 --- a/lang/expressions/symbols/exp_string.go +++ b/lang/expressions/symbols/exp_string.go @@ -49,20 +49,20 @@ func _() { _ = x[GreaterThanOrEqual-39] _ = x[LessThan-40] _ = x[LessThanOrEqual-41] - _ = x[Add-42] - _ = x[Subtract-43] - _ = x[MergeInto-44] + _ = x[Merge-42] + _ = x[Add-43] + _ = x[Subtract-44] _ = x[Multiply-45] _ = x[Divide-46] } const ( _Exp_name_0 = "Undefined" - _Exp_name_1 = "UnexpectedInvalidHyphenSubExpressionEndObjectEndArrayEndDataValuesBarewordSubExpressionBeginObjectBeginArrayBeginQuoteSingleQuoteDoubleQuoteParenthesisNumberBooleanNullScalarCalculatedOperationsAssignAssignUpdateAssignAndAddAssignAndSubtractAssignAndDivideAssignAndMultiplyAssignOrMergeElvisNullCoalescingLogicalOrLogicalAndEqualToNotEqualToLikeNotLikeRegexpNotRegexpGreaterThanGreaterThanOrEqualLessThanLessThanOrEqualAddSubtractMergeIntoMultiplyDivide" + _Exp_name_1 = "UnexpectedInvalidHyphenSubExpressionEndObjectEndArrayEndDataValuesBarewordSubExpressionBeginObjectBeginArrayBeginQuoteSingleQuoteDoubleQuoteParenthesisNumberBooleanNullScalarCalculatedOperationsAssignAssignUpdateAssignAndAddAssignAndSubtractAssignAndDivideAssignAndMultiplyAssignOrMergeElvisNullCoalescingLogicalOrLogicalAndEqualToNotEqualToLikeNotLikeRegexpNotRegexpGreaterThanGreaterThanOrEqualLessThanLessThanOrEqualMergeAddSubtractMultiplyDivide" ) var ( - _Exp_index_1 = [...]uint16{0, 10, 23, 39, 48, 56, 66, 74, 92, 103, 113, 124, 135, 151, 157, 164, 168, 174, 184, 194, 200, 212, 224, 241, 256, 273, 286, 291, 305, 314, 324, 331, 341, 345, 352, 358, 367, 378, 396, 404, 419, 422, 430, 439, 447, 453} + _Exp_index_1 = [...]uint16{0, 10, 23, 39, 48, 56, 66, 74, 92, 103, 113, 124, 135, 151, 157, 164, 168, 174, 184, 194, 200, 212, 224, 241, 256, 273, 286, 291, 305, 314, 324, 331, 341, 345, 352, 358, 367, 378, 396, 404, 419, 424, 427, 435, 443, 449} ) func (i Exp) String() string { diff --git a/lang/expressions/validate.go b/lang/expressions/validate.go index 0d08be678..a43959348 100644 --- a/lang/expressions/validate.go +++ b/lang/expressions/validate.go @@ -60,22 +60,22 @@ func (tree *ParserT) validateExpression() error { node.dt = primitive } else { - if node.key < symbols.Operations { - return raiseError(tree.expression, node, 0, "expecting an operation") - } - switch node.key { - case symbols.Add, symbols.GreaterThan, symbols.LessThan: - if prev == nil || prev.key == symbols.Bareword || - next == nil || next.key == symbols.Bareword { - return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s barewords", node.key)) - } + switch { + case node.key < symbols.Operations: + return raiseError(tree.expression, node, 0, "expecting an operation") - case symbols.Subtract, symbols.Divide, symbols.Multiply: + case node.key >= symbols.Add: if prev == nil || (prev.key != symbols.Number && prev.key != symbols.Calculated && prev.key != symbols.SubExpressionBegin && prev.key != symbols.Scalar) || next == nil || (next.key != symbols.Number && next.key != symbols.Calculated && next.key != symbols.SubExpressionBegin && next.key != symbols.Scalar) { return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s non-numeric data types", node.key)) } + + case node.key >= symbols.Elvis: + if prev == nil || prev.key == symbols.Bareword || + next == nil || next.key == symbols.Bareword { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s barewords", node.key)) + } } } diff --git a/version.svg b/version.svg index 6aa02d1b2..60ecf37a5 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1301Version6.3.1301 +Version: 6.3.1400Version6.3.1400 From 9a57ad132090a599516175b6c5c72801d14c501e Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 10 Aug 2024 21:37:01 +0100 Subject: [PATCH 024/142] docs: immutable merge --- docs/parser/README.md | 30 +++++++++++++++++------ docs/user-guide/operators-and-tokens.md | 30 +++++++++++++++++------ gen/includes/expr-operators-tokens.inc.md | 30 +++++++++++++++++------ lang/expressions/parse_expression.go | 2 +- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/docs/parser/README.md b/docs/parser/README.md index 7c12c0c08..a087be809 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -12,6 +12,7 @@ - [Operators And Tokens](#operators-and-tokens) - [Terminology](#terminology) - [Modifiers](#modifiers) + - [Immutable Merge](#immutable-merge) - [Comparators](#comparators) - [Assignment](#assignment) - [Conditionals](#conditionals) @@ -57,12 +58,13 @@ Order of operations: 2. sub-shells / sub-expressions 3. multiplication / division (expressions only) 4. addition / subtraction (expressions only) -5. comparisons, eg greater than -6. logical and (sub-expressions only) -7. logical or (sub-expressions only) -8. elvis (expressions only) -9. assign (expressions only) -10. _left_ to _right_ +5. immutable merge +6. comparisons, eg greater than (expressions only) +7. logical and (sub-expressions only) +8. logical or (sub-expressions only) +9. elvis (expressions only) +10. assign (expressions only) +11. _left_ to _right_ ### Expression Or Statement Discovery @@ -102,6 +104,20 @@ Read more: * Strict types config: [strict types](/docs/user-guide/strict-types.md) * Operators: [+](/docs/parser/addition.md), [-](/docs/parser/subtraction.md), [*](/docs/parser/multiplication.md), [/](/docs/parser/division.md) +### Immutable Merge + +Returns the result of merging _right_ into _left_. + +_immutable merge_ does not modify the contents of either _left_ nor _right_. + +The direction of the arrow indicates that the result returned is a new value +rather than an updated assignment. + +| Operator | Name | Operation | +|----------|-----------------|---------------------------------------------| +| `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | + + ### Comparators All comparators replace the _left_, operator and _right_ with the returned @@ -145,7 +161,7 @@ Assignment is only supported in expressions. Read more: * Data types: [bool](/docs/types/bool.md) -* Operators: =, [<~](/docs/parser/assign-or-merge.md), [+=](/docs/parser/add-with.md), [-=](/docs/parser/subtract-by.md), [=](/docs/parser/multiply-by.md), [=](/docs/parser/divide-by.md) +* Operators: =, [<~](/docs/parser/assign-or-merge.md), [+=](/docs/parser/add-with.md), [-=](/docs/parser/subtract-by.md), [*=](/docs/parser/multiply-by.md), [/=](/docs/parser/divide-by.md) ### Conditionals diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index ce8b40af9..c714149af 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -14,6 +14,7 @@ - [Operators And Tokens](#operators-and-tokens) - [Terminology](#terminology) - [Modifiers](#modifiers) + - [Immutable Merge](#immutable-merge) - [Comparators](#comparators) - [Assignment](#assignment) - [Conditionals](#conditionals) @@ -59,12 +60,13 @@ Order of operations: 2. sub-shells / sub-expressions 3. multiplication / division (expressions only) 4. addition / subtraction (expressions only) -5. comparisons, eg greater than -6. logical and (sub-expressions only) -7. logical or (sub-expressions only) -8. elvis (expressions only) -9. assign (expressions only) -10. _left_ to _right_ +5. immutable merge +6. comparisons, eg greater than (expressions only) +7. logical and (sub-expressions only) +8. logical or (sub-expressions only) +9. elvis (expressions only) +10. assign (expressions only) +11. _left_ to _right_ ### Expression Or Statement Discovery @@ -104,6 +106,20 @@ Read more: * Strict types config: [strict types](/docs/user-guide/strict-types.md) * Operators: [+](/docs/parser/addition.md), [-](/docs/parser/subtraction.md), [*](/docs/parser/multiplication.md), [/](/docs/parser/division.md) +### Immutable Merge + +Returns the result of merging _right_ into _left_. + +_immutable merge_ does not modify the contents of either _left_ nor _right_. + +The direction of the arrow indicates that the result returned is a new value +rather than an updated assignment. + +| Operator | Name | Operation | +|----------|-----------------|---------------------------------------------| +| `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | + + ### Comparators All comparators replace the _left_, operator and _right_ with the returned @@ -147,7 +163,7 @@ Assignment is only supported in expressions. Read more: * Data types: [bool](/docs/types/bool.md) -* Operators: =, [<~](/docs/parser/assign-or-merge.md), [+=](/docs/parser/add-with.md), [-=](/docs/parser/subtract-by.md), [=](/docs/parser/multiply-by.md), [=](/docs/parser/divide-by.md) +* Operators: =, [<~](/docs/parser/assign-or-merge.md), [+=](/docs/parser/add-with.md), [-=](/docs/parser/subtract-by.md), [*=](/docs/parser/multiply-by.md), [/=](/docs/parser/divide-by.md) ### Conditionals diff --git a/gen/includes/expr-operators-tokens.inc.md b/gen/includes/expr-operators-tokens.inc.md index 72a0fa52e..95c257ca4 100644 --- a/gen/includes/expr-operators-tokens.inc.md +++ b/gen/includes/expr-operators-tokens.inc.md @@ -10,6 +10,7 @@ - [Operators And Tokens](#operators-and-tokens) - [Terminology](#terminology) - [Modifiers](#modifiers) + - [Immutable Merge](#immutable-merge) - [Comparators](#comparators) - [Assignment](#assignment) - [Conditionals](#conditionals) @@ -55,12 +56,13 @@ Order of operations: 2. sub-shells / sub-expressions 3. multiplication / division (expressions only) 4. addition / subtraction (expressions only) -5. comparisons, eg greater than -6. logical and (sub-expressions only) -7. logical or (sub-expressions only) -8. elvis (expressions only) -9. assign (expressions only) -10. _left_ to _right_ +5. immutable merge +6. comparisons, eg greater than (expressions only) +7. logical and (sub-expressions only) +8. logical or (sub-expressions only) +9. elvis (expressions only) +10. assign (expressions only) +11. _left_ to _right_ ### Expression Or Statement Discovery @@ -100,6 +102,20 @@ Read more: * Strict types config: {{link "strict types" "strict-types"}} * Operators: {{link "+" "addition"}}, {{link "-" "subtraction"}}, {{link "*" "multiplication"}}, {{link "/" "division"}} +### Immutable Merge + +Returns the result of merging _right_ into _left_. + +_immutable merge_ does not modify the contents of either _left_ nor _right_. + +The direction of the arrow indicates that the result returned is a new value +rather than an updated assignment. + +| Operator | Name | Operation | +|----------|-----------------|---------------------------------------------| +| `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | + + ### Comparators All comparators replace the _left_, operator and _right_ with the returned @@ -143,7 +159,7 @@ Assignment is only supported in expressions. Read more: * Data types: {{link "bool" "bool"}} -* Operators: {{link "=" "equals"}}, {{link "<~" "assign-or-merge"}}, {{link "+=" "add-with"}}, {{link "-=" "subtract-by"}}, {{link "=" "multiply-by"}}, {{link "=" "divide-by"}} +* Operators: {{link "=" "equals"}}, {{link "<~" "assign-or-merge"}}, {{link "+=" "add-with"}}, {{link "-=" "subtract-by"}}, {{link "*=" "multiply-by"}}, {{link "/=" "divide-by"}} ### Conditionals diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 271d68509..231b21f9f 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -149,7 +149,7 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { tree.appendAst(symbols.Like) tree.charPos++ case '>': - // merge into + // immutable merge tree.appendAst(symbols.Merge) tree.charPos++ default: From f3ad4f1a4dca016194cff8612b411c7a6a4e20c0 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 10 Aug 2024 22:08:59 +0100 Subject: [PATCH 025/142] website: updated landing page --- gen/root/README.inc.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index 8c88edf97..ceee5b73c 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -3,9 +3,9 @@ home: true icon: home heroImage: murex-logo-shell.svg?v={{ env "COMMITHASHSHORT" }} heroText: Murex.Rocks -tagline: An intuitive, typed and content aware shell for the 2020s and beyond. +tagline: An intuitive and content aware shell for a modern command line head: - - [meta, { property: "og-description", content: "An intuitive, typed and content aware shell for the 2020s and beyond." }] + - [meta, { property: "og-description", content: "An intuitive and content aware shell for a modern command line" }] actions: - text: " Language Tour" icon: "plane-departure" @@ -29,7 +29,7 @@ highlights: - title: Content Aware icon: file-contract details: |- - Murex has built-in support for natively manipulating various file formats such as JSON, TOML, YAML, CSV, and commonlog. This allows for seamless integration and manipulation of data in various formats. + Native support for manipulating data formats such as JSON, YAML, CSV, and others. This allows for seamless integration and manipulation of data in various formats.

Data types can be explicitly cast and reformatted, but also inferred if preferred. link: types/ @@ -37,7 +37,7 @@ highlights: - title: Expressions icon: hashtag details: |- - Murex treats variables as expressions, allowing you to perform calculations and evaluations directly within the shell. This feature helps to avoid accidental bugs caused by spaces or incorrect syntax, providing a more reliable and predictable scripting experience. + Smarter handling of variables and expressions to avoid accidental bugs caused by spaces or incorrect syntax. Resulting in a more reliable and predictable scripting experience.

Never worry about file names with weird characters, nor running equations in "bc" again. link: parser/ @@ -45,7 +45,7 @@ highlights: - title: Smartly Interactive icon: wand-magic-sparkles details: |- - Murex parses man pages for command line flags and provides smart autocomplete functionality. By pressing the TAB key, you can auto-complete commands and parameters, and "fzf"-like functionality baked in. + A uniquely intuitive interactive shell. With command line hints pulled from man pages, AI LLMs, and other intelligent integrations.

Navigating the command line is faster, more intuitive and efficient than ever before. link: user-guide/interactive-shell @@ -53,7 +53,7 @@ highlights: - title: Easily Extended icon: "puzzle-piece" details: |- - Murex has an extension framework that allows you to design your own modules or enjoy prebuilt extensions. This allows for customization and additional functionality. The built-in package manager makes it very easy to share your configuration, import other peoples modules, and port your set up between different machines. + An extension framework that allows you to design your own modules or enjoy prebuilt extensions. The built-in package manager makes it very easy to share your configuration, import other peoples modules, and port your set up between different machines.

Configure once, use everywhere. link: user-guide/modules From 5420373c42c14f963da8f62521931fcea8e42e49 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 10 Aug 2024 22:12:26 +0100 Subject: [PATCH 026/142] website: updated landing page --- gen/root/README.inc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index ceee5b73c..4c5a36253 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -53,7 +53,7 @@ highlights: - title: Easily Extended icon: "puzzle-piece" details: |- - An extension framework that allows you to design your own modules or enjoy prebuilt extensions. The built-in package manager makes it very easy to share your configuration, import other peoples modules, and port your set up between different machines. + The built-in package manager makes it very easy to share your configuration, import other peoples namespaced modules, and port your environment between different machines.

Configure once, use everywhere. link: user-guide/modules From c1ffcb17a40f8a57ad25b460ee934a0ef42e3688 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 11 Aug 2024 10:43:13 +0100 Subject: [PATCH 027/142] core: deprecate backtick, improvements to expr validation logic --- docs/commands/expr.md | 4 +-- lang/expressions/exp07_test.go | 6 ++--- lang/expressions/expression.go | 4 +-- lang/expressions/parse_block.go | 10 +++++--- lang/expressions/parse_function.go | 1 - lang/expressions/parse_quotes.go | 3 ++- lang/expressions/parse_statement.go | 2 +- lang/expressions/validate.go | 39 ++++++++++++++++++++++++----- lang/interpreter.go | 1 - 9 files changed, 49 insertions(+), 21 deletions(-) diff --git a/docs/commands/expr.md b/docs/commands/expr.md index 1770c0f36..d92204de4 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -263,9 +263,9 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.LessThanOrEqual: err = expGtLt(tree, _ltEqF, _ltEqS) - // 05. Bitwise shift left and right + // 05. Bitwise shift left and right - // 04.1 Merge + // 04.1 Merge case symbols.Merge: err = expMerge(tree) diff --git a/lang/expressions/exp07_test.go b/lang/expressions/exp07_test.go index bbbabb482..1a31d146a 100644 --- a/lang/expressions/exp07_test.go +++ b/lang/expressions/exp07_test.go @@ -355,17 +355,17 @@ func TestExprEquBugFixes(t *testing.T) { tests := []test.MurexTest{ { Block: `foobar == foobar`, - Stderr: `Error`, + Stderr: `cannot EqualTo`, ExitNum: 1, }, { Block: `"foobar" == foobar`, - Stderr: `Error`, + Stderr: `cannot EqualTo`, ExitNum: 1, }, { Block: `foobar == "foobar"`, - Stderr: `Error`, + Stderr: `cannot EqualTo`, ExitNum: 1, }, { diff --git a/lang/expressions/expression.go b/lang/expressions/expression.go index 48eb92ea2..d165ba6d6 100644 --- a/lang/expressions/expression.go +++ b/lang/expressions/expression.go @@ -145,9 +145,9 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.LessThanOrEqual: err = expGtLt(tree, _ltEqF, _ltEqS) - // 05. Bitwise shift left and right + // 05. Bitwise shift left and right - // 04.1 Merge + // 04.1 Merge case symbols.Merge: err = expMerge(tree) diff --git a/lang/expressions/parse_block.go b/lang/expressions/parse_block.go index 0dcb4dc8e..fa2798ada 100644 --- a/lang/expressions/parse_block.go +++ b/lang/expressions/parse_block.go @@ -279,15 +279,17 @@ func (blk *BlockT) ParseBlock() error { return err } - case tree == nil: - tree = NewParser(nil, blk.expression[blk.charPos:], 0) + default: + //case tree == nil: + tree = NewParser(nil, blk.expression[blk.charPos:], blk.charPos-1) newPos, err := tree.preParser() if err != nil { return err } blk.charPos += newPos - default: - blk.panic('=', '>') + + //default: + // blk.panic('=', '>') } case '>': diff --git a/lang/expressions/parse_function.go b/lang/expressions/parse_function.go index 0f5188341..f427fdb57 100644 --- a/lang/expressions/parse_function.go +++ b/lang/expressions/parse_function.go @@ -127,7 +127,6 @@ func (tree *ParserT) parseFunctionParameters(cmd []rune) ([]rune, error) { // generic pipe return nil, errNotAllowedInFunctions(cmd, "generic pipes", []rune(`=>`)...) default: - // assign value continue } diff --git a/lang/expressions/parse_quotes.go b/lang/expressions/parse_quotes.go index f0e2fe16d..fe73f6024 100644 --- a/lang/expressions/parse_quotes.go +++ b/lang/expressions/parse_quotes.go @@ -3,6 +3,7 @@ package expressions import ( "fmt" + "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/expressions/symbols" "github.com/lmorg/murex/utils/ansi" ) @@ -186,7 +187,7 @@ endString: func (tree *ParserT) parseBackTick(quote rune, exec bool) ([]rune, error) { if exec { - //lang.Deprecated("Automatic backtick (`) converstions to single quote (')", tree.p.FileRef) + lang.Deprecated("Automatic backtick (`) conversions to single quote (')", tree.p.FileRef) quote = '\'' } diff --git a/lang/expressions/parse_statement.go b/lang/expressions/parse_statement.go index a56a6f789..fa9e4f6b3 100644 --- a/lang/expressions/parse_statement.go +++ b/lang/expressions/parse_statement.go @@ -151,7 +151,6 @@ func (tree *ParserT) parseStatement(exec bool) error { tree.charPos-- return err default: - // assign value appendToParam(tree, r) } @@ -473,6 +472,7 @@ func (tree *ParserT) parseStatement(exec bool) error { case next == '[' && len(tree.statement.command) == 0 && len(tree.statement.paramTemp) == 0: // @[ command appendToParam(tree, '@', '[') + //lang.Deprecated(`@[`, tree.p.FileRef) tree.charPos++ if err := tree.nextParameter(); err != nil { return err diff --git a/lang/expressions/validate.go b/lang/expressions/validate.go index a43959348..3f26bd55c 100644 --- a/lang/expressions/validate.go +++ b/lang/expressions/validate.go @@ -62,19 +62,33 @@ func (tree *ParserT) validateExpression() error { } else { switch { + case prev == nil: + return raiseError(tree.expression, node, 0, fmt.Sprintf("nil symbol preceding %s", node.key)) + case next == nil: + return raiseError(tree.expression, node, 0, fmt.Sprintf("nil symbol following %s", node.key)) + case node.key < symbols.Operations: return raiseError(tree.expression, node, 0, "expecting an operation") case node.key >= symbols.Add: - if prev == nil || (prev.key != symbols.Number && prev.key != symbols.Calculated && prev.key != symbols.SubExpressionBegin && prev.key != symbols.Scalar) || - next == nil || (next.key != symbols.Number && next.key != symbols.Calculated && next.key != symbols.SubExpressionBegin && next.key != symbols.Scalar) { - return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s non-numeric data types", node.key)) + if !isSymbolNumeric(prev.key) { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s non-numeric data types, left is %s", node.key, prev.key)) + } + if !isSymbolNumeric(next.key) { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s non-numeric data types, right is %s", node.key, next.key)) } case node.key >= symbols.Elvis: - if prev == nil || prev.key == symbols.Bareword || - next == nil || next.key == symbols.Bareword { - return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s barewords", node.key)) + if prev.key == symbols.Bareword { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s %s", node.key, prev.key)) + } + if next.key == symbols.Bareword { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s %s", node.key, next.key)) + } + + default: + if !isSymbolAssignable(prev.key) { + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s to %s", node.key, prev.key)) } } } @@ -87,3 +101,16 @@ func (tree *ParserT) validateExpression() error { return nil } + +func isSymbolNumeric(sym symbols.Exp) bool { + return sym == symbols.Number || + sym == symbols.Calculated || + sym == symbols.SubExpressionBegin || + sym == symbols.Scalar +} + +func isSymbolAssignable(sym symbols.Exp) bool { + return sym == symbols.Bareword || + sym == symbols.Scalar || + sym == symbols.SubExpressionBegin +} diff --git a/lang/interpreter.go b/lang/interpreter.go index 1aa382360..1357b5eb1 100644 --- a/lang/interpreter.go +++ b/lang/interpreter.go @@ -150,7 +150,6 @@ func compile(tree *[]functions.FunctionT, parent *Process) (*[]Process, int) { case (*tree)[i].Properties.NewChain(): // new chain procs[i].Stdin = streams.NewStdin() - //procs[i].Stdin = new(null.Null) } // Define stdout / stderr interfaces: From f93441342815075acdf1e3ea635e6c0f3bd97e5f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 11 Aug 2024 10:56:46 +0100 Subject: [PATCH 028/142] tests: comment out expr07 tests that are broken from improved expr validation [854] --- lang/expressions/exp07_test.go | 4 ++-- lang/expressions/validate.go | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lang/expressions/exp07_test.go b/lang/expressions/exp07_test.go index 1a31d146a..a46f393f7 100644 --- a/lang/expressions/exp07_test.go +++ b/lang/expressions/exp07_test.go @@ -353,7 +353,7 @@ func TestExpNotRegexp(t *testing.T) { // https://github.com/lmorg/murex/issues/831 func TestExprEquBugFixes(t *testing.T) { tests := []test.MurexTest{ - { + /*{ Block: `foobar == foobar`, Stderr: `cannot EqualTo`, ExitNum: 1, @@ -372,7 +372,7 @@ func TestExprEquBugFixes(t *testing.T) { Block: `"foobar" == "foobar"`, Stdout: `true`, ExitNum: 0, - }, + },*/ ///// { Block: `%[z y x] == %[z y x]`, diff --git a/lang/expressions/validate.go b/lang/expressions/validate.go index 3f26bd55c..4536ab0f4 100644 --- a/lang/expressions/validate.go +++ b/lang/expressions/validate.go @@ -68,7 +68,7 @@ func (tree *ParserT) validateExpression() error { return raiseError(tree.expression, node, 0, fmt.Sprintf("nil symbol following %s", node.key)) case node.key < symbols.Operations: - return raiseError(tree.expression, node, 0, "expecting an operation") + return raiseError(tree.expression, node, 0, fmt.Sprintf("expecting an operation, instead got %s", node.key)) case node.key >= symbols.Add: if !isSymbolNumeric(prev.key) { @@ -80,10 +80,10 @@ func (tree *ParserT) validateExpression() error { case node.key >= symbols.Elvis: if prev.key == symbols.Bareword { - return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s %s", node.key, prev.key)) + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s left %s", node.key, prev.key)) } if next.key == symbols.Bareword { - return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s %s", node.key, next.key)) + return raiseError(tree.expression, node, 0, fmt.Sprintf("cannot %s right %s", node.key, next.key)) } default: From 208ee9a852666b25c05a526f51468b82cc8a3f05 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 11 Aug 2024 11:24:36 +0100 Subject: [PATCH 029/142] docs: tour --- docs/tour.md | 5 +++-- gen/root/tour.inc.md | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/tour.md b/docs/tour.md index dc99a21a0..22a2aecf0 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -5,6 +5,7 @@
- [Introduction](#introduction) + - [Murex is a Typed Shell](#murex-is-a-typed-shell) - [Read–Eval–Print Loop](#readevalprint-loop) - [Barewords](#barewords) - [Expressions and Statements](#expressions-and-statements) @@ -53,7 +54,7 @@ ## Introduction -Murex is a typed shell. +### Murex is a Typed Shell Unlike other typed shells, Murex can still work natively with existing CLI tools without any tweaks. @@ -362,7 +363,7 @@ out [1,2,3] | :json: foreach { ... } ## Sub-Shells -There are two types of emendable sub-shells: strings and arrays. +There are two main types of emendable sub-shells: strings and arrays. * string sub-shells, `${ command }`, take the results from the sub-shell and return it as a single parameter. This saves the need to encapsulate the shell diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 98107378a..1990793b2 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -11,6 +11,7 @@
- [Introduction](#introduction) + - [Murex is a Typed Shell](#murex-is-a-typed-shell) - [Read–Eval–Print Loop](#readevalprint-loop) - [Barewords](#barewords) - [Expressions and Statements](#expressions-and-statements) @@ -59,7 +60,7 @@ {{ end }} ## Introduction -Murex is a typed shell. +### Murex is a Typed Shell Unlike other typed shells, Murex can still work natively with existing CLI tools without any tweaks. @@ -372,7 +373,7 @@ out [1,2,3] | :json: foreach { ... } ## Sub-Shells -There are two types of emendable sub-shells: strings and arrays. +There are two main types of emendable sub-shells: strings and arrays. * string sub-shells, `${ command }`, take the results from the sub-shell and return it as a single parameter. This saves the need to encapsulate the shell From acb09b0ef7a88de42aad79e8ae5aeaa933d9e0fa Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 11 Aug 2024 21:38:35 +0100 Subject: [PATCH 030/142] builtin: `for` syntax changed --- app/app.go | 2 +- builtins/core/io/read.go | 2 +- builtins/core/ranges/ranges.go | 2 +- builtins/core/structs/for.go | 26 ++++++++++++-------- builtins/core/structs/for_doc.yaml | 37 +++++++++++++++-------------- builtins/core/structs/for_test.go | 2 +- builtins/core/typemgmt/let.go | 2 +- builtins/core/typemgmt/math.go | 2 +- docs/commands/for.md | 37 +++++++++++++++-------------- docs/tour.md | 15 ++++++------ gen/root/tour.inc.md | 15 ++++++------ lang/deprecated.go | 20 ++++++++++++---- lang/expressions/parse_block.go | 2 +- lang/expressions/parse_quotes.go | 2 +- lang/expressions/statement_rules.go | 2 +- version.svg | 2 +- 16 files changed, 93 insertions(+), 77 deletions(-) diff --git a/app/app.go b/app/app.go index 385f9e4df..c25755f4f 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 1400 + Revision = 2000 ) // Copyright is the copyright owner string diff --git a/builtins/core/io/read.go b/builtins/core/io/read.go index b97865be5..a3e790360 100644 --- a/builtins/core/io/read.go +++ b/builtins/core/io/read.go @@ -24,7 +24,7 @@ func cmdRead(p *lang.Process) error { } func cmdTread(p *lang.Process) error { - lang.DeprecatedBuiltin(p) + lang.FeatureDeprecatedBuiltin(p) dt, err := p.Parameters.String(0) if err != nil { diff --git a/builtins/core/ranges/ranges.go b/builtins/core/ranges/ranges.go index 458c4fb18..554111a00 100644 --- a/builtins/core/ranges/ranges.go +++ b/builtins/core/ranges/ranges.go @@ -22,7 +22,7 @@ const usage = "\nUsage: [start..end] / [start..end]se\n(start or end can be omit var RxSplitRange = regexp.MustCompile(`^\s*(.*?)\s*\.\.\s*(.*?)\s*\]([bt8ernsiu]*)\s*$`) func deprecatedRange(p *lang.Process) error { - lang.DeprecatedBuiltin(p) + lang.FeatureDeprecatedBuiltin(p) return CmdRange(p) } diff --git a/builtins/core/structs/for.go b/builtins/core/structs/for.go index f35bc6f3f..b51c18c17 100644 --- a/builtins/core/structs/for.go +++ b/builtins/core/structs/for.go @@ -2,6 +2,7 @@ package structs import ( "errors" + "fmt" "strings" "github.com/lmorg/murex/lang" @@ -12,14 +13,23 @@ func init() { lang.DefineFunction("for", cmdFor, types.Generic) } +const ( + _VARIABLE = 0 + _CONDITIONAL = 1 + _INCREMENTAL = 2 +) + +const _FOR_WARNING = "The syntax for `for` has changed and the old syntax is no longer valid.\nFor more information on it's usage, either:\n* Visit https://murex.rocks/commands/for.html in your preferred browser\n* or run `murex-docs for` from the command line " + // Example usage: -// for ( i=1; i<6; i++ ) { echo $i } +// for { $i=1; $i<6; $i=$i+1 } { echo $i } func cmdFor(p *lang.Process) (err error) { p.Stdout.SetDataType(types.Generic) - cblock, err := p.Parameters.String(0) + cblock, err := p.Parameters.Block(0) if err != nil { - return err + lang.FeatureWarning(_FOR_WARNING, p.FileRef) + return fmt.Errorf(_FOR_WARNING) } block, err := p.Parameters.Block(1) @@ -32,17 +42,13 @@ func cmdFor(p *lang.Process) (err error) { return errors.New("invalid syntax. Must be ( variable; conditional; incremental )") } - variable := "let " + parameters[0] - conditional := "= " + parameters[1] - incremental := "let " + parameters[2] - - _, err = p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN | lang.F_NO_STDOUT).Execute([]rune(variable)) + _, err = p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN | lang.F_NO_STDOUT).Execute([]rune(parameters[_VARIABLE])) if err != nil { return err } - rConditional := []rune(conditional) - rIncremental := []rune(incremental) + rConditional := []rune(parameters[_CONDITIONAL]) + rIncremental := []rune(parameters[_INCREMENTAL]) for { if p.HasCancelled() { diff --git a/builtins/core/structs/for_doc.yaml b/builtins/core/structs/for_doc.yaml index 24ea25808..48b7c0086 100644 --- a/builtins/core/structs/for_doc.yaml +++ b/builtins/core/structs/for_doc.yaml @@ -6,16 +6,16 @@ A more familiar iteration loop to existing developers Description: |- This `for` loop is fills a small niche where `foreach` or `formap` are - inappropiate in your script. It's generally not recommended to use `for` + inappropriate in your script. It's generally not recommended to use `for` because it performs slower and doesn't adhere to Murex's design philosophy. However it does offer additional flexibility around recursion. Usage: |- ``` - for ( variable; conditional; incrementation ) { code-block } -> + for { variable; conditional; incrementor } { code-block } -> ``` Examples: |- ``` - » for ( i=1; i<6; i++ ) { echo $i } + » for { $i=1; $i<6; $i=$i+1 } { echo $i } 1 2 3 @@ -30,23 +30,29 @@ to the first parameter being entered as one string treated as 3 separate code blocks. The syntax is like this for two reasons: - 1. readability (having multiple `{ blocks }` would make scripts unsightly - 2. familiarity (for those using to `for` loops in other languages + 1. readability, having multiple `{ blocks }` would make scripts unsightly + 2. familiarity for those using to `for` loops in other languages - The first parameter is: `( i=1; i<6; i++ )`, but it is then converted into the + Take the following example: + + ``` + for { $i=1; $i<6; $i=$i+1} { echo $i } + ``` + + The first parameter is: `{ $i=1; $i<6; $i=$i+1 }`, but it is then converted into the following code: - 1. `let i=0` - declare the loop iteration variable - 2. `= i<0` - if the condition is true then proceed to run the code in + 1. `$i=1` - declare the loop iteration variable + 2. `$i<6` - if the condition is true then proceed to run the code in the second parameter - `{ echo $i }` - 3. `let i++` - increment the loop iteration variable + 3. `$i=$i+1` - increment the loop iterator variable The second parameter is the code to execute upon each iteration ### Better `for` loops Because each iteration of a `for` loop reruns the 2nd 2 parts in the first - parameter (the conditional and incrementation), `for` is very slow. Plus the + parameter (the conditional and incrementor), `for` is very slow. Plus the weird, non-idiomatic, way of writing the 3 parts, it's fair to say `for` is not the recommended method of iteration and in fact there are better functions to achieve the same thing...most of the time at least. @@ -68,25 +74,20 @@ » time { a [1..9999] -> foreach i { out $i } } 0.097643108 - » time { for ( i=1; i<10000; i=i+1 ) { out $i } } + » time { for { $i=1; $i<10000; $i=$i+1 } { out $i } } 0.663812496 ``` You can also do step ranges with `foreach`: ``` - » time { for ( i=10; i<10001; i=i+2 ) { out $i } } + » time { for ( $i=10; $i<10001; $i=$i+2 ) { out $i } } 0.346254973 - » time { a [1..999][0,2,4,6,8],10000 -> foreach i { out $i } } + » time { %[1..10001] -> foreach --step 2 i { out $i } } 0.053924326 ``` - ...though granted the latter is a little less readable. - - The big catch with using `a` piped into `foreach` is that values are passed - as strings rather than numbers. - {{ include "gen/includes/for-loop-json-tips.inc.md" }} Synonyms: Related: diff --git a/builtins/core/structs/for_test.go b/builtins/core/structs/for_test.go index b5ceb397a..e815e3db4 100644 --- a/builtins/core/structs/for_test.go +++ b/builtins/core/structs/for_test.go @@ -10,7 +10,7 @@ import ( func TestFor(t *testing.T) { tests := []test.MurexTest{ { - Block: `for ( i=1; i<6; i++ ) { echo $i }`, + Block: `for { $i=1; $i<6; $i=$i+1 } { echo $i }`, Stdout: "1\n2\n3\n4\n5\n", }, } diff --git a/builtins/core/typemgmt/let.go b/builtins/core/typemgmt/let.go index 0ab33ec1a..669ac2005 100644 --- a/builtins/core/typemgmt/let.go +++ b/builtins/core/typemgmt/let.go @@ -22,7 +22,7 @@ func init() { } func cmdLet(p *lang.Process) (err error) { - lang.DeprecatedBuiltin(p) + lang.FeatureDeprecatedBuiltin(p) if !debug.Enabled { defer func() { diff --git a/builtins/core/typemgmt/math.go b/builtins/core/typemgmt/math.go index 3415ceaef..40bf989cf 100644 --- a/builtins/core/typemgmt/math.go +++ b/builtins/core/typemgmt/math.go @@ -16,7 +16,7 @@ func init() { } func cmdEqu(p *lang.Process) (err error) { - lang.DeprecatedBuiltin(p) + lang.FeatureDeprecatedBuiltin(p) if p.Parameters.Len() == 0 { return errors.New("missing expression") diff --git a/docs/commands/for.md b/docs/commands/for.md index 8a6460748..2b23cd1ec 100644 --- a/docs/commands/for.md +++ b/docs/commands/for.md @@ -5,20 +5,20 @@ ## Description This `for` loop is fills a small niche where `foreach` or `formap` are -inappropiate in your script. It's generally not recommended to use `for` +inappropriate in your script. It's generally not recommended to use `for` because it performs slower and doesn't adhere to Murex's design philosophy. However it does offer additional flexibility around recursion. ## Usage ``` -for ( variable; conditional; incrementation ) { code-block } -> +for { variable; conditional; incrementor } { code-block } -> ``` ## Examples ``` -» for ( i=1; i<6; i++ ) { echo $i } +» for { $i=1; $i<6; $i=$i+1 } { echo $i } 1 2 3 @@ -34,23 +34,29 @@ for ( variable; conditional; incrementation ) { code-block } -> to the first parameter being entered as one string treated as 3 separate code blocks. The syntax is like this for two reasons: -1. readability (having multiple `{ blocks }` would make scripts unsightly -2. familiarity (for those using to `for` loops in other languages +1. readability, having multiple `{ blocks }` would make scripts unsightly +2. familiarity for those using to `for` loops in other languages -The first parameter is: `( i=1; i<6; i++ )`, but it is then converted into the +Take the following example: + +``` +for { $i=1; $i<6; $i=$i+1} { echo $i } +``` + +The first parameter is: `{ $i=1; $i<6; $i=$i+1 }`, but it is then converted into the following code: -1. `let i=0` - declare the loop iteration variable -2. `= i<0` - if the condition is true then proceed to run the code in +1. `$i=1` - declare the loop iteration variable +2. `$i<6` - if the condition is true then proceed to run the code in the second parameter - `{ echo $i }` -3. `let i++` - increment the loop iteration variable +3. `$i=$i+1` - increment the loop iterator variable The second parameter is the code to execute upon each iteration ### Better `for` loops Because each iteration of a `for` loop reruns the 2nd 2 parts in the first -parameter (the conditional and incrementation), `for` is very slow. Plus the +parameter (the conditional and incrementor), `for` is very slow. Plus the weird, non-idiomatic, way of writing the 3 parts, it's fair to say `for` is not the recommended method of iteration and in fact there are better functions to achieve the same thing...most of the time at least. @@ -72,25 +78,20 @@ The different in performance can be measured. eg: » time { a [1..9999] -> foreach i { out $i } } 0.097643108 -» time { for ( i=1; i<10000; i=i+1 ) { out $i } } +» time { for { $i=1; $i<10000; $i=$i+1 } { out $i } } 0.663812496 ``` You can also do step ranges with `foreach`: ``` -» time { for ( i=10; i<10001; i=i+2 ) { out $i } } +» time { for ( $i=10; $i<10001; $i=$i+2 ) { out $i } } 0.346254973 -» time { a [1..999][0,2,4,6,8],10000 -> foreach i { out $i } } +» time { %[1..10001] -> foreach --step 2 i { out $i } } 0.053924326 ``` -...though granted the latter is a little less readable. - -The big catch with using `a` piped into `foreach` is that values are passed -as strings rather than numbers. - ### Tips when writing JSON inside for loops One of the drawbacks (or maybe advantages, depending on your perspective) of diff --git a/docs/tour.md b/docs/tour.md index 22a2aecf0..c0f7ef95b 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -5,7 +5,6 @@
- [Introduction](#introduction) - - [Murex is a Typed Shell](#murex-is-a-typed-shell) - [Read–Eval–Print Loop](#readevalprint-loop) - [Barewords](#barewords) - [Expressions and Statements](#expressions-and-statements) @@ -54,7 +53,7 @@ ## Introduction -### Murex is a Typed Shell +Murex is a typed shell. Unlike other typed shells, Murex can still work natively with existing CLI tools without any tweaks. @@ -83,8 +82,8 @@ readability and terseness is to make heavy use of barewords. Barewords are ostensibly just instructions that are not quoted. In our case, command names and command parameters. -Murex also makes heavy use of barewords and so that places requirements on -the choice of syntax we can use. +Murex also makes heavy use of barewords and so that places restrictions on the +choice of syntax we can use. ### Expressions and Statements @@ -336,7 +335,7 @@ out "message" >> append-file.txt ### Type Conversion Aside from annotating variables upon definition, you can also transform data -along the pipeline. +along the pipeline using `format`. #### Cast @@ -379,9 +378,9 @@ touch ${ %[1,2,3] } # creates a file named '[1,2,3]' touch @{ %[1,2,3] } # creates three files, named '1', '2' and '3' ``` -The reason Murex breaks from the POSIX tradition of using backticks and -parentheses is because Murex works on the principle that everything inside -a curly bracket is considered a new block of code. +The reason Murex breaks from the traditions of using backticks and parentheses +is because Murex works on the principle that everything inside a curly bracket +is considered a new block of code. ## Filesystem Wildcards (Globbing) diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 1990793b2..6a15c4311 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -11,7 +11,6 @@
- [Introduction](#introduction) - - [Murex is a Typed Shell](#murex-is-a-typed-shell) - [Read–Eval–Print Loop](#readevalprint-loop) - [Barewords](#barewords) - [Expressions and Statements](#expressions-and-statements) @@ -60,7 +59,7 @@ {{ end }} ## Introduction -### Murex is a Typed Shell +Murex is a typed shell. Unlike other typed shells, Murex can still work natively with existing CLI tools without any tweaks. @@ -93,8 +92,8 @@ readability and terseness is to make heavy use of barewords. Barewords are ostensibly just instructions that are not quoted. In our case, command names and command parameters. -Murex also makes heavy use of barewords and so that places requirements on -the choice of syntax we can use. +Murex also makes heavy use of barewords and so that places restrictions on the +choice of syntax we can use. ### Expressions and Statements @@ -346,7 +345,7 @@ out "message" >> append-file.txt ### Type Conversion Aside from annotating variables upon definition, you can also transform data -along the pipeline. +along the pipeline using `format`. #### Cast @@ -389,9 +388,9 @@ touch ${ %[1,2,3] } # creates a file named '[1,2,3]' touch @{ %[1,2,3] } # creates three files, named '1', '2' and '3' ``` -The reason Murex breaks from the POSIX tradition of using backticks and -parentheses is because Murex works on the principle that everything inside -a curly bracket is considered a new block of code. +The reason Murex breaks from the traditions of using backticks and parentheses +is because Murex works on the principle that everything inside a curly bracket +is considered a new block of code. ## Filesystem Wildcards (Globbing) diff --git a/lang/deprecated.go b/lang/deprecated.go index f1dd928ea..758386861 100644 --- a/lang/deprecated.go +++ b/lang/deprecated.go @@ -3,21 +3,31 @@ package lang import ( "fmt" "os" + "strings" "time" "github.com/lmorg/murex/app" "github.com/lmorg/murex/lang/ref" ) -func DeprecatedBuiltin(p *Process) { - Deprecated(fmt.Sprintf("WARNING: The builtin `%s`", p.Name.String()), p.FileRef) +func FeatureDeprecatedBuiltin(p *Process) { + FeatureDeprecated(fmt.Sprintf("The builtin `%s`", p.Name.String()), p.FileRef) } -func Deprecated(message string, fileRef *ref.File) { +func FeatureDeprecated(message string, fileRef *ref.File) { + s := fmt.Sprintf("%s has been deprecated and will be removed in the v%d.0 release", + message, app.Major+1) + + FeatureWarning(s, fileRef) +} + +func FeatureWarning(message string, fileRef *ref.File) { fileRef = _fileRefUnknown(fileRef) - s := fmt.Sprintf("!!! %s has been deprecated and will be removed in the v%d.0 release\n!!! : Module: %s\n!!! : File: %s\n!!! : Line: %d\n!!! : Column: %d\n", - message, app.Major+1, + message = strings.ReplaceAll(message, "\n", "\n!!! > ") + + s := fmt.Sprintf("!!! WARNING: %s\n!!! : Module: %s\n!!! : File: %s\n!!! : Line: %d\n!!! : Column: %d\n", + message, fileRef.Source.Module, fileRef.Source.Filename, fileRef.Line, fileRef.Column) os.Stderr.WriteString(s) } diff --git a/lang/expressions/parse_block.go b/lang/expressions/parse_block.go index fa2798ada..8d7d019a9 100644 --- a/lang/expressions/parse_block.go +++ b/lang/expressions/parse_block.go @@ -258,7 +258,7 @@ func (blk *BlockT) ParseBlock() error { Column: blk.charPos, //Source: tree.p.FileRef.Source, } - lang.Deprecated(message, fileRef) + lang.FeatureDeprecated(message, fileRef) if err := blk.append(tree, fn.P_PIPE_ERR, fn.P_FOLLOW_ON|fn.P_METHOD); err != nil { return err diff --git a/lang/expressions/parse_quotes.go b/lang/expressions/parse_quotes.go index fe73f6024..19fbe9f65 100644 --- a/lang/expressions/parse_quotes.go +++ b/lang/expressions/parse_quotes.go @@ -187,7 +187,7 @@ endString: func (tree *ParserT) parseBackTick(quote rune, exec bool) ([]rune, error) { if exec { - lang.Deprecated("Automatic backtick (`) conversions to single quote (')", tree.p.FileRef) + lang.FeatureDeprecated("Automatic backtick (`) conversions to single quote (')", tree.p.FileRef) quote = '\'' } diff --git a/lang/expressions/statement_rules.go b/lang/expressions/statement_rules.go index 982388fc0..764f0c31f 100644 --- a/lang/expressions/statement_rules.go +++ b/lang/expressions/statement_rules.go @@ -4,7 +4,7 @@ import "github.com/lmorg/murex/utils/lists" var tokeniseCurlyBraceCommands = []string{ "if", "!if", - "foreach", "formap", + "foreach", "formap", "for", "switch", } diff --git a/version.svg b/version.svg index 60ecf37a5..bdecfe28d 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.1400Version6.3.1400 +Version: 6.3.2000Version6.3.2000 From 25c29dc5af726a5ff9395c3349b212c746934d85 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 11 Aug 2024 22:02:33 +0100 Subject: [PATCH 031/142] #854 core bugfix: statements as expressions when 1st param `=` --- lang/expressions/exp07_test.go | 21 ------------ lang/expressions/parse_block.go | 9 ++---- lang/expressions/parse_block_test.go | 48 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/lang/expressions/exp07_test.go b/lang/expressions/exp07_test.go index a46f393f7..6ee9fe4a1 100644 --- a/lang/expressions/exp07_test.go +++ b/lang/expressions/exp07_test.go @@ -353,27 +353,6 @@ func TestExpNotRegexp(t *testing.T) { // https://github.com/lmorg/murex/issues/831 func TestExprEquBugFixes(t *testing.T) { tests := []test.MurexTest{ - /*{ - Block: `foobar == foobar`, - Stderr: `cannot EqualTo`, - ExitNum: 1, - }, - { - Block: `"foobar" == foobar`, - Stderr: `cannot EqualTo`, - ExitNum: 1, - }, - { - Block: `foobar == "foobar"`, - Stderr: `cannot EqualTo`, - ExitNum: 1, - }, - { - Block: `"foobar" == "foobar"`, - Stdout: `true`, - ExitNum: 0, - },*/ - ///// { Block: `%[z y x] == %[z y x]`, Stdout: `true`, diff --git a/lang/expressions/parse_block.go b/lang/expressions/parse_block.go index 8d7d019a9..c19010cb9 100644 --- a/lang/expressions/parse_block.go +++ b/lang/expressions/parse_block.go @@ -79,17 +79,14 @@ func (tree *ParserT) preParser() (int, error) { } stErr = tree.statement.validate() + if stErr != nil { + return 0, stErr + } if len(tree.statement.command) == 0 { return 0, errors.New("you cannot have zero length commands") } - if stErr == nil && !tree.statement.asStatement && - len(tree.statement.parameters) > 0 && len(tree.statement.parameters[0]) > 0 && tree.statement.parameters[0][0] == '=' { - // i _still_ think this is probably an expression - return 0, expErr - } - return tree.charPos, nil } diff --git a/lang/expressions/parse_block_test.go b/lang/expressions/parse_block_test.go index c4d8b3066..5c8777f2e 100644 --- a/lang/expressions/parse_block_test.go +++ b/lang/expressions/parse_block_test.go @@ -376,3 +376,51 @@ func TestAlterOp(t *testing.T) { test.RunMurexTests(tests, t) } + +func TestIssue854(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj== TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `"TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"== TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj== "TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `"TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"== "TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"`, + Stdout: `true`, + ExitNum: 0, + }, + ///// + { + Block: `TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj == TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `"TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj" == TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj == "TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"`, + Stderr: `cannot EqualTo`, + ExitNum: 1, + }, + { + Block: `"TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj" == "TestIssue854_alksdlsdkfjsldfkjsldfkjsldfkjsldkfj"`, + Stdout: `true`, + ExitNum: 0, + }, + } + + test.RunMurexTestsRx(tests, t) +} From cd69d9d45924d95e1443b746d0927128a212446d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 15 Aug 2024 00:05:41 +0300 Subject: [PATCH 032/142] expressions: plus plus --- builtins/core/structs/for_doc.yaml | 57 ++++--------------------- docs/commands/expr.md | 2 + docs/commands/for.md | 57 ++++--------------------- docs/parser/README.md | 3 +- docs/user-guide/operators-and-tokens.md | 3 +- lang/expressions/ast.go | 30 ++++++++++++- lang/expressions/exp04.go | 39 +++++++++++++++++ lang/expressions/expression.go | 2 + lang/expressions/parse_expression.go | 13 +++--- lang/expressions/symbols/exp.go | 2 + lang/expressions/symbols/exp_string.go | 16 ++++--- lang/expressions/validate.go | 7 +++ 12 files changed, 120 insertions(+), 111 deletions(-) diff --git a/builtins/core/structs/for_doc.yaml b/builtins/core/structs/for_doc.yaml index 48b7c0086..4e45e787a 100644 --- a/builtins/core/structs/for_doc.yaml +++ b/builtins/core/structs/for_doc.yaml @@ -15,12 +15,12 @@ ``` Examples: |- ``` - » for { $i=1; $i<6; $i=$i+1 } { echo $i } - 1 - 2 - 3 - 4 - 5 + » for {$i=1; $i<6; $i++} { out "iteration $i" } + iteration 1 + iteration 2 + iteration 3 + iteration 4 + iteration 5 ``` Flags: Detail: |- @@ -36,58 +36,19 @@ Take the following example: ``` - for { $i=1; $i<6; $i=$i+1} { echo $i } + for {$i=1; $i<6; $i++} { out "iteration $i" } ``` - The first parameter is: `{ $i=1; $i<6; $i=$i+1 }`, but it is then converted into the + The first parameter is: `{$i=1; $i<6; $i++}`, this is then converted into the following code: 1. `$i=1` - declare the loop iteration variable 2. `$i<6` - if the condition is true then proceed to run the code in the second parameter - `{ echo $i }` - 3. `$i=$i+1` - increment the loop iterator variable + 3. `$i++` - increment the loop iterator variable The second parameter is the code to execute upon each iteration - ### Better `for` loops - - Because each iteration of a `for` loop reruns the 2nd 2 parts in the first - parameter (the conditional and incrementor), `for` is very slow. Plus the - weird, non-idiomatic, way of writing the 3 parts, it's fair to say `for` is - not the recommended method of iteration and in fact there are better functions - to achieve the same thing...most of the time at least. - - For example: - - ``` - a [1..5] -> foreach i { echo $i } - 1 - 2 - 3 - 4 - 5 - ``` - - The different in performance can be measured. eg: - - ``` - » time { a [1..9999] -> foreach i { out $i } } - 0.097643108 - - » time { for { $i=1; $i<10000; $i=$i+1 } { out $i } } - 0.663812496 - ``` - - You can also do step ranges with `foreach`: - - ``` - » time { for ( $i=10; $i<10001; $i=$i+2 ) { out $i } } - 0.346254973 - - » time { %[1..10001] -> foreach --step 2 i { out $i } } - 0.053924326 - ``` - {{ include "gen/includes/for-loop-json-tips.inc.md" }} Synonyms: Related: diff --git a/docs/commands/expr.md b/docs/commands/expr.md index d92204de4..5b24f5dca 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -270,6 +270,8 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { err = expMerge(tree) // 04. Addition and subtraction + case symbols.PlusPlus: + err = expPlusPlus(tree) case symbols.Add: err = expAdd(tree) case symbols.Subtract: diff --git a/docs/commands/for.md b/docs/commands/for.md index 2b23cd1ec..b4fcd16e0 100644 --- a/docs/commands/for.md +++ b/docs/commands/for.md @@ -18,12 +18,12 @@ for { variable; conditional; incrementor } { code-block } -> ## Examples ``` -» for { $i=1; $i<6; $i=$i+1 } { echo $i } -1 -2 -3 -4 -5 +» for {$i=1; $i<6; $i++} { out "iteration $i" } +iteration 1 +iteration 2 +iteration 3 +iteration 4 +iteration 5 ``` ## Detail @@ -40,58 +40,19 @@ blocks. The syntax is like this for two reasons: Take the following example: ``` -for { $i=1; $i<6; $i=$i+1} { echo $i } +for {$i=1; $i<6; $i++} { out "iteration $i" } ``` -The first parameter is: `{ $i=1; $i<6; $i=$i+1 }`, but it is then converted into the +The first parameter is: `{$i=1; $i<6; $i++}`, this is then converted into the following code: 1. `$i=1` - declare the loop iteration variable 2. `$i<6` - if the condition is true then proceed to run the code in the second parameter - `{ echo $i }` -3. `$i=$i+1` - increment the loop iterator variable +3. `$i++` - increment the loop iterator variable The second parameter is the code to execute upon each iteration -### Better `for` loops - -Because each iteration of a `for` loop reruns the 2nd 2 parts in the first -parameter (the conditional and incrementor), `for` is very slow. Plus the -weird, non-idiomatic, way of writing the 3 parts, it's fair to say `for` is -not the recommended method of iteration and in fact there are better functions -to achieve the same thing...most of the time at least. - -For example: - -``` -a [1..5] -> foreach i { echo $i } -1 -2 -3 -4 -5 -``` - -The different in performance can be measured. eg: - -``` -» time { a [1..9999] -> foreach i { out $i } } -0.097643108 - -» time { for { $i=1; $i<10000; $i=$i+1 } { out $i } } -0.663812496 -``` - -You can also do step ranges with `foreach`: - -``` -» time { for ( $i=10; $i<10001; $i=$i+2 ) { out $i } } -0.346254973 - -» time { %[1..10001] -> foreach --step 2 i { out $i } } -0.053924326 -``` - ### Tips when writing JSON inside for loops One of the drawbacks (or maybe advantages, depending on your perspective) of diff --git a/docs/parser/README.md b/docs/parser/README.md index a087be809..5c4a84194 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -145,7 +145,7 @@ Read more: ### Assignment -Assignment returns `true` if successful. +Assignment returns `null` if successful. Assignment is only supported in expressions. @@ -158,6 +158,7 @@ Assignment is only supported in expressions. | `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | | `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | | `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | Read more: * Data types: [bool](/docs/types/bool.md) diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index c714149af..2d7fd2494 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -147,7 +147,7 @@ Read more: ### Assignment -Assignment returns `true` if successful. +Assignment returns `null` if successful. Assignment is only supported in expressions. @@ -160,6 +160,7 @@ Assignment is only supported in expressions. | `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | | `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | | `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | Read more: * Data types: [bool](/docs/types/bool.md) diff --git a/lang/expressions/ast.go b/lang/expressions/ast.go index 5b340280d..2494d52bf 100644 --- a/lang/expressions/ast.go +++ b/lang/expressions/ast.go @@ -90,7 +90,7 @@ func (tree *ParserT) foldAst(new *astNodeT) error { case tree.astPos >= len(tree.ast)-1: return fmt.Errorf("cannot fold when tree.astPos<%d> >= len(tree.ast)-1<%d> (%s)", - tree.astPos, len(tree.ast), consts.IssueTrackerURL) + tree.astPos, len(tree.ast)-1, consts.IssueTrackerURL) case len(tree.ast) == 3: tree.ast = []*astNodeT{new} @@ -110,6 +110,34 @@ func (tree *ParserT) foldAst(new *astNodeT) error { return nil } +func (tree *ParserT) foldLeftAst(new *astNodeT) error { + switch { + case tree.astPos <= 0: + return fmt.Errorf("cannot fold when tree.astPos<%d> <= 0<%d> (%s)", + tree.astPos, len(tree.ast), consts.IssueTrackerURL) + + case tree.astPos >= len(tree.ast): + return fmt.Errorf("cannot fold when tree.astPos<%d> >= len(tree.ast)<%d> (%s)", + tree.astPos, len(tree.ast), consts.IssueTrackerURL) + + case len(tree.ast) == 2: + tree.ast = []*astNodeT{new} + + case tree.astPos == 1: + tree.ast = append([]*astNodeT{new}, tree.ast[2:]...) + + case tree.astPos == len(tree.ast)-1: + tree.ast = append(tree.ast[:len(tree.ast)-2], new) + + default: + start := append(tree.ast[:tree.astPos-1], new) + end := tree.ast[tree.astPos+1:] + tree.ast = append(start, end...) + } + + return nil +} + // memory safe func (tree *ParserT) prevSymbol() *astNodeT { if tree.astPos-1 < 0 { diff --git a/lang/expressions/exp04.go b/lang/expressions/exp04.go index 6c3eddaae..e6571a6ee 100644 --- a/lang/expressions/exp04.go +++ b/lang/expressions/exp04.go @@ -5,6 +5,7 @@ import ( "github.com/lmorg/murex/lang/expressions/primitives" "github.com/lmorg/murex/lang/expressions/symbols" + "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/alter" ) @@ -89,3 +90,41 @@ func expMerge(tree *ParserT) error { dt: primitives.NewScalar(right.DataType, merged), }) } + +func expPlusPlus(tree *ParserT) error { + left := tree.prevSymbol() + + if left == nil { + return raiseError(tree.expression, tree.ast[tree.astPos], 0, "missing value left of operation") + } + + if left.key != symbols.Scalar { + return raiseError(tree.expression, left, 0, + fmt.Sprintf("left side of %s should be %s, instead got %s", + tree.ast[tree.astPos].key, symbols.Scalar, left.key)) + } + + v, err := left.dt.GetValue() + if err != nil { + return err + } + + i, err := types.ConvertGoType(v.Value, types.Integer) + if err != nil { + return err + } + + i = i.(int) + 1 + + left.value = scalarNameDetokenised(left.value) + err = tree.setVar(left.value, i, types.Integer) + if err != nil { + return raiseError(tree.expression, tree.currentSymbol(), 0, err.Error()) + } + + return tree.foldLeftAst(&astNodeT{ + key: symbols.Number, + pos: tree.ast[tree.astPos].pos, + dt: primitives.NewPrimitive(primitives.Null, nil), + }) +} diff --git a/lang/expressions/expression.go b/lang/expressions/expression.go index d165ba6d6..dc2df598d 100644 --- a/lang/expressions/expression.go +++ b/lang/expressions/expression.go @@ -152,6 +152,8 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { err = expMerge(tree) // 04. Addition and subtraction + case symbols.PlusPlus: + err = expPlusPlus(tree) case symbols.Add: err = expAdd(tree) case symbols.Subtract: diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 231b21f9f..7b994b297 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -318,11 +318,11 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { return raiseError(tree.expression, nil, tree.charPos, fmt.Sprintf("%s: '%s'", err.Error(), string(r))) } - if !exec { - dt := primitives.NewScalar(mxDt, v) + if exec { + dt := primitives.NewFunction(fn) tree.appendAstWithPrimitive(symbols.Scalar, dt, runes...) } else { - dt := primitives.NewFunction(fn) + dt := primitives.NewScalar(mxDt, v) tree.appendAstWithPrimitive(symbols.Scalar, dt, runes...) } } @@ -331,7 +331,7 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { next := tree.nextChar() switch { case next == '{': - // subshell + // sub-shell runes, fn, err := tree.parseSubShell(exec, r, varAsValue) if err != nil { return err @@ -363,8 +363,11 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { // equal add tree.appendAst(symbols.AssignAndAdd) tree.charPos++ + case '+': + tree.appendAst(symbols.PlusPlus) + tree.charPos++ default: - // add (+append) + // add tree.appendAst(symbols.Add) } diff --git a/lang/expressions/symbols/exp.go b/lang/expressions/symbols/exp.go index d3821f646..1b7503751 100644 --- a/lang/expressions/symbols/exp.go +++ b/lang/expressions/symbols/exp.go @@ -86,7 +86,9 @@ const ( Merge // 04. Addition and subtraction + PlusPlus Add + MinusMinus Subtract // 03. Multiplication, division, modulo diff --git a/lang/expressions/symbols/exp_string.go b/lang/expressions/symbols/exp_string.go index d927f9889..0b545d5e0 100644 --- a/lang/expressions/symbols/exp_string.go +++ b/lang/expressions/symbols/exp_string.go @@ -50,26 +50,28 @@ func _() { _ = x[LessThan-40] _ = x[LessThanOrEqual-41] _ = x[Merge-42] - _ = x[Add-43] - _ = x[Subtract-44] - _ = x[Multiply-45] - _ = x[Divide-46] + _ = x[PlusPlus-43] + _ = x[Add-44] + _ = x[MinusMinus-45] + _ = x[Subtract-46] + _ = x[Multiply-47] + _ = x[Divide-48] } const ( _Exp_name_0 = "Undefined" - _Exp_name_1 = "UnexpectedInvalidHyphenSubExpressionEndObjectEndArrayEndDataValuesBarewordSubExpressionBeginObjectBeginArrayBeginQuoteSingleQuoteDoubleQuoteParenthesisNumberBooleanNullScalarCalculatedOperationsAssignAssignUpdateAssignAndAddAssignAndSubtractAssignAndDivideAssignAndMultiplyAssignOrMergeElvisNullCoalescingLogicalOrLogicalAndEqualToNotEqualToLikeNotLikeRegexpNotRegexpGreaterThanGreaterThanOrEqualLessThanLessThanOrEqualMergeAddSubtractMultiplyDivide" + _Exp_name_1 = "UnexpectedInvalidHyphenSubExpressionEndObjectEndArrayEndDataValuesBarewordSubExpressionBeginObjectBeginArrayBeginQuoteSingleQuoteDoubleQuoteParenthesisNumberBooleanNullScalarCalculatedOperationsAssignAssignUpdateAssignAndAddAssignAndSubtractAssignAndDivideAssignAndMultiplyAssignOrMergeElvisNullCoalescingLogicalOrLogicalAndEqualToNotEqualToLikeNotLikeRegexpNotRegexpGreaterThanGreaterThanOrEqualLessThanLessThanOrEqualMergePlusPlusAddMinusMinusSubtractMultiplyDivide" ) var ( - _Exp_index_1 = [...]uint16{0, 10, 23, 39, 48, 56, 66, 74, 92, 103, 113, 124, 135, 151, 157, 164, 168, 174, 184, 194, 200, 212, 224, 241, 256, 273, 286, 291, 305, 314, 324, 331, 341, 345, 352, 358, 367, 378, 396, 404, 419, 424, 427, 435, 443, 449} + _Exp_index_1 = [...]uint16{0, 10, 23, 39, 48, 56, 66, 74, 92, 103, 113, 124, 135, 151, 157, 164, 168, 174, 184, 194, 200, 212, 224, 241, 256, 273, 286, 291, 305, 314, 324, 331, 341, 345, 352, 358, 367, 378, 396, 404, 419, 424, 432, 435, 445, 453, 461, 467} ) func (i Exp) String() string { switch { case i == 0: return _Exp_name_0 - case 2 <= i && i <= 46: + case 2 <= i && i <= 48: i -= 2 return _Exp_name_1[_Exp_index_1[i]:_Exp_index_1[i+1]] default: diff --git a/lang/expressions/validate.go b/lang/expressions/validate.go index 4536ab0f4..2cc1324ba 100644 --- a/lang/expressions/validate.go +++ b/lang/expressions/validate.go @@ -64,6 +64,13 @@ func (tree *ParserT) validateExpression() error { switch { case prev == nil: return raiseError(tree.expression, node, 0, fmt.Sprintf("nil symbol preceding %s", node.key)) + + case node.key == symbols.PlusPlus, node.key == symbols.MinusMinus: + if prev.key != symbols.Scalar { + return raiseError(tree.expression, node, 0, fmt.Sprintf("%s can only follow a %s, instead got %s", node.key, symbols.Scalar, prev.key)) + } + expectValue = !expectValue + case next == nil: return raiseError(tree.expression, node, 0, fmt.Sprintf("nil symbol following %s", node.key)) From 3f9d2a970e82afc8edca0abdb29089f973dd2efd Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 15 Aug 2024 16:32:07 +0300 Subject: [PATCH 033/142] docs: plus plus --- gen/includes/expr-operators-tokens.inc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gen/includes/expr-operators-tokens.inc.md b/gen/includes/expr-operators-tokens.inc.md index 95c257ca4..a71070b09 100644 --- a/gen/includes/expr-operators-tokens.inc.md +++ b/gen/includes/expr-operators-tokens.inc.md @@ -143,7 +143,7 @@ Read more: ### Assignment -Assignment returns `true` if successful. +Assignment returns `null` if successful. Assignment is only supported in expressions. @@ -156,6 +156,7 @@ Assignment is only supported in expressions. | `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | | `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | | `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | Read more: * Data types: {{link "bool" "bool"}} From d292f0b5d1df7bc117fb7759ecc8bb40b591022d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 15 Aug 2024 18:15:01 +0300 Subject: [PATCH 034/142] expressions: assignment add should reuse other assignment number ops --- docs/commands/expr.md | 3 ++- docs/parser/README.md | 2 +- gen/parser-md-cat.inc.md | 2 +- gen/vuepress/styles/palette.scss | 2 +- lang/expressions/exp14.go | 10 +++------- lang/expressions/expression.go | 3 ++- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/docs/commands/expr.md b/docs/commands/expr.md index 5b24f5dca..fe7aeab90 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -212,7 +212,8 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.AssignUpdate: err = expAssign(tree, false) case symbols.AssignAndAdd: - err = expAssignAdd(tree) + //err = expAssignAdd(tree) + err = expAssignAndOperate(tree, _assAdd) case symbols.AssignAndSubtract: err = expAssignAndOperate(tree, _assSub) case symbols.AssignAndDivide: diff --git a/docs/parser/README.md b/docs/parser/README.md index 5c4a84194..f1705c586 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -290,7 +290,7 @@ characters have special meanings when escaped. ### Murex's Source Code -The parser is located Murex's source under the `lang/` path of the project +The parser is located Murex's source under the `lang/expressions/` path of the project files. ## Pages diff --git a/gen/parser-md-cat.inc.md b/gen/parser-md-cat.inc.md index 5eff243d7..268419ce8 100644 --- a/gen/parser-md-cat.inc.md +++ b/gen/parser-md-cat.inc.md @@ -12,5 +12,5 @@ ### Murex's Source Code -The parser is located Murex's source under the `lang/` path of the project +The parser is located Murex's source under the `lang/expressions/` path of the project files. \ No newline at end of file diff --git a/gen/vuepress/styles/palette.scss b/gen/vuepress/styles/palette.scss index 6297aaf1f..177d90fa0 100644 --- a/gen/vuepress/styles/palette.scss +++ b/gen/vuepress/styles/palette.scss @@ -8,4 +8,4 @@ $font-family: "Lato, sans-serif"; // this SHOULDN'T be quoted $font-title: Jura, sans-serif; $font-strong: Lato, sans-serif; -$font-italic: "Libre Baskerville", Jura, sans-serif; \ No newline at end of file +$font-italic: "Libre Baskerville", Lato, sans-serif; \ No newline at end of file diff --git a/lang/expressions/exp14.go b/lang/expressions/exp14.go index a64ba7f71..11640caf4 100644 --- a/lang/expressions/exp14.go +++ b/lang/expressions/exp14.go @@ -154,7 +154,7 @@ func expAssign(tree *ParserT, overwriteType bool) error { }) } -func expAssignAdd(tree *ParserT) error { +/*func expAssignAdd(tree *ParserT) error { leftNode, rightNode, err := tree.getLeftAndRightSymbols() if err != nil { return err @@ -175,11 +175,6 @@ func expAssignAdd(tree *ParserT) error { tree.currentSymbol().key, leftNode.key)) } - /*if right.key != symbols.Number { - return raiseError(tree.expression,tree.currentSymbol(), fmt.Sprintf( - "right side should not be a %s", right.key)) - }*/ - v, dt, err := tree.getVar(leftNode.value, varAsValue) if err != nil { if !tree.StrictTypes() && strings.Contains(err.Error(), lang.ErrDoesNotExist) { @@ -240,10 +235,11 @@ func expAssignAdd(tree *ParserT) error { pos: tree.ast[tree.astPos].pos, dt: primitives.NewPrimitive(primitives.Null, nil), }) -} +}*/ type assFnT func(float64, float64) float64 +func _assAdd(lv float64, rv float64) float64 { return lv + rv } func _assSub(lv float64, rv float64) float64 { return lv - rv } func _assMulti(lv float64, rv float64) float64 { return lv * rv } func _assDiv(lv float64, rv float64) float64 { return lv / rv } diff --git a/lang/expressions/expression.go b/lang/expressions/expression.go index dc2df598d..8b3ea16b7 100644 --- a/lang/expressions/expression.go +++ b/lang/expressions/expression.go @@ -94,7 +94,8 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.AssignUpdate: err = expAssign(tree, false) case symbols.AssignAndAdd: - err = expAssignAdd(tree) + //err = expAssignAdd(tree) + err = expAssignAndOperate(tree, _assAdd) case symbols.AssignAndSubtract: err = expAssignAndOperate(tree, _assSub) case symbols.AssignAndDivide: From 022166f6364c9218eed7de6b0af04ee575c6fe2c Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 16 Aug 2024 11:12:36 +0300 Subject: [PATCH 035/142] expressions: minus minus --- docs/commands/expr.md | 6 ++- docs/parser/README.md | 21 +++++---- docs/user-guide/operators-and-tokens.md | 21 +++++---- gen/includes/expr-operators-tokens.inc.md | 21 +++++---- lang/expressions/exp04.go | 4 +- lang/expressions/expression.go | 6 ++- lang/expressions/parameters_test.go | 3 -- lang/expressions/parse_expression.go | 4 ++ lang/expressions/parse_expression_test.go | 57 +++++++++++++++++++++++ version.svg | 2 +- 10 files changed, 105 insertions(+), 40 deletions(-) diff --git a/docs/commands/expr.md b/docs/commands/expr.md index fe7aeab90..0187be235 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -270,9 +270,11 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.Merge: err = expMerge(tree) - // 04. Addition and subtraction + // 04. Addition and subtraction case symbols.PlusPlus: - err = expPlusPlus(tree) + err = expPlusPlus(tree, 1) + case symbols.MinusMinus: + err = expPlusPlus(tree, -1) case symbols.Add: err = expAdd(tree) case symbols.Subtract: diff --git a/docs/parser/README.md b/docs/parser/README.md index f1705c586..1a89bfc34 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -149,16 +149,17 @@ Assignment returns `null` if successful. Assignment is only supported in expressions. -| Operator | Name | Operation | -|----------|---------------------|---------------------------------------------------| -| `=` | Assign (overwrite) | Assign _right_ to _left_ | -| `:=` | Assign (retain) | **EXPERIMENTAL** | -| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | -| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | -| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | -| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | -| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | -| `++` | Add one to variable | Adds one to _right_ and reassigns | +| Operator | Name | Operation | +|----------|-----------------------|---------------------------------------------------| +| `=` | Assign (overwrite) | Assign _right_ to _left_ | +| `:=` | Assign (retain) | **EXPERIMENTAL** | +| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | +| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | +| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | +| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | +| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | +| `--` | Subtract one from var | Subtracts one from _right_ and reassigns | Read more: * Data types: [bool](/docs/types/bool.md) diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index 2d7fd2494..7dc16c79a 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -151,16 +151,17 @@ Assignment returns `null` if successful. Assignment is only supported in expressions. -| Operator | Name | Operation | -|----------|---------------------|---------------------------------------------------| -| `=` | Assign (overwrite) | Assign _right_ to _left_ | -| `:=` | Assign (retain) | **EXPERIMENTAL** | -| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | -| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | -| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | -| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | -| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | -| `++` | Add one to variable | Adds one to _right_ and reassigns | +| Operator | Name | Operation | +|----------|-----------------------|---------------------------------------------------| +| `=` | Assign (overwrite) | Assign _right_ to _left_ | +| `:=` | Assign (retain) | **EXPERIMENTAL** | +| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | +| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | +| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | +| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | +| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | +| `--` | Subtract one from var | Subtracts one from _right_ and reassigns | Read more: * Data types: [bool](/docs/types/bool.md) diff --git a/gen/includes/expr-operators-tokens.inc.md b/gen/includes/expr-operators-tokens.inc.md index a71070b09..ef0536b96 100644 --- a/gen/includes/expr-operators-tokens.inc.md +++ b/gen/includes/expr-operators-tokens.inc.md @@ -147,16 +147,17 @@ Assignment returns `null` if successful. Assignment is only supported in expressions. -| Operator | Name | Operation | -|----------|---------------------|---------------------------------------------------| -| `=` | Assign (overwrite) | Assign _right_ to _left_ | -| `:=` | Assign (retain) | **EXPERIMENTAL** | -| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | -| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | -| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | -| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | -| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | -| `++` | Add one to variable | Adds one to _right_ and reassigns | +| Operator | Name | Operation | +|----------|-----------------------|---------------------------------------------------| +| `=` | Assign (overwrite) | Assign _right_ to _left_ | +| `:=` | Assign (retain) | **EXPERIMENTAL** | +| `<~` | Assign Or Merge | Merge _right_ (array / object) into _left_ | +| `+=` | Assign And Add | Add _right_ to _left_ and assign to _left_ | +| `-=` | Assign And Subtract | Subtract _right_ from _left_ and assign to _left_ | +| `*=` | Assign And Multiply | Multiply _right_ with _left_ and assign to _left_ | +| `/=` | Assign And Divide | Divide _right_ with _left_ and assign to _left_ | +| `++` | Add one to variable | Adds one to _right_ and reassigns | +| `--` | Subtract one from var | Subtracts one from _right_ and reassigns | Read more: * Data types: {{link "bool" "bool"}} diff --git a/lang/expressions/exp04.go b/lang/expressions/exp04.go index e6571a6ee..ce39ab449 100644 --- a/lang/expressions/exp04.go +++ b/lang/expressions/exp04.go @@ -91,7 +91,7 @@ func expMerge(tree *ParserT) error { }) } -func expPlusPlus(tree *ParserT) error { +func expPlusPlus(tree *ParserT, modifier int) error { left := tree.prevSymbol() if left == nil { @@ -114,7 +114,7 @@ func expPlusPlus(tree *ParserT) error { return err } - i = i.(int) + 1 + i = i.(int) + modifier left.value = scalarNameDetokenised(left.value) err = tree.setVar(left.value, i, types.Integer) diff --git a/lang/expressions/expression.go b/lang/expressions/expression.go index 8b3ea16b7..0eaeaf84c 100644 --- a/lang/expressions/expression.go +++ b/lang/expressions/expression.go @@ -152,9 +152,11 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { case symbols.Merge: err = expMerge(tree) - // 04. Addition and subtraction + // 04. Addition and subtraction case symbols.PlusPlus: - err = expPlusPlus(tree) + err = expPlusPlus(tree, 1) + case symbols.MinusMinus: + err = expPlusPlus(tree, -1) case symbols.Add: err = expAdd(tree) case symbols.Subtract: diff --git a/lang/expressions/parameters_test.go b/lang/expressions/parameters_test.go index 27e6329bd..7d3ec2e64 100644 --- a/lang/expressions/parameters_test.go +++ b/lang/expressions/parameters_test.go @@ -4,7 +4,6 @@ import ( "fmt" "math/rand" "testing" - "time" "github.com/lmorg/murex/test" ) @@ -104,8 +103,6 @@ func TestParamHangBug(t *testing.T) { } func TestParamVarRange(t *testing.T) { - rand.Seed(time.Now().Unix()) - test1, test2, test3 := rand.Int(), rand.Int(), rand.Int() tests := []test.MurexTest{ diff --git a/lang/expressions/parse_expression.go b/lang/expressions/parse_expression.go index 7b994b297..2641a9242 100644 --- a/lang/expressions/parse_expression.go +++ b/lang/expressions/parse_expression.go @@ -392,6 +392,10 @@ func (tree *ParserT) parseExpression(exec, incLogicalOps bool) error { // arrow pipe tree.charPos-- return nil + case c == '-' && (tree.charPos+2 >= len(tree.expression) || + !(tree.expression[tree.charPos+2] >= '0' && '9' >= tree.expression[tree.charPos+2])): + tree.appendAst(symbols.MinusMinus) + tree.charPos++ default: tree.appendAst(symbols.Subtract) // invalid hyphen diff --git a/lang/expressions/parse_expression_test.go b/lang/expressions/parse_expression_test.go index 599ec0170..7eb78591f 100644 --- a/lang/expressions/parse_expression_test.go +++ b/lang/expressions/parse_expression_test.go @@ -238,3 +238,60 @@ func TestParseExprLogicalAnd(t *testing.T) { test.RunMurexTests(tests, t) } + +func TestParseExprPlusPlus(t *testing.T) { + tests := []test.MurexTest{ + { + Block: "TestParseExprPlusPlus0 = 0; $TestParseExprPlusPlus0++; $TestParseExprPlusPlus0", + Stdout: "^1$", + }, + { + Block: "TestParseExprPlusPlus1 = 1; TestParseExprPlusPlus1++; $TestParseExprPlusPlus1", + Stdout: "^1$", + Stderr: "Error", + }, + { + Block: "TestParseExprPlusPlus2 = 2; $TestParseExprPlusPlus2 ++; $TestParseExprPlusPlus2", + Stdout: "^3$", + }, + /*{ // doesn't compile + Block: "TestParseExprPlusPlus3 = 3; $TestParseExprPlusPlus3 ++ 4; $TestParseExprPlusPlus3", + Stdout: "^3$", + Stderr: "commands cannot begin with", + },*/ + } + + test.RunMurexTestsRx(tests, t) +} + +func TestParseExprMinusMinus(t *testing.T) { + tests := []test.MurexTest{ + { + Block: "TestParseExprMinusMinus0 = 0; $TestParseExprMinusMinus0--; $TestParseExprMinusMinus0", + Stdout: "^-1$", + }, + { + Block: "TestParseExprMinusMinus1 = 1; TestParseExprMinusMinus1--; $TestParseExprMinusMinus1", + Stdout: "^1$", + Stderr: "Error", + }, + { + Block: "TestParseExprMinusMinus2 = 2; $TestParseExprMinusMinus2 --; $TestParseExprMinusMinus2", + Stdout: "^1$", + }, + /*{ // doesn't compile + Block: "TestParseExprMinusMinus3 = 3; $TestParseExprMinusMinus3 -- 4; $TestParseExprMinusMinus3", + Stdout: "^7$", + },*/ + { + Block: "TestParseExprMinusMinus4 = 4; $TestParseExprMinusMinus4 --5; $TestParseExprMinusMinus4", + Stdout: "^94$", + }, + { + Block: "TestParseExprMinusMinus5 = 5; $TestParseExprMinusMinus5--6; $TestParseExprMinusMinus5", + Stdout: "^115$", + }, + } + + test.RunMurexTestsRx(tests, t) +} diff --git a/version.svg b/version.svg index bdecfe28d..28b12a85a 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.2000Version6.3.2000 +Version: 6.3.3000Version6.3.3000 From ac56e69c19074ab58e9bcec30b9e0a3cd12f09ea Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 16 Aug 2024 23:23:14 +0300 Subject: [PATCH 036/142] new builtin: mjoin --- app/app.go | 2 +- builtins/core/lists/list.go | 2 + builtins/core/lists/mjoin.go | 47 ++++++++++++++++++++++ builtins/core/lists/mjoin_doc.yaml | 39 ++++++++++++++++++ builtins/core/lists/mjoin_test.go | 37 +++++++++++++++++ builtins/docs/summaries.go | 8 ++++ docs/commands/README.md | 2 + docs/commands/count.md | 1 + docs/commands/list.join.md | 53 +++++++++++++++++++++++++ docs/parser/README.md | 5 ++- docs/user-guide/README.md | 2 + docs/user-guide/operators-and-tokens.md | 5 ++- 12 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 builtins/core/lists/mjoin.go create mode 100644 builtins/core/lists/mjoin_doc.yaml create mode 100644 builtins/core/lists/mjoin_test.go create mode 100644 docs/commands/list.join.md diff --git a/app/app.go b/app/app.go index c25755f4f..ffe52faee 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 2000 + Revision = 3000 ) // Copyright is the copyright owner string diff --git a/builtins/core/lists/list.go b/builtins/core/lists/list.go index 9d1e047e7..98dbe4c9c 100644 --- a/builtins/core/lists/list.go +++ b/builtins/core/lists/list.go @@ -17,5 +17,7 @@ func init() { alias list.regex = regexp alias list.string = match alias list.split = jsplit + alias list.join = mjoin + alias list.count = count `) } diff --git a/builtins/core/lists/mjoin.go b/builtins/core/lists/mjoin.go new file mode 100644 index 000000000..e9f45adc9 --- /dev/null +++ b/builtins/core/lists/mjoin.go @@ -0,0 +1,47 @@ +package lists + +import ( + "bytes" + "strings" + + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/types" +) + +func init() { + lang.DefineMethod("mjoin", cmdMjoin, types.ReadArray, types.String) +} + +func cmdMjoin(p *lang.Process) error { + p.Stdout.SetDataType(types.String) + + separator, err := p.Parameters.Byte(0) + if err != nil { + return err + } + + if p.IsMethod { + return mjoinMethod(p, separator) + } + + return mjoinFunction(p, separator) +} + +func mjoinMethod(p *lang.Process, separator []byte) error { + var slice [][]byte + + p.Stdin.ReadArray(p.Context, func(b []byte) { + slice = append(slice, b) + }) + + _, err := p.Stdout.Write(bytes.Join(slice, separator)) + return err +} + +func mjoinFunction(p *lang.Process, separator []byte) error { + slice := p.Parameters.StringArray()[1:] + + s := strings.Join(slice, string(separator)) + _, err := p.Stdout.Write([]byte(s)) + return err +} diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml new file mode 100644 index 000000000..8514e9f19 --- /dev/null +++ b/builtins/core/lists/mjoin_doc.yaml @@ -0,0 +1,39 @@ +- DocumentID: list.join + Title: >- + `list.join` + CategoryID: commands + Summary: >- + Joins a list or array into a single string + Description: |- + `mjoin` will read an array from either stdin or it's command line parameters, + and joins those elements together to form a single string. + + The string will be delimited by the separator defined as the first command line + parameter. + Usage: |- + ``` + -> list.join separator -> + list.join separator item1 item2 item3... -> + ``` + Examples: |- + ### As a method + + ``` + » %[Monday..Friday] -> list.join ! + Monday!Tuesday!Wednesday!Thursday!Friday + ``` + + ### As a function + + ``` + » list.join ! @{ %[Monday..Friday] } + Monday!Tuesday!Wednesday!Thursday!Friday + ``` + Detail: + Synonyms: + - list.join + - mjoin + Related: + - jsplit + - array + - create-array diff --git a/builtins/core/lists/mjoin_test.go b/builtins/core/lists/mjoin_test.go new file mode 100644 index 000000000..dfcd6f464 --- /dev/null +++ b/builtins/core/lists/mjoin_test.go @@ -0,0 +1,37 @@ +package lists + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestListJoinMethod(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `%[] -> list.join '|'`, + Stdout: "", + }, + { + Block: `%[Mon..Fri] -> list.join '|'`, + Stdout: "Mon|Tue|Wed|Thu|Fri", + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListJoinFunction(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `list.join '|'`, // empty array + Stdout: "", + }, + { + Block: `list.join '|' @{ %[Mon..Fri] }`, + Stdout: "Mon|Tue|Wed|Thu|Fri", + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 19adfd2e9..a102cc129 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -68,6 +68,7 @@ func init() { "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "left": "Left substring every item in a list", "let": "Evaluate a mathematical function and assign to variable (deprecated)", + "list.join": "Joins a list or array into a single string", "lockfile": "Create and manage lock files", "man-get-flags": "Parses man page files for command line flags", "man-summary": "Outputs a man page summary of a command", @@ -197,6 +198,7 @@ func init() { "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "commands/left": "Left substring every item in a list", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", + "commands/list.join": "Joins a list or array into a single string", "commands/lockfile": "Create and manage lock files", "commands/man-get-flags": "Parses man page files for command line flags", "commands/man-summary": "Outputs a man page summary of a command", @@ -444,6 +446,7 @@ func init() { "continue": "continue", "count": "count", "len": "count", + "list.count": "count", "cpuarch": "cpuarch", "cpucount": "cpucount", "datetime": "datetime", @@ -500,6 +503,8 @@ func init() { "left": "left", "list.left": "left", "let": "let", + "list.join": "list.join", + "mjoin": "list.join", "lockfile": "lockfile", "man-get-flags": "man-get-flags", "man-summary": "man-summary", @@ -666,6 +671,7 @@ func init() { "commands/continue": "commands/continue", "commands/count": "commands/count", "commands/len": "commands/count", + "commands/list.count": "commands/count", "commands/cpuarch": "commands/cpuarch", "commands/cpucount": "commands/cpucount", "commands/datetime": "commands/datetime", @@ -722,6 +728,8 @@ func init() { "commands/left": "commands/left", "commands/list.left": "commands/left", "commands/let": "commands/let", + "commands/list.join": "commands/list.join", + "commands/mjoin": "commands/list.join", "commands/lockfile": "commands/lockfile", "commands/man-get-flags": "commands/man-get-flags", "commands/man-summary": "commands/man-summary", diff --git a/docs/commands/README.md b/docs/commands/README.md index 20d2bbcb4..e52870f4a 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -160,6 +160,8 @@ murex-docs trypipe Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) +* [`list.join` ](../commands/list.join.md): + Joins a list or array into a single string * [`lockfile`](../commands/lockfile.md): Create and manage lock files * [`man-get-flags` ](../commands/man-get-flags.md): diff --git a/docs/commands/count.md b/docs/commands/count.md index 6f21f9442..e924255a2 100644 --- a/docs/commands/count.md +++ b/docs/commands/count.md @@ -133,6 +133,7 @@ unique count should be one less than the total count: * `count` * `len` +* `list.count` ## See Also diff --git a/docs/commands/list.join.md b/docs/commands/list.join.md new file mode 100644 index 000000000..db32895de --- /dev/null +++ b/docs/commands/list.join.md @@ -0,0 +1,53 @@ +# `list.join` + +> Joins a list or array into a single string + +## Description + +`mjoin` will read an array from either stdin or it's command line parameters, +and joins those elements together to form a single string. + +The string will be delimited by the separator defined as the first command line +parameter. + +## Usage + +``` + -> list.join separator -> + list.join separator item1 item2 item3... -> +``` + +## Examples + +### As a method + +``` +» %[Monday..Friday] -> list.join ! +Monday!Tuesday!Wednesday!Thursday!Friday +``` + +### As a function + +``` +» list.join ! @{ %[Monday..Friday] } +Monday!Tuesday!Wednesday!Thursday!Friday +``` + +## Synonyms + +* `list.join` +* `mjoin` + + +## See Also + +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays +* [`@Array` Sigil](../parser/array.md): + Expand values as an array +* [`jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter + +
+ +This document was generated from [builtins/core/lists/mjoin_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/lists/mjoin_doc.yaml). \ No newline at end of file diff --git a/docs/parser/README.md b/docs/parser/README.md index 1a89bfc34..ca7ff1a1a 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -113,11 +113,14 @@ _immutable merge_ does not modify the contents of either _left_ nor _right_. The direction of the arrow indicates that the result returned is a new value rather than an updated assignment. +_Left_ can be a statement or expression, whereas _right_ can only be an +expression. However you can still use a sub-shell as part of, or the entirety, +of, that expression. + | Operator | Name | Operation | |----------|-----------------|---------------------------------------------| | `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | - ### Comparators All comparators replace the _left_, operator and _right_ with the returned diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 4e4ade2a8..d050e3163 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -269,6 +269,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) +* [`list.join` ](../commands/list.join.md): + Joins a list or array into a single string * [`lockfile`](../commands/lockfile.md): Create and manage lock files * [`man-get-flags` ](../commands/man-get-flags.md): diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index 7dc16c79a..ceb45605b 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -115,11 +115,14 @@ _immutable merge_ does not modify the contents of either _left_ nor _right_. The direction of the arrow indicates that the result returned is a new value rather than an updated assignment. +_Left_ can be a statement or expression, whereas _right_ can only be an +expression. However you can still use a sub-shell as part of, or the entirety, +of, that expression. + | Operator | Name | Operation | |----------|-----------------|---------------------------------------------| | `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | - ### Comparators All comparators replace the _left_, operator and _right_ with the returned From 1ddd89b9624e93fe3b0027fe9ffdcf8630847064 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 16 Aug 2024 23:24:26 +0300 Subject: [PATCH 037/142] new alias: `list.count` --- builtins/core/datatools/count_doc.yaml | 1 + gen/includes/expr-operators-tokens.inc.md | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index 18ef06b72..fe1763131 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -128,6 +128,7 @@ Synonyms: - count - len + - list.count Related: - prepend - append diff --git a/gen/includes/expr-operators-tokens.inc.md b/gen/includes/expr-operators-tokens.inc.md index ef0536b96..c66c37ac9 100644 --- a/gen/includes/expr-operators-tokens.inc.md +++ b/gen/includes/expr-operators-tokens.inc.md @@ -111,11 +111,14 @@ _immutable merge_ does not modify the contents of either _left_ nor _right_. The direction of the arrow indicates that the result returned is a new value rather than an updated assignment. +_Left_ can be a statement or expression, whereas _right_ can only be an +expression. However you can still use a sub-shell as part of, or the entirety, +of, that expression. + | Operator | Name | Operation | |----------|-----------------|---------------------------------------------| | `~>` | Immutable Merge | Returns merged value of _right_ into _left_ | - ### Comparators All comparators replace the _left_, operator and _right_ with the returned From e0260488a2a6d4ed133143b702b4582aca9049a6 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 16 Aug 2024 23:25:29 +0300 Subject: [PATCH 038/142] new example: dictionary api --- examples/dictionary-api.mx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 examples/dictionary-api.mx diff --git a/examples/dictionary-api.mx b/examples/dictionary-api.mx new file mode 100755 index 000000000..aae98d703 --- /dev/null +++ b/examples/dictionary-api.mx @@ -0,0 +1,17 @@ +#!/usr/bin/env murex + +words = list.join('%20' @PARAMS) + +open https://api.dictionaryapi.dev/api/v2/entries/en/$(words) \ +-> foreach { + -> [ meanings ] -> foreach meaning { + -> [ definitions ] -> foreach def { + $definitions <~ %[ { + partOfSpeech: $meaning.partOfSpeech + meaning: $def.definition + } ] + } + } +} + +$definitions \ No newline at end of file From 911e985b93e7ea92d9431e0874f557c02d26c623 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 17 Aug 2024 16:13:22 +0300 Subject: [PATCH 039/142] #858 escape aliases --- builtins/core/escape/escape.go | 11 ++++ builtins/core/escape/escape_doc.yaml | 8 +++ builtins/core/lists/list.go | 28 ++++----- builtins/core/lists/mjoin_test.go | 8 +-- builtins/core/lists/regexp_doc.yaml | 2 + builtins/docs/summaries.go | 18 ++++++ docs/commands/escape.md | 2 + docs/commands/esccli.md | 6 ++ docs/commands/eschtml.md | 2 + docs/commands/escurl.md | 2 + docs/commands/match.md | 1 + docs/commands/regexp.md | 1 + gen/examples/json-merge-nushell.md | 86 ++++++++++++++++++++++++++++ gen/examples/json-merge-nushell.yaml | 23 ++++++++ 14 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 gen/examples/json-merge-nushell.md create mode 100644 gen/examples/json-merge-nushell.yaml diff --git a/builtins/core/escape/escape.go b/builtins/core/escape/escape.go index bef16dc06..81d5675eb 100644 --- a/builtins/core/escape/escape.go +++ b/builtins/core/escape/escape.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/escape" @@ -19,6 +20,16 @@ func init() { lang.DefineMethod("escurl", cmdUrl, types.Text, types.String) lang.DefineMethod("!escurl", cmdUrl, types.Text, types.String) lang.DefineMethod("esccli", cmdEscapeCli, types.Text, types.String) + + defaults.AppendProfile(` + alias escape.quote = escape + alias !escape.quote = !escape + alias escape.html = eschtml + alias !escape.html = !eschtml + alias escape.url = escurl + alias !escape.url = !escurl + alias escape.cli = esccli + `) } func cmdEscape(p *lang.Process) error { diff --git a/builtins/core/escape/escape_doc.yaml b/builtins/core/escape/escape_doc.yaml index ee0d0164c..f484eba3e 100644 --- a/builtins/core/escape/escape_doc.yaml +++ b/builtins/core/escape/escape_doc.yaml @@ -40,6 +40,8 @@ Synonyms: - escape - "!escape" + - "escape.quote" + - "!escape.quote" Related: - esccli - eschtml @@ -94,6 +96,8 @@ Synonyms: - eschtml - "!eschtml" + - "escape.html" + - "!escape.html" Related: - esccli - escape @@ -151,6 +155,8 @@ Synonyms: - escurl - "!escurl" + - "escape.url" + - "!escape.url" Related: - esccli - escape @@ -203,6 +209,8 @@ Flags: Detail: Synonyms: + - "esccli" + - "escape.cli" Related: - alias - out diff --git a/builtins/core/lists/list.go b/builtins/core/lists/list.go index 98dbe4c9c..f991b9d64 100644 --- a/builtins/core/lists/list.go +++ b/builtins/core/lists/list.go @@ -6,18 +6,20 @@ import ( func init() { defaults.AppendProfile(` - alias list.sort = msort - alias list.reverse = mtac - alias list.prepend = prepend - alias list.append = append - alias list.prefix = prefix - alias list.suffix = suffix - alias list.left = left - alias list.right = right - alias list.regex = regexp - alias list.string = match - alias list.split = jsplit - alias list.join = mjoin - alias list.count = count + alias list.sort = msort + alias list.reverse = mtac + alias list.prepend = prepend + alias list.append = append + alias list.prefix = prefix + alias list.suffix = suffix + alias list.left = left + alias list.right = right + alias list.regex = regexp + alias !list.regex = !regexp + alias list.string = match + alias !list.string = !match + alias list.split = jsplit + alias list.join = mjoin + alias list.count = count `) } diff --git a/builtins/core/lists/mjoin_test.go b/builtins/core/lists/mjoin_test.go index dfcd6f464..71e071770 100644 --- a/builtins/core/lists/mjoin_test.go +++ b/builtins/core/lists/mjoin_test.go @@ -9,11 +9,11 @@ import ( func TestListJoinMethod(t *testing.T) { tests := []test.MurexTest{ { - Block: `%[] -> list.join '|'`, + Block: `%[] -> mjoin '|'`, Stdout: "", }, { - Block: `%[Mon..Fri] -> list.join '|'`, + Block: `%[Mon..Fri] -> mjoin '|'`, Stdout: "Mon|Tue|Wed|Thu|Fri", }, } @@ -24,11 +24,11 @@ func TestListJoinMethod(t *testing.T) { func TestListJoinFunction(t *testing.T) { tests := []test.MurexTest{ { - Block: `list.join '|'`, // empty array + Block: `mjoin '|'`, // empty array Stdout: "", }, { - Block: `list.join '|' @{ %[Mon..Fri] }`, + Block: `mjoin '|' @{ %[Mon..Fri] }`, Stdout: "Mon|Tue|Wed|Thu|Fri", }, } diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index cc15b909f..4d6c9e2f3 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -65,6 +65,7 @@ - match - "!match" - list.string + - "!list.string" Related: - a - ja @@ -166,6 +167,7 @@ - regexp - "!regexp" - list.regex + - "!list.regex" Related: - a - ja diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index a102cc129..04ddd2c43 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -455,11 +455,18 @@ func init() { "err": "err", "escape": "escape", "!escape": "escape", + "escape.quote": "escape", + "!escape.quote": "escape", "esccli": "esccli", + "escape.cli": "esccli", "eschtml": "eschtml", "!eschtml": "eschtml", + "escape.html": "eschtml", + "!escape.html": "eschtml", "escurl": "escurl", "!escurl": "escurl", + "escape.url": "escurl", + "!escape.url": "escurl", "event": "event", "!event": "event", "exec": "exec", @@ -512,6 +519,7 @@ func init() { "match": "match", "!match": "match", "list.string": "match", + "!list.string": "match", "method": "method", "msort": "msort", "list.sort": "msort", @@ -547,6 +555,7 @@ func init() { "regexp": "regexp", "!regexp": "regexp", "list.regex": "regexp", + "!list.regex": "regexp", "return": "return", "right": "right", "list.right": "right", @@ -680,11 +689,18 @@ func init() { "commands/err": "commands/err", "commands/escape": "commands/escape", "commands/!escape": "commands/escape", + "commands/escape.quote": "commands/escape", + "commands/!escape.quote": "commands/escape", "commands/esccli": "commands/esccli", + "commands/escape.cli": "commands/esccli", "commands/eschtml": "commands/eschtml", "commands/!eschtml": "commands/eschtml", + "commands/escape.html": "commands/eschtml", + "commands/!escape.html": "commands/eschtml", "commands/escurl": "commands/escurl", "commands/!escurl": "commands/escurl", + "commands/escape.url": "commands/escurl", + "commands/!escape.url": "commands/escurl", "commands/event": "commands/event", "commands/!event": "commands/event", "commands/exec": "commands/exec", @@ -737,6 +753,7 @@ func init() { "commands/match": "commands/match", "commands/!match": "commands/match", "commands/list.string": "commands/match", + "commands/!list.string": "commands/match", "commands/method": "commands/method", "commands/msort": "commands/msort", "commands/list.sort": "commands/msort", @@ -772,6 +789,7 @@ func init() { "commands/regexp": "commands/regexp", "commands/!regexp": "commands/regexp", "commands/list.regex": "commands/regexp", + "commands/!list.regex": "commands/regexp", "commands/return": "commands/return", "commands/right": "commands/right", "commands/list.right": "commands/right", diff --git a/docs/commands/escape.md b/docs/commands/escape.md index 86bf3fcdb..51c916e6b 100644 --- a/docs/commands/escape.md +++ b/docs/commands/escape.md @@ -43,6 +43,8 @@ escape string to escape -> * `escape` * `!escape` +* `escape.quote` +* `!escape.quote` ## See Also diff --git a/docs/commands/esccli.md b/docs/commands/esccli.md index 5bb76eb6c..0564c2597 100644 --- a/docs/commands/esccli.md +++ b/docs/commands/esccli.md @@ -41,6 +41,12 @@ out foo\$b\@r out foo\$b\@r ``` +## Synonyms + +* `esccli` +* `escape.cli` + + ## See Also * [`[ Index ]`](../parser/item-index.md): diff --git a/docs/commands/eschtml.md b/docs/commands/eschtml.md index 7d268cfd1..d244a8cd3 100644 --- a/docs/commands/eschtml.md +++ b/docs/commands/eschtml.md @@ -48,6 +48,8 @@ eschtml string to escape -> * `eschtml` * `!eschtml` +* `escape.html` +* `!escape.html` ## See Also diff --git a/docs/commands/escurl.md b/docs/commands/escurl.md index 2252a85ef..14b26e708 100644 --- a/docs/commands/escurl.md +++ b/docs/commands/escurl.md @@ -48,6 +48,8 @@ out '%21%3F%20%3C%3E%0A' -> !escurl * `escurl` * `!escurl` +* `escape.url` +* `!escape.url` ## See Also diff --git a/docs/commands/match.md b/docs/commands/match.md index 42a1ddf98..566e9970f 100644 --- a/docs/commands/match.md +++ b/docs/commands/match.md @@ -71,6 +71,7 @@ same data-type. * `match` * `!match` * `list.string` +* `!list.string` ## See Also diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index afe1a0da7..8db4f1ed2 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -90,6 +90,7 @@ same data-type. * `regexp` * `!regexp` * `list.regex` +* `!list.regex` ## See Also diff --git a/gen/examples/json-merge-nushell.md b/gen/examples/json-merge-nushell.md new file mode 100644 index 000000000..90af55b18 --- /dev/null +++ b/gen/examples/json-merge-nushell.md @@ -0,0 +1,86 @@ +### Creating JSON files + +First we need to create two JSON files. + +Here the syntax is pretty similar however with the Nushell code we are using +the command `save` whereas the Murex equivalent uses the `|>` operator, which +is like the Bash `>` redirection pipe. + +Nushell: + +```nu +[0,1,2,3] | range 0..3 | save a.json +[4,5,6,7] | range 0..3 | save b.json +``` + +Murex: + +```mx +%[0..3] |> a.json +%[4..7] |> b.json +``` + +This will create two files that look like + +``` +# a.json +[ + 0, + 1, + 2, + 3 +] +# b.json +[ + 4, + 5, + 6, + 7 +] +``` + +> Murex's JSON files are minified by default. You can make them human readable +> with the `pretty` command, eg +> +> ``` +> %[0..3] | pretty |> a.json +> ``` + +### Embedding arrays in an array + +To then embed two the files together, with Nushell you reuse the `echo` command +whereas in Murex you would use the array builder: + +Nushell: + +```nu +echo (open a.json) (open b.json) | save c.json +``` + +Murex: + +```mx +%[ ${open a.json} ${open b.json} ]> c.json +``` + +### Merging and flattening two arrays + +With Murex merging (or "flattening") the two arrays can be done with a single +operator `~>`. + +Nushell: + +``` +echo (open a.json) (open b.json) | flatten | save c.json +``` + +Murex: + +``` +open(a.json) ~> open(b.json) |> c.json +``` + +### Nushell references + +The Nushell script used here can be found at https://github.com/nushell/nu_scripts/blob/main/sourced/cool-oneliners/file_cat.nu + diff --git a/gen/examples/json-merge-nushell.yaml b/gen/examples/json-merge-nushell.yaml new file mode 100644 index 000000000..026d3696a --- /dev/null +++ b/gen/examples/json-merge-nushell.yaml @@ -0,0 +1,23 @@ +- DocumentID: json-merge-nushell + Title: >- + JSON Merge + CategoryID: examples + Summary: >- + Merging two JSON arrays (comparing Murex to Nushell) + Description: |- + In this example we'll merge two JSON files together, using example code from + Nushell to illustrate Murex's syntax. + Detail: |- + {{ include "gen/examples/json-merge-nushell.md" }} + Related: + - expr + - addition + - subtract-by + - multiply-by + - divide-by + - int + - float + - num + - config + - cast + - operators-and-tokens \ No newline at end of file From 8b7f48c132e6265be9a3311cdb1f594c2bbc76ea Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 17 Aug 2024 16:21:57 +0300 Subject: [PATCH 040/142] remove support for string concatenation via `+=` --- lang/expressions/exp14_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/expressions/exp14_test.go b/lang/expressions/exp14_test.go index 682a751b7..3fc39cafd 100644 --- a/lang/expressions/exp14_test.go +++ b/lang/expressions/exp14_test.go @@ -51,7 +51,7 @@ func TestExpAssignAdd(t *testing.T) { }, { Expression: `TestExpAssignAdd1 += "bar"`, - Expected: nil, + Error: true, }, { Expression: `TestExpAssignAdd2 += bar`, From c1d2704696309765a1692ebc35ea36e17599d1d7 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 17 Aug 2024 22:14:38 +0300 Subject: [PATCH 041/142] #670 new builtin: `list.case` --- app/app.go | 2 +- builtins/core/lists/case.go | 142 +++++++++++++++++++++++++ builtins/core/lists/case_doc.yaml.todo | 39 +++++++ builtins/core/lists/case_test.go | 97 +++++++++++++++++ builtins/core/lists/mjoin.go | 8 +- go.mod | 8 +- go.sum | 19 ++-- version.svg | 2 +- 8 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 builtins/core/lists/case.go create mode 100644 builtins/core/lists/case_doc.yaml.todo create mode 100644 builtins/core/lists/case_test.go diff --git a/app/app.go b/app/app.go index ffe52faee..0e7ee0e57 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 3000 + Revision = 3100 ) // Copyright is the copyright owner string diff --git a/builtins/core/lists/case.go b/builtins/core/lists/case.go new file mode 100644 index 000000000..5cf9efa1c --- /dev/null +++ b/builtins/core/lists/case.go @@ -0,0 +1,142 @@ +package lists + +import ( + "fmt" + "strings" + + "golang.org/x/text/cases" + "golang.org/x/text/language" + + "github.com/lmorg/murex/config/defaults" + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/types" + "github.com/lmorg/murex/utils/json" +) + +func init() { + lang.DefineMethod("list.case", cmdCase, types.ReadArray, types.WriteArray) + + defaults.AppendProfile(` + autocomplete set list.case %[ + { + DynamicDesc: '{ list.case help }' + } + ] + `) +} + +const ( + _CASE_UPPER = "upper" + _CASE_LOWER = "lower" + _CASE_TITLE = "title" + _CASE_TITLE_CAPS = "title+caps" + _CASE_HELP = "help" +) + +var caseActions = map[string]string{ + _CASE_UPPER: "Convert all elements in list to uppercase", + _CASE_LOWER: "Convert all elements in list to lowercase", + _CASE_TITLE: "Capitalize the first character of each word", + _CASE_TITLE_CAPS: "Capitalize the first character of each word, do not lowercase characters already in uppercase", +} + +func caseTitle(s string) string { + return cases.Title(language.English).String(s) +} + +func caseTitlePlusCaps(s string) string { + return cases.Title(language.English, cases.NoLower).String(s) +} + +func cmdCase(p *lang.Process) error { + action, err := p.Parameters.String(0) + if err != nil { + return err + } + + var fn func(string) string + + switch action { + case _CASE_UPPER: + fn = strings.ToUpper + + case _CASE_LOWER: + fn = strings.ToLower + + case _CASE_TITLE: + fn = caseTitle + + case _CASE_TITLE_CAPS: + fn = caseTitlePlusCaps + + case _CASE_HELP: + return caseHelp(p) + + default: + return fmt.Errorf("invalid action `%s` -- run `%s %s` for usage", + action, p.Name.String(), _CASE_HELP) + } + + if p.IsMethod { + return caseMethod(p, fn) + } + + return caseFunction(p, fn) +} + +func caseMethod(p *lang.Process, fn func(string) string) error { + dt := p.Stdin.GetDataType() + p.Stdout.SetDataType(dt) + aw, err := p.Stdout.WriteArray(dt) + if err != nil { + return err + } + + err = p.Stdin.ReadArray(p.Context, func(b []byte) { + s := fn(string(b)) + err := aw.WriteString(s) + if err != nil { + p.Done() + _, err = p.Stderr.Writeln([]byte(fmt.Sprintf("error: %s", err.Error()))) + p.ExitNum = 2 + if err != nil { + panic(err) + } + } + }) + if err != nil { + return err + } + + return aw.Close() +} + +func caseFunction(p *lang.Process, fn func(string) string) error { + p.Stdout.SetDataType(types.Json) + + slice := p.Parameters.StringArray()[1:] + + for i := range slice { + slice[i] = fn(slice[i]) + } + + b, err := json.Marshal(slice, p.Stdout.IsTTY()) + if err != nil { + return err + } + + _, err = p.Stdout.Write(b) + return err +} + +func caseHelp(p *lang.Process) error { + p.Stdout.SetDataType(types.Json) + + b, err := json.Marshal(caseActions, p.Stdout.IsTTY()) + if err != nil { + return err + } + + _, err = p.Stdout.Write(b) + return err +} diff --git a/builtins/core/lists/case_doc.yaml.todo b/builtins/core/lists/case_doc.yaml.todo new file mode 100644 index 000000000..8514e9f19 --- /dev/null +++ b/builtins/core/lists/case_doc.yaml.todo @@ -0,0 +1,39 @@ +- DocumentID: list.join + Title: >- + `list.join` + CategoryID: commands + Summary: >- + Joins a list or array into a single string + Description: |- + `mjoin` will read an array from either stdin or it's command line parameters, + and joins those elements together to form a single string. + + The string will be delimited by the separator defined as the first command line + parameter. + Usage: |- + ``` + -> list.join separator -> + list.join separator item1 item2 item3... -> + ``` + Examples: |- + ### As a method + + ``` + » %[Monday..Friday] -> list.join ! + Monday!Tuesday!Wednesday!Thursday!Friday + ``` + + ### As a function + + ``` + » list.join ! @{ %[Monday..Friday] } + Monday!Tuesday!Wednesday!Thursday!Friday + ``` + Detail: + Synonyms: + - list.join + - mjoin + Related: + - jsplit + - array + - create-array diff --git a/builtins/core/lists/case_test.go b/builtins/core/lists/case_test.go new file mode 100644 index 000000000..a5f250c23 --- /dev/null +++ b/builtins/core/lists/case_test.go @@ -0,0 +1,97 @@ +package lists + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestListUpperMethod(t *testing.T) { + tests := []test.MurexTest{ + /*{ + Block: `%[] -> list.case upper`, + Stdout: "", + },*/ + { + Block: `%[Mon..Fri] -> list.case upper`, + Stdout: `["MON","TUE","WED","THU","FRI"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListUpperFunction(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `list.case upper`, // empty array + Stdout: "[]", + }, + { + Block: `list.case upper @{ %[Mon..Fri] }`, + Stdout: `["MON","TUE","WED","THU","FRI"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListTitleMethod(t *testing.T) { + tests := []test.MurexTest{ + /*{ + Block: `%[] -> list.case title`, + Stdout: "", + },*/ + { + Block: `%[MON..FRI] -> list.case title`, + Stdout: `["Mon","Tue","Wed","Thu","Fri"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListTitleFunction(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `list.case title`, // empty array + Stdout: "[]", + }, + { + Block: `list.case title @{ %[MON..FRI] }`, + Stdout: `["Mon","Tue","Wed","Thu","Fri"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListLowerMethod(t *testing.T) { + tests := []test.MurexTest{ + /*{ + Block: `%[] -> list.case lower`, + Stdout: "", + },*/ + { + Block: `%[MON..FRI] -> list.case lower`, + Stdout: `["mon","tue","wed","thu","fri"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestListLowerFunction(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `list.case lower`, // empty array + Stdout: "[]", + }, + { + Block: `list.case lower @{ %[MON..FRI] }`, + Stdout: `["mon","tue","wed","thu","fri"]`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/builtins/core/lists/mjoin.go b/builtins/core/lists/mjoin.go index e9f45adc9..313364ef7 100644 --- a/builtins/core/lists/mjoin.go +++ b/builtins/core/lists/mjoin.go @@ -30,11 +30,15 @@ func cmdMjoin(p *lang.Process) error { func mjoinMethod(p *lang.Process, separator []byte) error { var slice [][]byte - p.Stdin.ReadArray(p.Context, func(b []byte) { + err := p.Stdin.ReadArray(p.Context, func(b []byte) { slice = append(slice, b) }) - _, err := p.Stdout.Write(bytes.Join(slice, separator)) + if err != nil { + return err + } + + _, err = p.Stdout.Write(bytes.Join(slice, separator)) return err } diff --git a/go.mod b/go.mod index b8bd81803..4d914a791 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,8 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/pelletier/go-toml v1.9.5 github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee - golang.org/x/sys v0.8.0 + golang.org/x/sys v0.20.0 + golang.org/x/text v0.17.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.25.0 ) @@ -31,8 +32,9 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/stretchr/testify v1.8.2 // indirect golang.org/x/image v0.18.0 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect lukechampine.com/uint128 v1.2.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect modernc.org/ccgo/v3 v3.16.13 // indirect diff --git a/go.sum b/go.sum index c888a0a9f..7b74bf502 100644 --- a/go.sum +++ b/go.sum @@ -17,7 +17,7 @@ github.com/eliukblau/pixterm v1.3.1 h1:XeouQViH+lmzCa7sMUoK2cd7qlgHYGLIjwRKaOdJb github.com/eliukblau/pixterm v1.3.1/go.mod h1:on5ueknFt+ZFVvIVVzQ7/JXwPjv5fJd8Q1Ybh7XixfU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -60,19 +60,22 @@ golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/version.svg b/version.svg index 28b12a85a..e3c2d65e7 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.3000Version6.3.3000 +Version: 6.3.3100Version6.3.3100 From 2e92e02eb596f4b761cb2d7c760423c2251954b4 Mon Sep 17 00:00:00 2001 From: tiymat <138939221+tiymat@users.noreply.github.com> Date: Sat, 17 Aug 2024 21:07:17 -0230 Subject: [PATCH 042/142] fix broken urls --- builtins/docs/summaries.go | 2 +- compatibility.md | 4 ++-- docs/changelog/README.md | 2 +- docs/changelog/v4.1.md | 10 +++++----- docs/changelog/v4.3.md | 6 +++--- gen/changelog/v4.1_doc.yaml | 8 ++++---- gen/changelog/v4.3_doc.yaml | 4 ++-- gen/root/compatibility.inc.md | 4 ++-- shell/shell.go | 2 +- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 04ddd2c43..2b6fc95ba 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -400,7 +400,7 @@ func init() { "changelog/v3.0": "This is a major release that brings a significant number of changes and improvements, including a complete overhaul of the parser. Backwards compatibility is a high priority however these new features bring greater readability and consistency to shell scripting. So while the older syntax remains for compatibility, it is worth migrating over to the newer syntax for all new code being written", "changelog/v3.1": "This release includes mostly bug fixes and new experimental features which are opt into. To enable all experimental features, set the environmental variable `MUREX_EXPERIMENTAL` to any value. Or you can enable specific features individually via `config`", "changelog/v4.0": "This release sees significant improvements for use with non-latin characters in both the interactive prompt and shell scripting. It introduces new syntax to make working with structured data even easier than before. As well as new data types and smoother user experience.", - "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/docs/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", + "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", "changelog/v4.2": "Murex usage has raised considerably in recent weeks. This release addresses a number of feature requests and bugs raised on Github.", "changelog/v4.3": "This brings improved support on Windows plus one breaking change from the previous release (v4.2)", "changelog/v4.4": "v4.4 features two new builtins, improvements in testing, and automatic generation of autocompletion suggestions backed by man page parsing. Plus there has been a lot of focus on improving _readline_ responsiveness", diff --git a/compatibility.md b/compatibility.md index f46e7403f..1ec5685b6 100644 --- a/compatibility.md +++ b/compatibility.md @@ -61,7 +61,7 @@ Breaking changes _might_ happen outside of the feature deprecation life cycle that solely consists of the new operator is now parsed as an operator rather than a string) -Breaking changes will be published in the [changelog](https://murex.rocks/changelog). +Breaking changes will be published in the [changelog](https://murex.rocks/changelog/). ### Experimental features @@ -91,4 +91,4 @@ Murex releases roughly follows [semantic versioning](https://semver.org/).
-This document was generated from [gen/root/compatibility_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/root/compatibility_doc.yaml). \ No newline at end of file +This document was generated from [gen/root/compatibility_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/root/compatibility_doc.yaml). diff --git a/docs/changelog/README.md b/docs/changelog/README.md index dd68e7aae..8fb7a82dc 100644 --- a/docs/changelog/README.md +++ b/docs/changelog/README.md @@ -56,7 +56,7 @@ Murex usage has raised considerably in recent weeks. This release addresses a nu ### 04.06.2023 - [v4.1.x](../changelog/v4.1.md) -The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/docs/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too +The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too ### 26.03.2023 - [v4.0](../changelog/v4.0.md) diff --git a/docs/changelog/v4.1.md b/docs/changelog/v4.1.md index 5c4937f40..677bb89a0 100644 --- a/docs/changelog/v4.1.md +++ b/docs/changelog/v4.1.md @@ -1,6 +1,6 @@ # v4.1.x -The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/docs/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too +The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too ## v4.1.7300 @@ -12,7 +12,7 @@ None * generic `*` data type marshaller can now marshal maps ([#593](https://github.com/lmorg/murex/issues/593)) -* range can count from end when supplied with a negative index ([read more](https://murex.rocks/docs/commands/range.html)) +* range can count from end when supplied with a negative index ([read more](https://murex.rocks/commands/range.html)) ### Bug Fixes @@ -60,11 +60,11 @@ None * `f`: new flag `i` -- deprecates `?` flag due to `?` being a glob pattern. However `?` will remain supported -* `$PREFIX` variable passed to **Dynamic** and **DynamicDesc** functions in `autocomplete` -- includes the partial term ([read more](https://murex.rocks/docs/commands/autocomplete.html#directives)) +* `$PREFIX` variable passed to **Dynamic** and **DynamicDesc** functions in `autocomplete` -- includes the partial term ([read more](https://murex.rocks/commands/autocomplete.html#directives)) * `user@` completion support for `ssh` -* Updated `autocomplete` docs ([read more](https://murex.rocks/docs/commands/autocomplete.html)) +* Updated `autocomplete` docs ([read more](https://murex.rocks/commands/autocomplete.html)) * command line is included in error message when error running inside another module @@ -158,4 +158,4 @@ Published: 04.06.2023 at 10:44
-This document was generated from [gen/changelog/v4.1_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.1_doc.yaml). \ No newline at end of file +This document was generated from [gen/changelog/v4.1_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.1_doc.yaml). diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index e03dd36b8..7f0ffb7b0 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -6,13 +6,13 @@ This brings improved support on Windows plus one breaking change from the previo * `pre-prompt-func` and `post-prompt-func` have been replaced with `onPrompt` events: `event onKeyPress example=before { ... }` -* The `onFileSystemChange` event payload now lowercases the filesystem event operation string. However until this release, that payload was undocumented ([read more](https://murex.rocks/docs/events/onfilesystemchange.html)) +* The `onFileSystemChange` event payload now lowercases the filesystem event operation string. However until this release, that payload was undocumented ([read more](https://murex.rocks/events/onfilesystemchange.html)) ## Features * New events, `onPrompt`, triggered when the interactive prompt is at various stages -* **Dynamic** and **DynamicDesc** autocompletions can have their partial term prefix filter disabled ([read more](https://murex.rocks/docs/commands/autocomplete.html#ignoreprefix-boolean-false), [previous discussion](https://github.com/lmorg/murex/issues/635)) +* **Dynamic** and **DynamicDesc** autocompletions can have their partial term prefix filter disabled ([read more](https://murex.rocks/commands/autocomplete.html#ignoreprefix-boolean-false), [previous discussion](https://github.com/lmorg/murex/issues/635)) * New autocompletions: `gping` @@ -39,4 +39,4 @@ Published: 02.07.2023 at 09:55
-This document was generated from [gen/changelog/v4.3_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.3_doc.yaml). \ No newline at end of file +This document was generated from [gen/changelog/v4.3_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.3_doc.yaml). diff --git a/gen/changelog/v4.1_doc.yaml b/gen/changelog/v4.1_doc.yaml index afaa28f31..5bb16dd6f 100644 --- a/gen/changelog/v4.1_doc.yaml +++ b/gen/changelog/v4.1_doc.yaml @@ -4,7 +4,7 @@ CategoryID: changelog DateTime: 2023-06-04 10:44 Summary: >- - The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/docs/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too + The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too Description: |- ## v4.1.7300 @@ -16,7 +16,7 @@ * generic `*` data type marshaller can now marshal maps ([#593](https://github.com/lmorg/murex/issues/593)) - * range can count from end when supplied with a negative index ([read more](https://murex.rocks/docs/commands/range.html)) + * range can count from end when supplied with a negative index ([read more](https://murex.rocks/commands/range.html)) ### Bug Fixes @@ -64,11 +64,11 @@ * `f`: new flag `i` -- deprecates `?` flag due to `?` being a glob pattern. However `?` will remain supported - * `$PREFIX` variable passed to **Dynamic** and **DynamicDesc** functions in `autocomplete` -- includes the partial term ([read more](https://murex.rocks/docs/commands/autocomplete.html#directives)) + * `$PREFIX` variable passed to **Dynamic** and **DynamicDesc** functions in `autocomplete` -- includes the partial term ([read more](https://murex.rocks/commands/autocomplete.html#directives)) * `user@` completion support for `ssh` - * Updated `autocomplete` docs ([read more](https://murex.rocks/docs/commands/autocomplete.html)) + * Updated `autocomplete` docs ([read more](https://murex.rocks/commands/autocomplete.html)) * command line is included in error message when error running inside another module diff --git a/gen/changelog/v4.3_doc.yaml b/gen/changelog/v4.3_doc.yaml index b9e407c26..918a4ef88 100644 --- a/gen/changelog/v4.3_doc.yaml +++ b/gen/changelog/v4.3_doc.yaml @@ -10,13 +10,13 @@ * `pre-prompt-func` and `post-prompt-func` have been replaced with `onPrompt` events: `event onKeyPress example=before { ... }` - * The `onFileSystemChange` event payload now lowercases the filesystem event operation string. However until this release, that payload was undocumented ([read more](https://murex.rocks/docs/events/onfilesystemchange.html)) + * The `onFileSystemChange` event payload now lowercases the filesystem event operation string. However until this release, that payload was undocumented ([read more](https://murex.rocks/events/onfilesystemchange.html)) ## Features * New events, `onPrompt`, triggered when the interactive prompt is at various stages - * **Dynamic** and **DynamicDesc** autocompletions can have their partial term prefix filter disabled ([read more](https://murex.rocks/docs/commands/autocomplete.html#ignoreprefix-boolean-false), [previous discussion](https://github.com/lmorg/murex/issues/635)) + * **Dynamic** and **DynamicDesc** autocompletions can have their partial term prefix filter disabled ([read more](https://murex.rocks/commands/autocomplete.html#ignoreprefix-boolean-false), [previous discussion](https://github.com/lmorg/murex/issues/635)) * New autocompletions: `gping` diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index 4f90f42e4..10b7805f6 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -66,7 +66,7 @@ Breaking changes _might_ happen outside of the feature deprecation life cycle that solely consists of the new operator is now parsed as an operator rather than a string) -Breaking changes will be published in the [changelog](https://murex.rocks/changelog). +Breaking changes will be published in the [changelog](https://murex.rocks/changelog/). ### Experimental features @@ -85,4 +85,4 @@ yet been released to `master` is considered experimental. ### Versioning -Murex releases roughly follows [semantic versioning](https://semver.org/). \ No newline at end of file +Murex releases roughly follows [semantic versioning](https://semver.org/). diff --git a/shell/shell.go b/shell/shell.go index 01f48c638..131fad0de 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -382,7 +382,7 @@ func Spellchecker(r []rune) []rune { new, err := spellcheck.String(s) if err != nil && !ignoreSpellCheckErr { ignoreSpellCheckErr = true - hint := fmt.Sprintf("{RED}Spellchecker error: %s{RESET} {BLUE}https://murex.rocks/docs/user-guide/spellcheck.html{RESET}", err.Error()) + hint := fmt.Sprintf("{RED}Spellchecker error: %s{RESET} {BLUE}https://murex.rocks/user-guide/spellcheck.html{RESET}", err.Error()) Prompt.ForceHintTextUpdate(ansi.ExpandConsts(hint)) } From 357070f50132b5c6fa41c7e642805fd13e710b7b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 18 Aug 2024 21:51:43 +0300 Subject: [PATCH 043/142] deprecated builtin: `die` --- builtins/core/typemgmt/types.go | 2 ++ builtins/core/typemgmt/types_doc.yaml | 5 ++++- builtins/docs/summaries.go | 4 ++-- docs/commands/README.md | 2 +- docs/commands/devnull.md | 2 +- docs/commands/die.md | 5 ++++- docs/commands/exit.md | 2 +- docs/user-guide/README.md | 2 +- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/builtins/core/typemgmt/types.go b/builtins/core/typemgmt/types.go index 7c0f250be..2a0920562 100644 --- a/builtins/core/typemgmt/types.go +++ b/builtins/core/typemgmt/types.go @@ -69,6 +69,8 @@ func cmdNot(p *lang.Process) error { func cmdDie(p *lang.Process) error { p.Stdout.SetDataType(types.Die) + lang.FeatureDeprecatedBuiltin(p) + lang.Exit(1) return nil } diff --git a/builtins/core/typemgmt/types_doc.yaml b/builtins/core/typemgmt/types_doc.yaml index 6e76bed2e..a4e66e7ba 100644 --- a/builtins/core/typemgmt/types_doc.yaml +++ b/builtins/core/typemgmt/types_doc.yaml @@ -84,9 +84,12 @@ `die` CategoryID: commands Summary: >- - Terminate murex with an exit number of 1 + Terminate murex with an exit number of 1 (deprecated) Description: |- Terminate Murex with an exit number of 1. + + > This builtin has now been deprecated. The same behaviour can be achieved via + > `exit 1` Usage: |- ``` die diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 04ddd2c43..0f0c2b57c 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -31,7 +31,7 @@ func init() { "cpucount": "Output the number of CPU cores available on your host", "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", "debug": "Debugging information", - "die": "Terminate murex with an exit number of 1", + "die": "Terminate murex with an exit number of 1 (deprecated)", "err": "Print a line to the stderr", "escape": "Escape or unescape input", "esccli": "Escapes an array so output is valid shell code", @@ -161,7 +161,7 @@ func init() { "commands/cpucount": "Output the number of CPU cores available on your host", "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", "commands/debug": "Debugging information", - "commands/die": "Terminate murex with an exit number of 1", + "commands/die": "Terminate murex with an exit number of 1 (deprecated)", "commands/err": "Print a line to the stderr", "commands/escape": "Escape or unescape input", "commands/esccli": "Escapes an array so output is valid shell code", diff --git a/docs/commands/README.md b/docs/commands/README.md index e52870f4a..5c43ba20c 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -87,7 +87,7 @@ murex-docs trypipe * [`debug`](../commands/debug.md): Debugging information * [`die`](../commands/die.md): - Terminate murex with an exit number of 1 + Terminate murex with an exit number of 1 (deprecated) * [`err`](../commands/err.md): Print a line to the stderr * [`escape`](../commands/escape.md): diff --git a/docs/commands/devnull.md b/docs/commands/devnull.md index 0a3b359e1..91047baa3 100644 --- a/docs/commands/devnull.md +++ b/docs/commands/devnull.md @@ -38,7 +38,7 @@ use the named pipe property rather than piping to null: * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`die`](../commands/die.md): - Terminate murex with an exit number of 1 + Terminate murex with an exit number of 1 (deprecated) * [`exit`](../commands/exit.md): Exit murex diff --git a/docs/commands/die.md b/docs/commands/die.md index f3640ba76..7ece07d5c 100644 --- a/docs/commands/die.md +++ b/docs/commands/die.md @@ -1,11 +1,14 @@ # `die` -> Terminate murex with an exit number of 1 +> Terminate murex with an exit number of 1 (deprecated) ## Description Terminate Murex with an exit number of 1. +> This builtin has now been deprecated. The same behaviour can be achieved via +> `exit 1` + ## Usage ``` diff --git a/docs/commands/exit.md b/docs/commands/exit.md index e8e5020c6..0a8c089dd 100644 --- a/docs/commands/exit.md +++ b/docs/commands/exit.md @@ -33,7 +33,7 @@ exit number * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`die`](../commands/die.md): - Terminate murex with an exit number of 1 + Terminate murex with an exit number of 1 (deprecated) * [`null`](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index d050e3163..ea1b0f491 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -196,7 +196,7 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. * [`debug`](../commands/debug.md): Debugging information * [`die`](../commands/die.md): - Terminate murex with an exit number of 1 + Terminate murex with an exit number of 1 (deprecated) * [`err`](../commands/err.md): Print a line to the stderr * [`escape`](../commands/escape.md): From 5056dcbbb83d5b34a03a57c3a679410d99fc0f33 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 19 Aug 2024 22:22:53 +0300 Subject: [PATCH 044/142] alias `list.string` renamed to `list.match` --- builtins/core/lists/list.go | 6 ++---- builtins/docs/summaries.go | 6 ++++++ docs/commands/cpuarch.md | 8 +++++++- docs/commands/cpucount.md | 8 +++++++- docs/commands/os.md | 8 +++++++- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/builtins/core/lists/list.go b/builtins/core/lists/list.go index f991b9d64..94bc5b56b 100644 --- a/builtins/core/lists/list.go +++ b/builtins/core/lists/list.go @@ -16,10 +16,8 @@ func init() { alias list.right = right alias list.regex = regexp alias !list.regex = !regexp - alias list.string = match - alias !list.string = !match - alias list.split = jsplit + alias list.match = match + alias !list.match = !match alias list.join = mjoin - alias list.count = count `) } diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 0f0c2b57c..605339a0c 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -448,7 +448,9 @@ func init() { "len": "count", "list.count": "count", "cpuarch": "cpuarch", + "sys.cpu.arch": "cpuarch", "cpucount": "cpucount", + "sys.cpu.count": "cpucount", "datetime": "datetime", "debug": "debug", "die": "die", @@ -538,6 +540,7 @@ func init() { "or": "or", "!or": "or", "os": "os", + "sys.os": "os", "out": "out", "echo": "out", "pipe": "pipe", @@ -682,7 +685,9 @@ func init() { "commands/len": "commands/count", "commands/list.count": "commands/count", "commands/cpuarch": "commands/cpuarch", + "commands/sys.cpu.arch": "commands/cpuarch", "commands/cpucount": "commands/cpucount", + "commands/sys.cpu.count": "commands/cpucount", "commands/datetime": "commands/datetime", "commands/debug": "commands/debug", "commands/die": "commands/die", @@ -772,6 +777,7 @@ func init() { "commands/or": "commands/or", "commands/!or": "commands/or", "commands/os": "commands/os", + "commands/sys.os": "commands/os", "commands/out": "commands/out", "commands/echo": "commands/out", "commands/pipe": "commands/pipe", diff --git a/docs/commands/cpuarch.md b/docs/commands/cpuarch.md index eef8967e2..c38ee022b 100644 --- a/docs/commands/cpuarch.md +++ b/docs/commands/cpuarch.md @@ -19,6 +19,12 @@ cpuarch -> amd64 ``` +## Synonyms + +* `cpuarch` +* `sys.cpu.arch` + + ## See Also * [`cpucount`](../commands/cpucount.md): @@ -28,4 +34,4 @@ amd64
-This document was generated from [builtins/core/management/functions_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/management/functions_doc.yaml). \ No newline at end of file +This document was generated from [builtins/core/system/system_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/system/system_doc.yaml). \ No newline at end of file diff --git a/docs/commands/cpucount.md b/docs/commands/cpucount.md index 21ef6ff8d..43b4f4cce 100644 --- a/docs/commands/cpucount.md +++ b/docs/commands/cpucount.md @@ -19,6 +19,12 @@ cpucount -> 4 ``` +## Synonyms + +* `cpucount` +* `sys.cpu.count` + + ## See Also * [`cpuarch`](../commands/cpuarch.md): @@ -28,4 +34,4 @@ cpucount ->
-This document was generated from [builtins/core/management/functions_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/management/functions_doc.yaml). \ No newline at end of file +This document was generated from [builtins/core/system/system_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/system/system_doc.yaml). \ No newline at end of file diff --git a/docs/commands/os.md b/docs/commands/os.md index 74ee9c008..ad8083d71 100644 --- a/docs/commands/os.md +++ b/docs/commands/os.md @@ -69,6 +69,12 @@ POSIX-compliant. For that reason, `os` returns false with the `posix` parameter when run on Plan 9. If you want to include Plan 9 in the check then please write it as `os posix plan9`. +## Synonyms + +* `os` +* `sys.os` + + ## See Also * [`cpuarch`](../commands/cpuarch.md): @@ -78,4 +84,4 @@ then please write it as `os posix plan9`.
-This document was generated from [builtins/core/management/functions_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/management/functions_doc.yaml). \ No newline at end of file +This document was generated from [builtins/core/system/system_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/system/system_doc.yaml). \ No newline at end of file From ce19e61526b58ff3418aada3c7d51b9e920beb88 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 19 Aug 2024 22:25:34 +0300 Subject: [PATCH 045/142] builtin refactor: `sys.` builtins --- builtins/core.go | 1 + builtins/core/management/functions.go | 36 ----- builtins/core/management/functions_doc.yaml | 128 ----------------- builtins/core/management/functions_test.go | 26 ---- builtins/core/system/system.go | 54 ++++++++ builtins/core/system/system_doc.yaml | 131 ++++++++++++++++++ builtins/core/system/system_test.go | 34 +++++ builtins/core/system/system_unix_test.go | 26 ++++ .../core/system/system_windows_test copy.go | 26 ++++ 9 files changed, 272 insertions(+), 190 deletions(-) create mode 100644 builtins/core/system/system.go create mode 100644 builtins/core/system/system_doc.yaml create mode 100644 builtins/core/system/system_test.go create mode 100644 builtins/core/system/system_unix_test.go create mode 100644 builtins/core/system/system_windows_test copy.go diff --git a/builtins/core.go b/builtins/core.go index 130c2867d..b949b0038 100644 --- a/builtins/core.go +++ b/builtins/core.go @@ -33,6 +33,7 @@ import ( _ "github.com/lmorg/murex/builtins/core/ranges" // working with ranges within arrays (`@[..]`) _ "github.com/lmorg/murex/builtins/core/runtime" // runtime inspection _ "github.com/lmorg/murex/builtins/core/structs" // control structures + _ "github.com/lmorg/murex/builtins/core/system" // query the host system _ "github.com/lmorg/murex/builtins/core/tabulate" // function to auto-tabulise data _ "github.com/lmorg/murex/builtins/core/test" // testing framework for murex shell scripts _ "github.com/lmorg/murex/builtins/core/time" // time-based utilities diff --git a/builtins/core/management/functions.go b/builtins/core/management/functions.go index a876bf3d1..9c5a0602a 100644 --- a/builtins/core/management/functions.go +++ b/builtins/core/management/functions.go @@ -3,7 +3,6 @@ package management import ( "errors" "fmt" - "runtime" "strconv" "github.com/lmorg/murex/lang" @@ -14,16 +13,12 @@ import ( "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/lists" "github.com/lmorg/murex/utils/man" - "github.com/lmorg/murex/utils/posix" ) func init() { lang.DefineFunction("exitnum", cmdExitNum, types.Integer) lang.DefineFunction("bexists", cmdBuiltinExists, types.Json) lang.DefineFunction("cd", cmdCd, types.Null) - lang.DefineFunction("os", cmdOs, types.String) - lang.DefineFunction("cpuarch", cmdCpuArch, types.String) - lang.DefineFunction("cpucount", cmdCpuCount, types.Integer) lang.DefineFunction("murex-update-exe-list", cmdUpdateExeList, types.Null) lang.DefineFunction("man-summary", cmdManSummary, types.Null) } @@ -90,37 +85,6 @@ func cmdCd(p *lang.Process) error { } } -func cmdOs(p *lang.Process) error { - if p.Parameters.Len() == 0 { - p.Stdout.SetDataType(types.String) - _, err := p.Stdout.Write([]byte(runtime.GOOS)) - return err - } - - for _, os := range p.Parameters.StringArray() { - if os == runtime.GOOS || (os == "posix" && posix.IsPosix()) { - _, err := p.Stdout.Write(types.TrueByte) - return err - } - } - - p.ExitNum = 1 - _, err := p.Stdout.Write(types.FalseByte) - return err -} - -func cmdCpuArch(p *lang.Process) (err error) { - p.Stdout.SetDataType(types.String) - _, err = p.Stdout.Write([]byte(runtime.GOARCH)) - return -} - -func cmdCpuCount(p *lang.Process) (err error) { - p.Stdout.SetDataType(types.Integer) - _, err = p.Stdout.Write([]byte(strconv.Itoa(runtime.NumCPU()))) - return -} - func cmdUpdateExeList(p *lang.Process) error { p.Stdout.SetDataType(types.Null) autocomplete.UpdateGlobalExeList() diff --git a/builtins/core/management/functions_doc.yaml b/builtins/core/management/functions_doc.yaml index a1bbe804e..c8880be4d 100644 --- a/builtins/core/management/functions_doc.yaml +++ b/builtins/core/management/functions_doc.yaml @@ -24,134 +24,6 @@ -- DocumentID: os - Title: >+ - `os` - CategoryID: commands - Summary: >- - Output the auto-detected OS name - Description: |- - Output the auto-detected OS name. - Usage: |- - ``` - os -> - - os string -> - ``` - Examples: |- - ### Name current platform - - ``` - » os - linux - ``` - - ### Check platforms - - Or if you want to check if the host is one of a number of platforms: - - ``` - # When run on Linux or FreeBSD - » os linux freebsd - true - - # When run on another platform, eg Windows or Darwin (macOS) - # (exit number would also be `1`) - » os linux freebsd - false - ``` - - The intention is this allows simple tests in scripts: - - ``` - if { os windows } then { - # run some Windows specific code - } - ``` - - ### POSIX - - `posix` is also supported to check if Murex is running on a UNIX-like operating - system. - - All Murex targets _apart_ from Windows and Plan 9 are considered POSIX. - - ``` - # When run on Linux or macOS - » os posix - true - - # When run on Windows or Plan 9 - # (exit number would also be `1`) - » os posix - false - ``` - - Please note that although Plan 9 shares similarities with POSIX, it is not - POSIX-compliant. For that reason, `os` returns false with the `posix` - parameter when run on Plan 9. If you want to include Plan 9 in the check - then please write it as `os posix plan9`. - Flags: - Detail: |- - Synonyms: - Related: - - cpuarch - - cpucount - - - -- DocumentID: cpuarch - Title: >+ - `cpuarch` - CategoryID: commands - Summary: >- - Output the hosts CPU architecture - Description: |- - Output the hosts CPU architecture. - Usage: |- - ``` - cpuarch -> - ``` - Examples: |- - ``` - » cpuarch - amd64 - ``` - Flags: - Detail: |- - Synonyms: - Related: - - os - - cpucount - - - -- DocumentID: cpucount - Title: >+ - `cpucount` - CategoryID: commands - Summary: >- - Output the number of CPU cores available on your host - Description: |- - Output the number of CPU cores available on your host. - Usage: |- - ``` - cpucount -> - ``` - Examples: |- - ``` - » cpucount - 4 - ``` - Flags: - Detail: |- - Synonyms: - Related: - - os - - cpuarch - - - - DocumentID: murex-update-exe-list Title: >+ `murex-update-exe-list` diff --git a/builtins/core/management/functions_test.go b/builtins/core/management/functions_test.go index f3c555466..82c6733e6 100644 --- a/builtins/core/management/functions_test.go +++ b/builtins/core/management/functions_test.go @@ -1,7 +1,6 @@ package management_test import ( - "runtime" "testing" _ "github.com/lmorg/murex/builtins" @@ -65,28 +64,3 @@ func TestBuiltinExistsErrors(t *testing.T) { test.RunMurexTestsRx(tests, t) } - -func TestOs(t *testing.T) { - tests := []test.MurexTest{ - { - Block: `os`, - Stdout: runtime.GOOS, - }, - { - Block: `os: bob`, - Stdout: "false", - ExitNum: 1, - }, - { - Block: `os: windows`, - Stdout: "false", - ExitNum: 1, - }, - { - Block: `os: ` + runtime.GOOS, - Stdout: "true", - }, - } - - test.RunMurexTests(tests, t) -} diff --git a/builtins/core/system/system.go b/builtins/core/system/system.go new file mode 100644 index 000000000..f248a3bad --- /dev/null +++ b/builtins/core/system/system.go @@ -0,0 +1,54 @@ +package system + +import ( + "runtime" + "strconv" + + "github.com/lmorg/murex/config/defaults" + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/types" + "github.com/lmorg/murex/utils/posix" +) + +func init() { + lang.DefineFunction("os", cmdOs, types.String) + lang.DefineFunction("cpuarch", cmdCpuArch, types.String) + lang.DefineFunction("cpucount", cmdCpuCount, types.Integer) + + defaults.AppendProfile(` + alias sys.os = os + alias sys.cpu.arch = cpuarch + alias sys.cpu.count = cpucount + `) +} + +func cmdOs(p *lang.Process) error { + if p.Parameters.Len() == 0 { + p.Stdout.SetDataType(types.String) + _, err := p.Stdout.Write([]byte(runtime.GOOS)) + return err + } + + for _, os := range p.Parameters.StringArray() { + if os == runtime.GOOS || (os == "posix" && posix.IsPosix()) { + _, err := p.Stdout.Write(types.TrueByte) + return err + } + } + + p.ExitNum = 1 + _, err := p.Stdout.Write(types.FalseByte) + return err +} + +func cmdCpuArch(p *lang.Process) (err error) { + p.Stdout.SetDataType(types.String) + _, err = p.Stdout.Write([]byte(runtime.GOARCH)) + return +} + +func cmdCpuCount(p *lang.Process) (err error) { + p.Stdout.SetDataType(types.Integer) + _, err = p.Stdout.Write([]byte(strconv.Itoa(runtime.NumCPU()))) + return +} diff --git a/builtins/core/system/system_doc.yaml b/builtins/core/system/system_doc.yaml new file mode 100644 index 000000000..21a1c85f9 --- /dev/null +++ b/builtins/core/system/system_doc.yaml @@ -0,0 +1,131 @@ +- DocumentID: os + Title: >+ + `os` + CategoryID: commands + Summary: >- + Output the auto-detected OS name + Description: |- + Output the auto-detected OS name. + Usage: |- + ``` + os -> + + os string -> + ``` + Examples: |- + ### Name current platform + + ``` + » os + linux + ``` + + ### Check platforms + + Or if you want to check if the host is one of a number of platforms: + + ``` + # When run on Linux or FreeBSD + » os linux freebsd + true + + # When run on another platform, eg Windows or Darwin (macOS) + # (exit number would also be `1`) + » os linux freebsd + false + ``` + + The intention is this allows simple tests in scripts: + + ``` + if { os windows } then { + # run some Windows specific code + } + ``` + + ### POSIX + + `posix` is also supported to check if Murex is running on a UNIX-like operating + system. + + All Murex targets _apart_ from Windows and Plan 9 are considered POSIX. + + ``` + # When run on Linux or macOS + » os posix + true + + # When run on Windows or Plan 9 + # (exit number would also be `1`) + » os posix + false + ``` + + Please note that although Plan 9 shares similarities with POSIX, it is not + POSIX-compliant. For that reason, `os` returns false with the `posix` + parameter when run on Plan 9. If you want to include Plan 9 in the check + then please write it as `os posix plan9`. + Flags: + Detail: |- + Synonyms: + - os + - sys.os + Related: + - cpuarch + - cpucount + + + +- DocumentID: cpuarch + Title: >+ + `cpuarch` + CategoryID: commands + Summary: >- + Output the hosts CPU architecture + Description: |- + Output the hosts CPU architecture. + Usage: |- + ``` + cpuarch -> + ``` + Examples: |- + ``` + » cpuarch + amd64 + ``` + Flags: + Detail: |- + Synonyms: + - cpuarch + - sys.cpu.arch + Related: + - os + - cpucount + + + +- DocumentID: cpucount + Title: >+ + `cpucount` + CategoryID: commands + Summary: >- + Output the number of CPU cores available on your host + Description: |- + Output the number of CPU cores available on your host. + Usage: |- + ``` + cpucount -> + ``` + Examples: |- + ``` + » cpucount + 4 + ``` + Flags: + Detail: |- + Synonyms: + - cpucount + - sys.cpu.count + Related: + - os + - cpuarch diff --git a/builtins/core/system/system_test.go b/builtins/core/system/system_test.go new file mode 100644 index 000000000..096d44e20 --- /dev/null +++ b/builtins/core/system/system_test.go @@ -0,0 +1,34 @@ +package system_test + +import ( + "runtime" + "testing" + + _ "github.com/lmorg/murex/builtins" + "github.com/lmorg/murex/test" +) + +func TestOs(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `os`, + Stdout: runtime.GOOS, + }, + { + Block: `os bob`, + Stdout: "false", + ExitNum: 1, + }, + { + Block: `os ` + runtime.GOOS, + Stdout: "true", + }, + } + + test.RunMurexTests(tests, t) +} +{ + Block: `os posix`, + Stdout: "false", + ExitNum: 1, +}, \ No newline at end of file diff --git a/builtins/core/system/system_unix_test.go b/builtins/core/system/system_unix_test.go new file mode 100644 index 000000000..fdbb5ad1e --- /dev/null +++ b/builtins/core/system/system_unix_test.go @@ -0,0 +1,26 @@ +//go:build !windows && !plan9 && !js +// +build !windows,!plan9,!js + +package system_test + +import ( + "testing" + + _ "github.com/lmorg/murex/builtins" + "github.com/lmorg/murex/test" +) + +func TestOsWindows(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `os windows`, + Stdout: "true", + }, + { + Block: `os posix`, + Stdout: "false", + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/builtins/core/system/system_windows_test copy.go b/builtins/core/system/system_windows_test copy.go new file mode 100644 index 000000000..3afcd4f60 --- /dev/null +++ b/builtins/core/system/system_windows_test copy.go @@ -0,0 +1,26 @@ +//go:build windows +// +build windows + +package system_test + +import ( + "testing" + + _ "github.com/lmorg/murex/builtins" + "github.com/lmorg/murex/test" +) + +func TestOsUnix(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `os windows`, + Stdout: "true", + }, + { + Block: `os posix`, + Stdout: "false", + }, + } + + test.RunMurexTests(tests, t) +} From 7a253d6a2b3ca82bf91a0eeb49591b4d13698066 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 20 Aug 2024 18:34:15 +0300 Subject: [PATCH 046/142] updated docs + aliases --- builtins/core/arraytools/2darray_doc.yaml | 4 +- builtins/core/arraytools/struct.go | 11 ++++ builtins/core/datatools/struct.go | 11 ++++ builtins/core/lists/case_doc.yaml | 46 +++++++++++++++ builtins/core/lists/case_doc.yaml.todo | 39 ------------ builtins/core/lists/mjoin_doc.yaml | 14 ++--- builtins/core/system/system_test.go | 5 -- builtins/core/system/system_unix_test.go | 7 ++- ...ws_test copy.go => system_windows_test.go} | 5 +- builtins/docs/summaries.go | 18 ++++-- docs/commands/2darray.md | 8 ++- docs/commands/README.md | 6 +- docs/commands/list.case.md | 59 +++++++++++++++++++ docs/commands/{list.join.md => mjoin.md} | 12 ++-- docs/user-guide/README.md | 6 +- 15 files changed, 177 insertions(+), 74 deletions(-) create mode 100644 builtins/core/arraytools/struct.go create mode 100644 builtins/core/datatools/struct.go create mode 100644 builtins/core/lists/case_doc.yaml delete mode 100644 builtins/core/lists/case_doc.yaml.todo rename builtins/core/system/{system_windows_test copy.go => system_windows_test.go} (83%) create mode 100644 docs/commands/list.case.md rename docs/commands/{list.join.md => mjoin.md} (80%) diff --git a/builtins/core/arraytools/2darray_doc.yaml b/builtins/core/arraytools/2darray_doc.yaml index af2d1687e..7e7cfded2 100644 --- a/builtins/core/arraytools/2darray_doc.yaml +++ b/builtins/core/arraytools/2darray_doc.yaml @@ -8,7 +8,7 @@ `2darray` merges multiple input sources to create a two dimensional array in JSON Usage: |- ``` - 2darray { code-block } { code-block } -> + 2darray { code-block } { code-block } ... -> ``` Examples: |- ``` @@ -86,6 +86,8 @@ Detail: |- `2darray` can have as many or as few code blocks as you wish. Synonyms: + - 2darray + - struct.2darray Related: - prepend - append diff --git a/builtins/core/arraytools/struct.go b/builtins/core/arraytools/struct.go new file mode 100644 index 000000000..64181e7bf --- /dev/null +++ b/builtins/core/arraytools/struct.go @@ -0,0 +1,11 @@ +package arraytools + +import "github.com/lmorg/murex/config/defaults" + +func init() { + defaults.AppendProfile(` + alias struct.new.2darray = 2darray + alias struct.new.heading = addheading + alias struct.new.map = map + `) +} diff --git a/builtins/core/datatools/struct.go b/builtins/core/datatools/struct.go new file mode 100644 index 000000000..4353247b4 --- /dev/null +++ b/builtins/core/datatools/struct.go @@ -0,0 +1,11 @@ +package datatools + +import "github.com/lmorg/murex/config/defaults" + +func init() { + defaults.AppendProfile(` + alias struct.alter = alter + alias struct.count = count + alias struct.keys = struct-keys + `) +} diff --git a/builtins/core/lists/case_doc.yaml b/builtins/core/lists/case_doc.yaml new file mode 100644 index 000000000..38d44f299 --- /dev/null +++ b/builtins/core/lists/case_doc.yaml @@ -0,0 +1,46 @@ +- DocumentID: list.case + Title: >- + `list.case` + CategoryID: commands + Summary: >- + Changes the character case of a string or all elements in an array + Description: |- + `list.case` will read an array from either stdin or it's command line + parameters, and change that list to be upper or lower case. + Usage: |- + ``` + -> list.case operation -> + list.case operation item1 [ item2 item3 ... ] -> + ``` + Examples: |- + ### As a method + + ``` + » %[Monday..Friday] -> list.case upper + [ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY" + ] + ``` + + ### As a function + + ``` + » list.case lower @{ %[Monday..Friday] } + [ + "monday", + "tuesday", + "wednesday", + "thursday", + "friday" + ] + ``` + Detail: + Synonyms: + - list.case + Related: + - array + - create-array diff --git a/builtins/core/lists/case_doc.yaml.todo b/builtins/core/lists/case_doc.yaml.todo deleted file mode 100644 index 8514e9f19..000000000 --- a/builtins/core/lists/case_doc.yaml.todo +++ /dev/null @@ -1,39 +0,0 @@ -- DocumentID: list.join - Title: >- - `list.join` - CategoryID: commands - Summary: >- - Joins a list or array into a single string - Description: |- - `mjoin` will read an array from either stdin or it's command line parameters, - and joins those elements together to form a single string. - - The string will be delimited by the separator defined as the first command line - parameter. - Usage: |- - ``` - -> list.join separator -> - list.join separator item1 item2 item3... -> - ``` - Examples: |- - ### As a method - - ``` - » %[Monday..Friday] -> list.join ! - Monday!Tuesday!Wednesday!Thursday!Friday - ``` - - ### As a function - - ``` - » list.join ! @{ %[Monday..Friday] } - Monday!Tuesday!Wednesday!Thursday!Friday - ``` - Detail: - Synonyms: - - list.join - - mjoin - Related: - - jsplit - - array - - create-array diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml index 8514e9f19..88f6a066a 100644 --- a/builtins/core/lists/mjoin_doc.yaml +++ b/builtins/core/lists/mjoin_doc.yaml @@ -1,6 +1,6 @@ -- DocumentID: list.join +- DocumentID: mjoin Title: >- - `list.join` + `mjoin` CategoryID: commands Summary: >- Joins a list or array into a single string @@ -12,27 +12,27 @@ parameter. Usage: |- ``` - -> list.join separator -> - list.join separator item1 item2 item3... -> + -> mjoin separator -> + mjoin separator item1 [ item2 item3 ... ] -> ``` Examples: |- ### As a method ``` - » %[Monday..Friday] -> list.join ! + » %[Monday..Friday] -> mjoin ! Monday!Tuesday!Wednesday!Thursday!Friday ``` ### As a function ``` - » list.join ! @{ %[Monday..Friday] } + » mjoin ! @{ %[Monday..Friday] } Monday!Tuesday!Wednesday!Thursday!Friday ``` Detail: Synonyms: - - list.join - mjoin + - list.join Related: - jsplit - array diff --git a/builtins/core/system/system_test.go b/builtins/core/system/system_test.go index 096d44e20..ce042ad88 100644 --- a/builtins/core/system/system_test.go +++ b/builtins/core/system/system_test.go @@ -27,8 +27,3 @@ func TestOs(t *testing.T) { test.RunMurexTests(tests, t) } -{ - Block: `os posix`, - Stdout: "false", - ExitNum: 1, -}, \ No newline at end of file diff --git a/builtins/core/system/system_unix_test.go b/builtins/core/system/system_unix_test.go index fdbb5ad1e..fe7c74d92 100644 --- a/builtins/core/system/system_unix_test.go +++ b/builtins/core/system/system_unix_test.go @@ -13,12 +13,13 @@ import ( func TestOsWindows(t *testing.T) { tests := []test.MurexTest{ { - Block: `os windows`, - Stdout: "true", + Block: `os windows`, + Stdout: "false", + ExitNum: 1, }, { Block: `os posix`, - Stdout: "false", + Stdout: "true", }, } diff --git a/builtins/core/system/system_windows_test copy.go b/builtins/core/system/system_windows_test.go similarity index 83% rename from builtins/core/system/system_windows_test copy.go rename to builtins/core/system/system_windows_test.go index 3afcd4f60..544def632 100644 --- a/builtins/core/system/system_windows_test copy.go +++ b/builtins/core/system/system_windows_test.go @@ -17,8 +17,9 @@ func TestOsUnix(t *testing.T) { Stdout: "true", }, { - Block: `os posix`, - Stdout: "false", + Block: `os posix`, + Stdout: "false", + ExitNum: 1, }, } diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 605339a0c..2f03c04ac 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -68,13 +68,14 @@ func init() { "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "left": "Left substring every item in a list", "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "list.join": "Joins a list or array into a single string", + "list.case": "Changes the character case of a string or all elements in an array", "lockfile": "Create and manage lock files", "man-get-flags": "Parses man page files for command line flags", "man-summary": "Outputs a man page summary of a command", "map": "Creates a map from two data sources", "match": "Match an exact value in an array", "method": "Define a methods supported data-types", + "mjoin": "Joins a list or array into a single string", "msort": "Sorts an array - data type agnostic", "mtac": "Reverse the order of an array", "murex-docs": "Displays the man pages for Murex builtins", @@ -198,13 +199,14 @@ func init() { "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "commands/left": "Left substring every item in a list", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/list.join": "Joins a list or array into a single string", + "commands/list.case": "Changes the character case of a string or all elements in an array", "commands/lockfile": "Create and manage lock files", "commands/man-get-flags": "Parses man page files for command line flags", "commands/man-summary": "Outputs a man page summary of a command", "commands/map": "Creates a map from two data sources", "commands/match": "Match an exact value in an array", "commands/method": "Define a methods supported data-types", + "commands/mjoin": "Joins a list or array into a single string", "commands/msort": "Sorts an array - data type agnostic", "commands/mtac": "Reverse the order of an array", "commands/murex-docs": "Displays the man pages for Murex builtins", @@ -418,6 +420,7 @@ func init() { "!": "not-func", "not": "not-func", "2darray": "2darray", + "struct.2darray": "2darray", "(murex named pipe)": "namedpipe", "<>": "namedpipe", "read-named-pipe": "namedpipe", @@ -512,8 +515,7 @@ func init() { "left": "left", "list.left": "left", "let": "let", - "list.join": "list.join", - "mjoin": "list.join", + "list.case": "list.case", "lockfile": "lockfile", "man-get-flags": "man-get-flags", "man-summary": "man-summary", @@ -523,6 +525,8 @@ func init() { "list.string": "match", "!list.string": "match", "method": "method", + "mjoin": "mjoin", + "list.join": "mjoin", "msort": "msort", "list.sort": "msort", "mtac": "mtac", @@ -655,6 +659,7 @@ func init() { "commands/!": "commands/not-func", "commands/not": "commands/not-func", "commands/2darray": "commands/2darray", + "commands/struct.2darray": "commands/2darray", "commands/(murex named pipe)": "commands/namedpipe", "commands/<>": "commands/namedpipe", "commands/read-named-pipe": "commands/namedpipe", @@ -749,8 +754,7 @@ func init() { "commands/left": "commands/left", "commands/list.left": "commands/left", "commands/let": "commands/let", - "commands/list.join": "commands/list.join", - "commands/mjoin": "commands/list.join", + "commands/list.case": "commands/list.case", "commands/lockfile": "commands/lockfile", "commands/man-get-flags": "commands/man-get-flags", "commands/man-summary": "commands/man-summary", @@ -760,6 +764,8 @@ func init() { "commands/list.string": "commands/match", "commands/!list.string": "commands/match", "commands/method": "commands/method", + "commands/mjoin": "commands/mjoin", + "commands/list.join": "commands/mjoin", "commands/msort": "commands/msort", "commands/list.sort": "commands/msort", "commands/mtac": "commands/mtac", diff --git a/docs/commands/2darray.md b/docs/commands/2darray.md index 151ecebbf..5f44880a1 100644 --- a/docs/commands/2darray.md +++ b/docs/commands/2darray.md @@ -9,7 +9,7 @@ ## Usage ``` -2darray { code-block } { code-block } -> +2darray { code-block } { code-block } ... -> ``` ## Examples @@ -91,6 +91,12 @@ `2darray` can have as many or as few code blocks as you wish. +## Synonyms + +* `2darray` +* `struct.2darray` + + ## See Also * [`[ ..Range ]`](../parser/range.md): diff --git a/docs/commands/README.md b/docs/commands/README.md index 5c43ba20c..feadaaebc 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -160,8 +160,8 @@ murex-docs trypipe Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`list.join` ](../commands/list.join.md): - Joins a list or array into a single string +* [`list.case` ](../commands/list.case.md): + Changes the character case of a string or all elements in an array * [`lockfile`](../commands/lockfile.md): Create and manage lock files * [`man-get-flags` ](../commands/man-get-flags.md): @@ -174,6 +174,8 @@ murex-docs trypipe Match an exact value in an array * [`method`](../commands/method.md): Define a methods supported data-types +* [`mjoin` ](../commands/mjoin.md): + Joins a list or array into a single string * [`msort`](../commands/msort.md): Sorts an array - data type agnostic * [`mtac`](../commands/mtac.md): diff --git a/docs/commands/list.case.md b/docs/commands/list.case.md new file mode 100644 index 000000000..660633c6b --- /dev/null +++ b/docs/commands/list.case.md @@ -0,0 +1,59 @@ +# `list.case` + +> Changes the character case of a string or all elements in an array + +## Description + +`list.case` will read an array from either stdin or it's command line +parameters, and change that list to be upper or lower case. + +## Usage + +``` + -> list.case operation -> + list.case operation item1 [ item2 item3 ... ] -> +``` + +## Examples + +### As a method + +``` +» %[Monday..Friday] -> list.case upper +[ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY" +] +``` + +### As a function + +``` +» list.case lower @{ %[Monday..Friday] } +[ + "monday", + "tuesday", + "wednesday", + "thursday", + "friday" +] +``` + +## Synonyms + +* `list.case` + + +## See Also + +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays +* [`@Array` Sigil](../parser/array.md): + Expand values as an array + +
+ +This document was generated from [builtins/core/lists/case_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/lists/case_doc.yaml). \ No newline at end of file diff --git a/docs/commands/list.join.md b/docs/commands/mjoin.md similarity index 80% rename from docs/commands/list.join.md rename to docs/commands/mjoin.md index db32895de..98a6b6536 100644 --- a/docs/commands/list.join.md +++ b/docs/commands/mjoin.md @@ -1,4 +1,4 @@ -# `list.join` +# `mjoin` > Joins a list or array into a single string @@ -13,8 +13,8 @@ parameter. ## Usage ``` - -> list.join separator -> - list.join separator item1 item2 item3... -> + -> mjoin separator -> + mjoin separator item1 [ item2 item3 ... ] -> ``` ## Examples @@ -22,21 +22,21 @@ parameter. ### As a method ``` -» %[Monday..Friday] -> list.join ! +» %[Monday..Friday] -> mjoin ! Monday!Tuesday!Wednesday!Thursday!Friday ``` ### As a function ``` -» list.join ! @{ %[Monday..Friday] } +» mjoin ! @{ %[Monday..Friday] } Monday!Tuesday!Wednesday!Thursday!Friday ``` ## Synonyms -* `list.join` * `mjoin` +* `list.join` ## See Also diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index ea1b0f491..c6d703984 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -269,8 +269,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`list.join` ](../commands/list.join.md): - Joins a list or array into a single string +* [`list.case` ](../commands/list.case.md): + Changes the character case of a string or all elements in an array * [`lockfile`](../commands/lockfile.md): Create and manage lock files * [`man-get-flags` ](../commands/man-get-flags.md): @@ -283,6 +283,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Match an exact value in an array * [`method`](../commands/method.md): Define a methods supported data-types +* [`mjoin` ](../commands/mjoin.md): + Joins a list or array into a single string * [`msort`](../commands/msort.md): Sorts an array - data type agnostic * [`mtac`](../commands/mtac.md): From 4922e76dece26314fcb4cf6a0dafc699f5d742bc Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 20 Aug 2024 18:47:24 +0300 Subject: [PATCH 047/142] ci: remove codeql (it sucks) --- .github/workflows/codeql.yml | 94 ------------------------------------ compatibility.md | 2 +- docs/changelog/v4.1.md | 2 +- docs/changelog/v4.3.md | 2 +- 4 files changed, 3 insertions(+), 97 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 01a3a87bd..000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,94 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - paths: - - "**/*.go" - schedule: - - cron: '30 23 * * 6' - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: go - build-mode: autobuild - - language: javascript-typescript - build-mode: none - # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}" diff --git a/compatibility.md b/compatibility.md index 1ec5685b6..167708654 100644 --- a/compatibility.md +++ b/compatibility.md @@ -91,4 +91,4 @@ Murex releases roughly follows [semantic versioning](https://semver.org/).
-This document was generated from [gen/root/compatibility_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/root/compatibility_doc.yaml). +This document was generated from [gen/root/compatibility_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/root/compatibility_doc.yaml). \ No newline at end of file diff --git a/docs/changelog/v4.1.md b/docs/changelog/v4.1.md index 677bb89a0..f107089a7 100644 --- a/docs/changelog/v4.1.md +++ b/docs/changelog/v4.1.md @@ -158,4 +158,4 @@ Published: 04.06.2023 at 10:44
-This document was generated from [gen/changelog/v4.1_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.1_doc.yaml). +This document was generated from [gen/changelog/v4.1_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.1_doc.yaml). \ No newline at end of file diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index 7f0ffb7b0..7d0c77767 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -39,4 +39,4 @@ Published: 02.07.2023 at 09:55
-This document was generated from [gen/changelog/v4.3_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.3_doc.yaml). +This document was generated from [gen/changelog/v4.3_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v4.3_doc.yaml). \ No newline at end of file From 6fac5234057639e32676edc3b003d51795da617d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 24 Aug 2024 18:01:21 +0100 Subject: [PATCH 048/142] rewrite of system forking --- app/app.go | 6 +- app/whatsnew/whatsnew.go | 5 +- builtins/core/processes/bgfg_unix.go | 10 +- lang/exec.go | 73 ++++++---- lang/exec_js.go | 23 ++-- lang/exec_plan9.go | 23 ++-- lang/exec_test.go | 15 ++- lang/exec_unix.go | 195 +++++++++++++++++++++++++-- lang/exec_windows.go | 25 ++-- lang/process.go | 10 +- lang/process/exec.go | 44 ------ lang/process/exec_test.go | 29 ---- lang/process/sysproc.go | 11 ++ lang/process_structs.go | 13 +- lang/redirection.go | 7 +- shell/signals.go | 19 ++- shell/signals_unix.go | 34 +++-- utils/consts/temp.go | 2 +- utils/which/which.go | 14 ++ version.svg | 2 +- 20 files changed, 359 insertions(+), 201 deletions(-) delete mode 100644 lang/process/exec.go delete mode 100644 lang/process/exec_test.go create mode 100644 lang/process/sysproc.go diff --git a/app/app.go b/app/app.go index 898b85650..9091daa33 100644 --- a/app/app.go +++ b/app/app.go @@ -12,10 +12,10 @@ const Name = "murex" // Version number of $SHELL // Format of version string should be "(major).(minor).(revision) DESCRIPTION" const ( - version = "%d.%d.%d" + version = "%d.%d.%04d JC863" Major = 6 - Minor = 2 - Revision = 4000 + Minor = 3 + Revision = 330 ) // Copyright is the copyright owner string diff --git a/app/whatsnew/whatsnew.go b/app/whatsnew/whatsnew.go index 74d0225bd..5f78fe4b3 100644 --- a/app/whatsnew/whatsnew.go +++ b/app/whatsnew/whatsnew.go @@ -34,8 +34,9 @@ func Display() { } changelog: - fmt.Fprintf(os.Stdout, "Welcome to murex %d.%d.%d\nChangelog: https://murex.rocks/changelog/\nOr run `help changelog/v%d.%d` from the command line\n", - app.Major, app.Minor, app.Revision, app.Major, app.Minor) + fmt.Fprintf(os.Stdout, "Welcome to murex %s\nChangelog: https://murex.rocks/changelog/\nOr run `help changelog/v%d.%d` from the command line\n", + app.Version(), + app.Major, app.Minor) f, err = os.OpenFile(profile.ModulePath()+"/version", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) if err != nil { diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index e2bd042a3..2c39e7cd0 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -27,9 +27,8 @@ func mkbg(p *lang.Process) error { return errors.New("FID is not a stopped process. Run `jobs` or `fid-list` to see a list of stopped processes") } - pid, cmd := f.Exec.Get() - if pid > 0 && cmd != nil { - err = cmd.Process.Signal(syscall.SIGCONT) + if p.SystemProcess != nil { + err = p.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err } @@ -59,9 +58,8 @@ func cmdForeground(p *lang.Process) error { lang.HidePrompt <- true - pid, cmd := f.Exec.Get() - if pid > 0 && cmd != nil { - err = cmd.Process.Signal(syscall.SIGCONT) + if p.SystemProcess != nil { + err = p.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err } diff --git a/lang/exec.go b/lang/exec.go index 2519ab2d6..7dd2ec5bf 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -29,33 +29,48 @@ var ( //termOut = reflect.TypeOf(new(term.Out)).String() ) +func forceTTY(p *Process) bool { + v, err := p.Config.Get("proc", "force-tty", types.Boolean) + if err != nil { + return false + } + return v.(bool) +} + // External executes an external process. func External(p *Process) error { - if err := execute(p); err != nil { - _, cmd := p.Exec.Get() - if cmd != nil { - p.ExitNum = cmd.ProcessState.ExitCode() + err := execute(p) + if err != nil { + if p.SystemProcess != nil { + p.ExitNum = p.SystemProcess.ExitNum() } else { p.ExitNum = 1 } return err - } + return nil } func execute(p *Process) error { - exeName, parameters, err := getCmdTokens(p) - if err != nil { - return err + argv := osExecGetArgv(p) + if len(argv) == 0 { + return fmt.Errorf("no parameters specified for `exec`\nExpecting a name of command to run") + } + + if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() && forceTTY(p) { + return osExecFork(p, argv) } - cmd := exec.Command(exeName, parameters...) + + return execForkFallback(p, argv) +} + +func execForkFallback(p *Process, argv []string) error { + cmd := exec.Command(argv[0], argv[1:]...) if p.HasCancelled() { return nil } - - //ctxCancel := p.Kill p.Kill = func() { if !debug.Enabled { defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway @@ -69,7 +84,7 @@ func execute(p *Process) error { } name, _ := p.Args() os.Stderr.WriteString( - fmt.Sprintf("\nError sending SIGTERM to `%s`: %s\n", name, err.Error())) + fmt.Sprintf("\n!!! Error sending SIGTERM to `%s`: %s\n", name, err.Error())) } } @@ -93,18 +108,18 @@ func execute(p *Process) error { cmd.Env = append(os.Environ(), envMurexPid, envMethodFalse, envBackgroundFalse, envDataType+p.Stdin.GetDataType()) } - if len(p.Exec.Env) > 0 { - for i := range p.Exec.Env { - if !strings.Contains(p.Exec.Env[i], "=") { - v, err := p.Variables.GetString(p.Exec.Env[i]) + /*if len(p.Envs) > 0 { + for i := range p.Envs { + if !strings.Contains(p.Envs[i], "=") { + v, err := p.Variables.GetString(p.Envs[i]) if err != nil { continue } - p.Exec.Env[i] += "=" + v + p.Envs[i] += "=" + v } } - cmd.Env = append(cmd.Env, p.Exec.Env...) - } + cmd.Env = append(cmd.Env, p.Envs...) + }*/ // *** // Define STANDARD OUT (fd 1) @@ -118,7 +133,9 @@ func execute(p *Process) error { // osSyscalls(cmd, int(p.ttyout.Fd())) // cmd.Stdout = p.ttyout //} else { - osSyscalls(cmd, int(p.Stdout.File().Fd())) + + cmd.SysProcAttr = osSysProcAttr(int(p.Stdout.File().Fd())) + cmd.Stdout = p.Stdout.File() //} } else { @@ -200,7 +217,7 @@ func execute(p *Process) error { ///////// - p.Exec.Set(cmd.Process.Pid, cmd) + p.SystemProcess = &sysProcT{cmd} /*if err := mxdtW.Close(); err != nil { tty.Stderr.WriteString("error closing murex data type output file write pipe:" + err.Error() + "\n") @@ -217,10 +234,10 @@ func execute(p *Process) error { return nil } -func forceTTY(p *Process) bool { - v, err := p.Config.Get("proc", "force-tty", types.Boolean) - if err != nil { - return false - } - return v.(bool) -} +type sysProcT struct{ cmd *exec.Cmd } + +func (sp *sysProcT) Pid() int { return sp.cmd.Process.Pid } +func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.ExitCode() } +func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } +func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } +func (sp *sysProcT) UnixT() bool { return false } diff --git a/lang/exec_js.go b/lang/exec_js.go index 731ddb19e..55a9af1bc 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -4,20 +4,21 @@ package lang import ( - "os/exec" -) + "syscall" -func getCmdTokens(p *Process) (exe string, parameters []string, err error) { - exe, err = p.Parameters.String(0) - if err != nil { - return - } + "github.com/lmorg/murex/utils/which" +) - parameters = p.Parameters.StringArray()[1:] +func osExecGetArgv(p *Process) []string { + argv := p.Parameters.StringArray() + argv[0] = which.WhichIgnoreFail(argv[0]) + return argv +} - return +func osExecFork(p *Process, argv []string) error { + return execForkFallback(p, argv) } -func osSyscalls(_ *exec.Cmd, _ int) { - return +func osSysProcAttr(_ int) *syscall.SysProcAttr { + return nil } diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index ae5c7f1b6..a1864f52a 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -4,20 +4,21 @@ package lang import ( - "os/exec" -) + "syscall" -func getCmdTokens(p *Process) (exe string, parameters []string, err error) { - exe, err = p.Parameters.String(0) - if err != nil { - return - } + "github.com/lmorg/murex/utils/which" +) - parameters = p.Parameters.StringArray()[1:] +func osExecGetArgv(p *Process) []string { + argv := p.Parameters.StringArray() + argv[0] = which.WhichIgnoreFail(argv[0]) + return argv +} - return +func osExecFork(p *Process, argv []string) error { + return execForkFallback(p, argv) } -func osSyscalls(_ *exec.Cmd, _ int) { - return +func osSysProcAttr(_ int) *syscall.SysProcAttr { + return nil } diff --git a/lang/exec_test.go b/lang/exec_test.go index e51381af0..ffa95a179 100644 --- a/lang/exec_test.go +++ b/lang/exec_test.go @@ -1,3 +1,6 @@ +//go:build !windows && !plan9 && !js +// +build !windows,!plan9,!js + package lang_test import ( @@ -30,11 +33,13 @@ func TestProcessExecStruct(t *testing.T) { return } - pid, cmd := lang.ForegroundProc.Get().Exec.Get() - if pid == 0 { - t.Errorf("Expecting a non-zero pid, instead found %d", pid) + if p.SystemProcess == nil { + t.Errorf("Expecting a non-nil p.SystemProcess") + return } - if cmd == nil { - t.Errorf("Expecting a non-nil cmd, instead got %v", cmd) + + pid := p.SystemProcess.Pid() + if p.SystemProcess.Pid() == 0 { + t.Errorf("Expecting a non-zero pid, instead found %d", pid) } } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index d8cf39abb..6fd1e8060 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -4,26 +4,199 @@ package lang import ( - "os/exec" + "fmt" + "os" + "strings" "syscall" + + "github.com/lmorg/murex/debug" + "github.com/lmorg/murex/lang/state" + "github.com/lmorg/murex/utils/json" + "github.com/lmorg/murex/utils/which" ) -func getCmdTokens(p *Process) (exe string, parameters []string, err error) { - exe, err = p.Parameters.String(0) +func osExecGetArgv(p *Process) []string { + argv := p.Parameters.StringArray() + argv[0] = which.WhichIgnoreFail(argv[0]) + return argv +} + +func osExecFork(p *Process, argv []string) error { + if p.HasCancelled() { + return nil + } + p.Kill = func() { + if !debug.Enabled { + defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway + } + + //ctxCancel() + err := p.SystemProcess.Signal(syscall.SIGTERM) + if err != nil { + if err.Error() == os.ErrProcessDone.Error() { + return + } + name, _ := p.Args() + os.Stderr.WriteString( + fmt.Sprintf("\n!!! Error sending SIGTERM to `%s`: %s\n", name, err.Error())) + } + } + + pwd, _ := os.Getwd() + p.State.Set(state.Executing) + /*pid, err := syscall.ForkExec(argv[0], argv, &syscall.ProcAttr{ + Dir: pwd, + Files: []uintptr{stdinFd(p), stdoutFd(p), stderrFd(p)}, + //Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, + Env: p.Envs, + Sys: &syscall.SysProcAttr{ + //Setsid: true, // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + Setpgid: true, + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. + //Setctty: true, + //Noctty: true, // Detach fd 0 from controlling terminal + Ctty: int(os.Stdin.Fd()), // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. + }, + }) + + if err != nil { + return fmt.Errorf("failed syscall in osExecFork(): %s\nargv: %s", + err.Error(), + json.LazyLogging(argv), + ) + }*/ + + unixProcess, err := os.StartProcess(argv[0], argv, &os.ProcAttr{ + Dir: pwd, + Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, + Env: p.Envs, + Sys: &syscall.SysProcAttr{ + //Setsid: true, // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + Setpgid: true, + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. + Setctty: true, + //Noctty: true, // Detach fd 0 from controlling terminal + Ctty: int(os.Stdin.Fd()), // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + //Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. + }, + }) + if err != nil { - return + return fmt.Errorf("failed os.StartProcess in osExecFork()...\n%s\nargv: %s", + err.Error(), + json.LazyLogging(argv), + ) } - parameters = p.Parameters.StringArray()[1:] + sysProc := sysProcUnixT{ + p: unixProcess, + } + + p.SystemProcess = &sysProc + + sysProc.state, err = sysProc.p.Wait() - return + if err != nil { + if !strings.HasPrefix(err.Error(), "signal:") { + return err + } + } + + return nil } -func osSyscalls(cmd *exec.Cmd, fd int) { - cmd.SysProcAttr = &syscall.SysProcAttr{ - Ctty: fd, - //Noctty: false, +func osSysProcAttr(fd int) *syscall.SysProcAttr { + return &syscall.SysProcAttr{ + //Setsid: true, // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + //Setpgid: true, + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. //Setctty: true, - //Setsid: true, + //Noctty: true, // Detach fd 0 from controlling terminal + Ctty: fd, // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + //Foreground: true, + //Pgid: 0, // Child's process group ID if Setpgid. + } +} + +func stdinFd(_ *Process) uintptr { + return os.Stdin.Fd() +} + +func stdoutFd(p *Process) uintptr { + f := p.Stdout.File() + if f != nil { + return f.Fd() } + + //path := fmt.Sprintf("%s%d.1") + panic("not implemented file creation") +} + +func stderrFd(p *Process) uintptr { + f := p.Stderr.File() + if f != nil { + return f.Fd() + } + + //path := fmt.Sprintf("%s%d.2") + panic("not implemented file creation") +} + +type sysProcUnixT struct { + p *os.Process + state *os.ProcessState +} + +func (sp *sysProcUnixT) Pid() int { + panic("bob00") + return sp.p.Pid +} +func (sp *sysProcUnixT) ExitNum() int { + panic("bob01") + return sp.state.ExitCode() +} +func (sp *sysProcUnixT) Kill() error { + panic("bob02") + return sp.p.Kill() +} +func (sp *sysProcUnixT) Signal(sig os.Signal) error { + panic("bob03") + return sp.p.Signal(sig) +} + +func (sp *sysProcUnixT) UnixT() bool { + return true } diff --git a/lang/exec_windows.go b/lang/exec_windows.go index 7a428ed15..197cdc76b 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -3,20 +3,23 @@ package lang -import "os/exec" +import ( + "syscall" -func getCmdTokens(p *Process) (exe string, parameters []string, err error) { - _, err = p.Parameters.String(0) - if err != nil { - return - } + "github.com/lmorg/murex/utils/which" +) - exe = "cmd" - parameters = append([]string{"/c"}, p.Parameters.StringArray()...) +func osExecGetArgv(p *Process) []string { + argv := []string{"cmd", "/c"} + argv = append(argv, p.Parameters.StringArray()...) + argv[2] = which.WhichIgnoreFail(argv[2]) + return argv +} - return +func osExecFork(p *Process, argv []string) error { + return execForkFallback(p, argv) } -func osSyscalls(_ *exec.Cmd, _ int) { - return +func osSysProcAttr(_ int) *syscall.SysProcAttr { + return nil } diff --git a/lang/process.go b/lang/process.go index 4f66bd954..1e27e006f 100644 --- a/lang/process.go +++ b/lang/process.go @@ -338,7 +338,8 @@ executeProcess: // shell execute p.Parameters.Prepend([]string{name}) p.Name.Set("exec") - // Don't here p.State.Set(state.Executing) - this should be done in `exec` builtin + // Don't put the following here: p.State.Set(state.Executing) + // That should be done in the `exec` builtin instead err = GoFunctions["exec"](p) if err != nil && strings.Contains(err.Error(), "executable file not found") { _, cpErr := ParseExpression(p.raw, 0, false) @@ -355,7 +356,6 @@ executeProcess: } cleanUpProcess: - //debug.Json("Execute process (cleanUpProcess)", p) if err != nil { p.Stderr.Writeln(writeError(p, err)) @@ -380,19 +380,19 @@ cleanUpProcess: if len(p.NamedPipeOut) > 7 /* tmp:$FID/$MD5 */ && p.NamedPipeOut[:4] == "tmp:" { out, err := GlobalPipes.Get(p.NamedPipeOut) if err != nil { - p.Stderr.Writeln([]byte(fmt.Sprintf("Error connecting to temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) + p.Stderr.Writeln([]byte(fmt.Sprintf("!!! Error connecting to temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) } else { p.stdoutOldPtr.Open() _, err = out.WriteTo(p.stdoutOldPtr) p.stdoutOldPtr.Close() if err != nil && err != io.EOF { - p.Stderr.Writeln([]byte(fmt.Sprintf("Error piping from temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) + p.Stderr.Writeln([]byte(fmt.Sprintf("!!! Error piping from temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) } } err = GlobalPipes.Close(p.NamedPipeOut) if err != nil { - p.Stderr.Writeln([]byte(fmt.Sprintf("Error closing temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) + p.Stderr.Writeln([]byte(fmt.Sprintf("!!! Error closing temporary named pipe '%s': %s", p.NamedPipeOut, err.Error()))) } } diff --git a/lang/process/exec.go b/lang/process/exec.go deleted file mode 100644 index 6792eb86f..000000000 --- a/lang/process/exec.go +++ /dev/null @@ -1,44 +0,0 @@ -package process - -import ( - "os/exec" - "sync" -) - -type ExecCallbackFunc func(int) - -type Exec struct { - mutex sync.RWMutex - pid int - cmd *exec.Cmd - Env []string - Callback ExecCallbackFunc `json:"-"` -} - -func (exec *Exec) Set(pid int, cmd *exec.Cmd) { - exec.mutex.Lock() - exec.pid = pid - exec.cmd = cmd - exec.mutex.Unlock() - - if exec.Callback != nil { - exec.Callback(pid) - } -} - -func (exec *Exec) Get() (int, *exec.Cmd) { - exec.mutex.RLock() - pid := exec.pid - cmd := exec.cmd - exec.mutex.RUnlock() - - return pid, cmd -} - -func (exec *Exec) Pid() int { - exec.mutex.RLock() - pid := exec.pid - exec.mutex.RUnlock() - - return pid -} diff --git a/lang/process/exec_test.go b/lang/process/exec_test.go deleted file mode 100644 index 8fa7e3e58..000000000 --- a/lang/process/exec_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package process_test - -import ( - "os/exec" - "testing" - - "github.com/lmorg/murex/lang/process" - "github.com/lmorg/murex/test/count" -) - -func TestExec(t *testing.T) { - count.Tests(t, 4) - - e := new(process.Exec) - - e.Set(13, new(exec.Cmd)) - - pid, cmd := e.Get() - if pid != 13 { - t.Errorf("Set and/or Get failed. Didn't return 13") - } - if cmd == nil { - t.Errorf("Set and/or Get failed. Returned nil") - } - - if e.Pid() != 13 { - t.Errorf("Set and/or Pid failed. Didn't return 13") - } -} diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go new file mode 100644 index 000000000..cda8d7900 --- /dev/null +++ b/lang/process/sysproc.go @@ -0,0 +1,11 @@ +package process + +import "os" + +type SystemProcess interface { + Signal(sig os.Signal) error + Kill() error + Pid() int + ExitNum() int + UnixT() bool +} diff --git a/lang/process_structs.go b/lang/process_structs.go index 310e2240d..69ffdc438 100644 --- a/lang/process_structs.go +++ b/lang/process_structs.go @@ -39,7 +39,8 @@ type Process struct { HasStopped chan bool `json:"-"` Done func() `json:"-"` Kill func() `json:"-"` - Exec process.Exec + SystemProcess process.SystemProcess + Envs []string Scope *Process `json:"-"` Parent *Process `json:"-"` Previous *Process `json:"-"` @@ -87,7 +88,7 @@ func (p *Process) Dump() map[string]any { "IsFork": p.IsFork, //"Done": p.Done, //"Kill": p.Kill, - "ExecPid": p.Exec.Pid(), + "SysProcId": _jsonfySysProc(p), "ScopeFid": p.Scope.Id, "ParentFid": p.Parent.Id, "PreviousFid": p.Previous.Id, @@ -121,6 +122,14 @@ func (p *Process) Dump() map[string]any { } } +func _jsonfySysProc(p *Process) any { + if p.SystemProcess == nil { + return nil + } + + return p.SystemProcess.Pid() +} + type statsT struct { Read uint64 Written uint64 diff --git a/lang/redirection.go b/lang/redirection.go index 0bb28ceaa..c90e994b1 100644 --- a/lang/redirection.go +++ b/lang/redirection.go @@ -33,7 +33,7 @@ func parseRedirection(p *Process) { } case len(name) > 4 && name[:4] == "env:": - p.Exec.Env = append(p.Exec.Env, name[4:]) + p.Envs = append(p.Envs, name[4:]) case len(name) > 4 && name[:4] == "fid:": varName := name[4:] @@ -45,7 +45,8 @@ func parseRedirection(p *Process) { } case len(name) > 4 && name[:4] == "pid:": - varName := name[4:] + panic("TODO") + /*varName := name[4:] p.Exec.Callback = func(pid int) { err := p.Variables.Set(p, varName, pid, types.Integer) if err != nil { @@ -53,7 +54,7 @@ func parseRedirection(p *Process) { fmt.Sprintf("Cannot write variable '%s': %s", varName, err.Error()), )) } - } + }*/ case name[0] == '!': if p.NamedPipeErr == "" { diff --git a/shell/signals.go b/shell/signals.go index 9f50a127c..475ce7436 100644 --- a/shell/signals.go +++ b/shell/signals.go @@ -41,9 +41,9 @@ func sigterm(interactive bool) { switch { case p == nil: - //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify forground process !!!")) + //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground process")) case p.Kill == nil: - //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify forground kill function !!!")) + //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground kill function")) default: p.Kill() } @@ -53,12 +53,12 @@ var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) func sigquit(interactive bool) { if !interactive { - os.Stderr.WriteString("Murex received SIGQUIT!" + utils.NewLineString) + os.Stderr.WriteString("!!! Murex received SIGQUIT!" + utils.NewLineString) lang.Exit(2) } //tty.Stderr.WriteString(PromptSIGQUIT) - os.Stderr.WriteString("Murex received SIGQUIT!" + utils.NewLineString) + os.Stderr.WriteString("!!! Murex received SIGQUIT!" + utils.NewLineString) fids := lang.GlobalFIDs.ListAll() for _, p := range fids { @@ -80,19 +80,18 @@ func sigquit(interactive bool) { p.Id, procName, procParam))) p.Kill() - i, cmd := p.Exec.Get() - if cmd != nil { - err := cmd.Process.Kill() + if p.SystemProcess != nil { + err := p.SystemProcess.Kill() if err != nil { lang.ShellProcess.Stderr.Writeln([]byte( fmt.Sprintf( - "!!! Error terminating FID %d (%d), `%s`: %s !!!", - p.Id, i, procName, err.Error()))) + "!!! Error terminating FID %d (%d), `%s`: %s", + p.Id, p.SystemProcess.Pid(), procName, err.Error()))) } } } } - lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt !!!")) + lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) lang.ShowPrompt <- true } diff --git a/shell/signals_unix.go b/shell/signals_unix.go index dcc061443..81ecbe381 100644 --- a/shell/signals_unix.go +++ b/shell/signals_unix.go @@ -5,7 +5,6 @@ package shell import ( "fmt" - "os" "os/signal" "syscall" @@ -25,19 +24,22 @@ func SignalHandler(interactive bool) { switch sig.String() { case syscall.SIGINT.String(): - sigint(interactive) + go sigint(interactive) case syscall.SIGTERM.String(): - sigterm(interactive) + go sigterm(interactive) case syscall.SIGQUIT.String(): - sigquit(interactive) + go sigquit(interactive) case syscall.SIGTSTP.String(): - sigtstp() + go sigtstp() + + case syscall.SIGCHLD.String(): + // TODO default: - os.Stderr.WriteString("Unhandled signal: " + sig.String()) + panic("unhandled signal: " + sig.String()) // this shouldn't ever happen } } }() @@ -46,12 +48,14 @@ func SignalHandler(interactive bool) { func signalRegister(interactive bool) { if interactive { // Interactive, so we will handle stop - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) + } else { // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) } } + func sigtstp() { p := lang.ForegroundProc.Get() //debug.Json("p =", p) @@ -65,10 +69,8 @@ func sigtstp() { stopStatus(p) } - _, cmd := p.Exec.Get() - if cmd != nil { - //err = cmd.Process.Signal(syscall.SIGTSTP) - err = cmd.Process.Signal(syscall.SIGSTOP) + if p.SystemProcess != nil { + err = p.SystemProcess.Signal(syscall.SIGSTOP) if err != nil { lang.ShellProcess.Stderr.Write([]byte(err.Error())) } @@ -80,10 +82,6 @@ func sigtstp() { } func stopStatus(p *lang.Process) { - //if p == nil { - // panic("stopStatus received nil p") - //} - var ( stdinR, stdinW uint64 stdoutR, stdoutW uint64 @@ -108,7 +106,7 @@ func stopStatus(p *lang.Process) { ) lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) - if p.Exec.Pid() != 0 { + if p.SystemProcess != nil { block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) if err != nil { lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) @@ -116,9 +114,9 @@ func stopStatus(p *lang.Process) { } fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN) - fork.Name.Set("(SIGTSTP)") + fork.Name.Set("(SIGSTOP)") fork.FileRef = fileRef - fork.Variables.Set(fork.Process, "PID", lang.ForegroundProc.Get().Exec.Pid(), types.Integer) + fork.Variables.Set(fork.Process, "PID", p.SystemProcess.Pid(), types.Integer) _, err = fork.Execute([]rune(block.(string))) if err != nil { diff --git a/utils/consts/temp.go b/utils/consts/temp.go index 8565039dc..000dab6c4 100644 --- a/utils/consts/temp.go +++ b/utils/consts/temp.go @@ -28,7 +28,7 @@ func createDirIfNotExist(dir string) { if _, err := os.Stat(dir); os.IsNotExist(err) { err = os.MkdirAll(dir, 0755) if err != nil { - _, err = os.Stderr.WriteString("WARNING: temp directory doesn't exist and unable to create it. This might cause problems.\nTemp directory: " + dir) + _, err = os.Stderr.WriteString("!!! WARNING: temp directory doesn't exist and unable to create it. This might cause problems.\nTemp directory: " + dir) if err != nil { panic("Unable to create tmp directories, unable to write to STDERR. Something is amiss") diff --git a/utils/which/which.go b/utils/which/which.go index e08658a3f..8ad36cc91 100644 --- a/utils/which/which.go +++ b/utils/which/which.go @@ -8,6 +8,11 @@ import ( // Which works similarly to the UNIX command with the same name func Which(cmd string) string { + _, err := os.Stat(cmd) + if !os.IsNotExist(err) { + return cmd + } + envPath := os.Getenv("PATH") for _, path := range SplitPath(envPath) { @@ -20,3 +25,12 @@ func Which(cmd string) string { return "" } + +func WhichIgnoreFail(cmd string) string { + path := Which(cmd) + if path == "" { + return cmd + } + + return path +} diff --git a/version.svg b/version.svg index 43019cc1a..5f0d00254 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.2.4000Version6.2.4000 +Version: 6.3.0330Version6.3.0330 From d3f42cef8d4481d8d875551fe5f83b9cf56c8de8 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 25 Aug 2024 11:00:39 +0100 Subject: [PATCH 049/142] bespoke UNIX code to manage foreground pids --- app/app.go | 2 +- lang/exec.go | 4 +- lang/exec_js.go | 8 --- lang/exec_plan9.go | 8 --- lang/exec_unix.go | 125 ++++++++++++++++++++-------------------- lang/exec_windows.go | 3 - lang/process/sysproc.go | 1 - shell/shell.go | 1 + shell/signals_unix.go | 4 ++ version.svg | 2 +- 10 files changed, 70 insertions(+), 88 deletions(-) diff --git a/app/app.go b/app/app.go index 9091daa33..ecd455146 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%04d JC863" Major = 6 Minor = 3 - Revision = 330 + Revision = 409 ) // Copyright is the copyright owner string diff --git a/lang/exec.go b/lang/exec.go index 7dd2ec5bf..7656495b1 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -12,6 +12,7 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/consts" + "github.com/lmorg/murex/utils/which" ) const ( @@ -66,7 +67,7 @@ func execute(p *Process) error { } func execForkFallback(p *Process, argv []string) error { - cmd := exec.Command(argv[0], argv[1:]...) + cmd := exec.Command(which.WhichIgnoreFail(argv[0]), argv[1:]...) if p.HasCancelled() { return nil @@ -240,4 +241,3 @@ func (sp *sysProcT) Pid() int { return sp.cmd.Process.Pid } func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.ExitCode() } func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } -func (sp *sysProcT) UnixT() bool { return false } diff --git a/lang/exec_js.go b/lang/exec_js.go index 55a9af1bc..7d4a9b1ed 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -5,16 +5,8 @@ package lang import ( "syscall" - - "github.com/lmorg/murex/utils/which" ) -func osExecGetArgv(p *Process) []string { - argv := p.Parameters.StringArray() - argv[0] = which.WhichIgnoreFail(argv[0]) - return argv -} - func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index a1864f52a..c7a7fd957 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -5,16 +5,8 @@ package lang import ( "syscall" - - "github.com/lmorg/murex/utils/which" ) -func osExecGetArgv(p *Process) []string { - argv := p.Parameters.StringArray() - argv[0] = which.WhichIgnoreFail(argv[0]) - return argv -} - func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 6fd1e8060..7936dda3f 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -6,6 +6,7 @@ package lang import ( "fmt" "os" + "os/signal" "strings" "syscall" @@ -13,14 +14,9 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/which" + "golang.org/x/sys/unix" ) -func osExecGetArgv(p *Process) []string { - argv := p.Parameters.StringArray() - argv[0] = which.WhichIgnoreFail(argv[0]) - return argv -} - func osExecFork(p *Process, argv []string) error { if p.HasCancelled() { return nil @@ -42,13 +38,12 @@ func osExecFork(p *Process, argv []string) error { } } - pwd, _ := os.Getwd() p.State.Set(state.Executing) - /*pid, err := syscall.ForkExec(argv[0], argv, &syscall.ProcAttr{ - Dir: pwd, - Files: []uintptr{stdinFd(p), stdoutFd(p), stderrFd(p)}, - //Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, - Env: p.Envs, + /*pid, err := syscall.ForkExec(which.WhichIgnoreFail(argv[0]), argv, &syscall.ProcAttr{ + //Dir: pwd, + //Files: []uintptr{stdinFd(p), stdoutFd(p), stderrFd(p)}, + Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, + Env: p.Envs, Sys: &syscall.SysProcAttr{ //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, @@ -66,8 +61,8 @@ func osExecFork(p *Process, argv []string) error { // the descriptor of the controlling TTY. // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. - Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. + //Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. }, }) @@ -76,12 +71,33 @@ func osExecFork(p *Process, argv []string) error { err.Error(), json.LazyLogging(argv), ) + } + + sysProc := sysProcUnixT{ + p: &os.Process{Pid: pid}, + } + + p.SystemProcess = &sysProc + + sysProc.state, err = sysProc.p.Wait() + + if err != nil { + if !strings.HasPrefix(err.Error(), "signal:") { + return err + } }*/ - unixProcess, err := os.StartProcess(argv[0], argv, &os.ProcAttr{ - Dir: pwd, - Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, - Env: p.Envs, + unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, &os.ProcAttr{ + //Dir: pwd, + Files: []*os.File{ + os.Stdin, + //os.Stdout, + //os.Stderr, + //p.Stdin.File(), + p.Stdout.File(), + p.Stderr.File(), + }, + Env: p.Envs, Sys: &syscall.SysProcAttr{ //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, @@ -91,9 +107,9 @@ func osExecFork(p *Process, argv []string) error { // file descriptor Ctty. Ctty must be a descriptor number // in the child process: an index into ProcAttr.Files. // This is only meaningful if Setsid is true. - Setctty: true, - //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: int(os.Stdin.Fd()), // Controlling TTY fd + //Setctty: true, + //Noctty: true, // Detach fd 0 from controlling terminal + //Ctty: int(os.Stdin.Fd()), // Controlling TTY fd // Foreground places the child process group in the foreground. // This implies Setpgid. The Ctty field must be set to // the descriptor of the controlling TTY. @@ -105,7 +121,7 @@ func osExecFork(p *Process, argv []string) error { }) if err != nil { - return fmt.Errorf("failed os.StartProcess in osExecFork()...\n%s\nargv: %s", + return fmt.Errorf("failed fork in os.StartProcess -> osExecFork()...\n%s\nargv: %s", err.Error(), json.LazyLogging(argv), ) @@ -117,7 +133,11 @@ func osExecFork(p *Process, argv []string) error { p.SystemProcess = &sysProc + signal.Ignore(syscall.SIGTTOU) //, syscall.SIGTTIN) + defer signal.Reset(syscall.SIGTTOU) //, syscall.SIGTTIN) + UnixPidToFg(sysProc.p.Pid) sysProc.state, err = sysProc.p.Wait() + UnixPidToFg(0) if err != nil { if !strings.HasPrefix(err.Error(), "signal:") { @@ -151,52 +171,29 @@ func osSysProcAttr(fd int) *syscall.SysProcAttr { } } -func stdinFd(_ *Process) uintptr { - return os.Stdin.Fd() -} - -func stdoutFd(p *Process) uintptr { - f := p.Stdout.File() - if f != nil { - return f.Fd() - } - - //path := fmt.Sprintf("%s%d.1") - panic("not implemented file creation") -} - -func stderrFd(p *Process) uintptr { - f := p.Stderr.File() - if f != nil { - return f.Fd() - } - - //path := fmt.Sprintf("%s%d.2") - panic("not implemented file creation") -} - type sysProcUnixT struct { p *os.Process state *os.ProcessState } -func (sp *sysProcUnixT) Pid() int { - panic("bob00") - return sp.p.Pid -} -func (sp *sysProcUnixT) ExitNum() int { - panic("bob01") - return sp.state.ExitCode() -} -func (sp *sysProcUnixT) Kill() error { - panic("bob02") - return sp.p.Kill() -} -func (sp *sysProcUnixT) Signal(sig os.Signal) error { - panic("bob03") - return sp.p.Signal(sig) -} +func (sp *sysProcUnixT) Pid() int { return sp.p.Pid } +func (sp *sysProcUnixT) ExitNum() int { return sp.state.ExitCode() } +func (sp *sysProcUnixT) Kill() error { return sp.p.Kill() } +func (sp *sysProcUnixT) Signal(sig os.Signal) error { return sp.p.Signal(sig) } -func (sp *sysProcUnixT) UnixT() bool { - return true +// UnixPidToFg brings a UNIX process to the foreground. +// If pid == 0 then UnixPidToFg will assume Murex Pid instead. +func UnixPidToFg(pid int) { + if pid == 0 { + pid = os.Getpid() + } + + err := unix.IoctlSetPointerInt(0, unix.TIOCSPGRP, pid) + if err != nil { + os.Stderr.WriteString( + fmt.Sprintf("!!! failed syscall in unix.IoctlSetPointerInt -> unixResetFg()...\n!!! %s\n", + err.Error(), + ), + ) + } } diff --git a/lang/exec_windows.go b/lang/exec_windows.go index 197cdc76b..98b83e89a 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -5,14 +5,11 @@ package lang import ( "syscall" - - "github.com/lmorg/murex/utils/which" ) func osExecGetArgv(p *Process) []string { argv := []string{"cmd", "/c"} argv = append(argv, p.Parameters.StringArray()...) - argv[2] = which.WhichIgnoreFail(argv[2]) return argv } diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index cda8d7900..ee11cf5a6 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -7,5 +7,4 @@ type SystemProcess interface { Kill() error Pid() int ExitNum() int - UnixT() bool } diff --git a/shell/shell.go b/shell/shell.go index 01f48c638..8a08b16dd 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -119,6 +119,7 @@ func showPrompt() { panic("shell.ShowPrompt() called before initialising prompt with shell.Start()") } + lang.UnixPidToFg(0) SignalHandler(true) v, err := lang.ShellProcess.Config.Get("shell", "max-suggestions", types.Integer) diff --git a/shell/signals_unix.go b/shell/signals_unix.go index 81ecbe381..7ea035355 100644 --- a/shell/signals_unix.go +++ b/shell/signals_unix.go @@ -57,6 +57,7 @@ func signalRegister(interactive bool) { } func sigtstp() { + panic("bob04") p := lang.ForegroundProc.Get() //debug.Json("p =", p) @@ -65,6 +66,8 @@ func sigtstp() { show = false } + panic("bob03") + if show.(bool) { stopStatus(p) } @@ -78,6 +81,7 @@ func sigtstp() { p.State.Set(state.Stopped) go func() { p.HasStopped <- true }() + lang.ShowPrompt <- true } diff --git a/version.svg b/version.svg index 5f0d00254..55a97f4ec 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0330Version6.3.0330 +Version: 6.3.0409Version6.3.0409 From dcec5748a062bea4e169e63ea692624a7bb36c30 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 25 Aug 2024 12:53:14 +0100 Subject: [PATCH 050/142] refactor signal handler --- app/app.go | 2 +- lang/exec_notwin.go | 8 +++ lang/exec_unix.go | 59 +++--------------- lang/process_test.go | 15 +++-- main.go | 19 +++++- main_test.go | 3 + shell/shell.go | 7 ++- .../sigfns/sigfns.go} | 33 +++------- shell/signal_handler/sigfns/sigfns_plan9.go | 4 ++ .../sigfns/sigfns_unix.go} | 51 ++-------------- shell/signal_handler/sigfns/sigfns_windows.go | 4 ++ shell/signal_handler/signals.go | 19 ++++++ shell/signal_handler/signals_js.go | 15 +++++ shell/{ => signal_handler}/signals_plan9.go | 21 ++++--- shell/signal_handler/signals_unix.go | 61 +++++++++++++++++++ shell/{ => signal_handler}/signals_windows.go | 24 +++++--- shell/signals_js.go | 11 ---- version.svg | 2 +- 18 files changed, 197 insertions(+), 161 deletions(-) create mode 100644 lang/exec_notwin.go rename shell/{signals.go => signal_handler/sigfns/sigfns.go} (68%) create mode 100644 shell/signal_handler/sigfns/sigfns_plan9.go rename shell/{signals_unix.go => signal_handler/sigfns/sigfns_unix.go} (66%) create mode 100644 shell/signal_handler/sigfns/sigfns_windows.go create mode 100644 shell/signal_handler/signals.go create mode 100644 shell/signal_handler/signals_js.go rename shell/{ => signal_handler}/signals_plan9.go (50%) create mode 100644 shell/signal_handler/signals_unix.go rename shell/{ => signal_handler}/signals_windows.go (50%) delete mode 100644 shell/signals_js.go diff --git a/app/app.go b/app/app.go index ecd455146..0856aa3c5 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%04d JC863" Major = 6 Minor = 3 - Revision = 409 + Revision = 416 ) // Copyright is the copyright owner string diff --git a/lang/exec_notwin.go b/lang/exec_notwin.go new file mode 100644 index 000000000..546c0d8a0 --- /dev/null +++ b/lang/exec_notwin.go @@ -0,0 +1,8 @@ +//go:build !windows +// +build !windows + +package lang + +func osExecGetArgv(p *Process) []string { + return p.Parameters.StringArray() +} diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 7936dda3f..5e2cf09bb 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -12,6 +12,7 @@ import ( "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/state" + signalhandler "github.com/lmorg/murex/shell/signal_handler" "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/which" "golang.org/x/sys/unix" @@ -39,53 +40,6 @@ func osExecFork(p *Process, argv []string) error { } p.State.Set(state.Executing) - /*pid, err := syscall.ForkExec(which.WhichIgnoreFail(argv[0]), argv, &syscall.ProcAttr{ - //Dir: pwd, - //Files: []uintptr{stdinFd(p), stdoutFd(p), stderrFd(p)}, - Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, - Env: p.Envs, - Sys: &syscall.SysProcAttr{ - //Setsid: true, // Create session. - // Setpgid sets the process group ID of the child to Pgid, - // or, if Pgid == 0, to the new child's process ID. - Setpgid: true, - // Setctty sets the controlling terminal of the child to - // file descriptor Ctty. Ctty must be a descriptor number - // in the child process: an index into ProcAttr.Files. - // This is only meaningful if Setsid is true. - //Setctty: true, - //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: int(os.Stdin.Fd()), // Controlling TTY fd - // Foreground places the child process group in the foreground. - // This implies Setpgid. The Ctty field must be set to - // the descriptor of the controlling TTY. - // Unlike Setctty, in this case Ctty must be a descriptor - // number in the parent process. - //Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. - }, - }) - - if err != nil { - return fmt.Errorf("failed syscall in osExecFork(): %s\nargv: %s", - err.Error(), - json.LazyLogging(argv), - ) - } - - sysProc := sysProcUnixT{ - p: &os.Process{Pid: pid}, - } - - p.SystemProcess = &sysProc - - sysProc.state, err = sysProc.p.Wait() - - if err != nil { - if !strings.HasPrefix(err.Error(), "signal:") { - return err - } - }*/ unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, &os.ProcAttr{ //Dir: pwd, @@ -109,14 +63,14 @@ func osExecFork(p *Process, argv []string) error { // This is only meaningful if Setsid is true. //Setctty: true, //Noctty: true, // Detach fd 0 from controlling terminal - //Ctty: int(os.Stdin.Fd()), // Controlling TTY fd + Ctty: int(os.Stdin.Fd()), // Controlling TTY fd // Foreground places the child process group in the foreground. // This implies Setpgid. The Ctty field must be set to // the descriptor of the controlling TTY. // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. - //Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. + Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. }, }) @@ -133,9 +87,10 @@ func osExecFork(p *Process, argv []string) error { p.SystemProcess = &sysProc - signal.Ignore(syscall.SIGTTOU) //, syscall.SIGTTIN) - defer signal.Reset(syscall.SIGTTOU) //, syscall.SIGTTIN) + signal.Ignore(syscall.SIGTTOU) + defer signal.Reset(syscall.SIGTTOU) UnixPidToFg(sysProc.p.Pid) + signalhandler.Register(Interactive) sysProc.state, err = sysProc.p.Wait() UnixPidToFg(0) diff --git a/lang/process_test.go b/lang/process_test.go index 3d546f0a1..d67878bb9 100644 --- a/lang/process_test.go +++ b/lang/process_test.go @@ -7,20 +7,25 @@ import ( "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" - "github.com/lmorg/murex/shell" "github.com/lmorg/murex/test" ) -/* Bug fix: +/* + Bug fix: + » function abc { config: set proc echo true ; out: testing; a: [1..3] } » abc panic: interface conversion: interface {} is string, not bool goroutine 922 [running]: github.com/lmorg/murex/lang.executeProcess(0xc0001082b0) - /Users/laurencemorgan/go/src/github.com/lmorg/murex/lang/process.go:196 +0x158d + + /Users/laurencemorgan/go/src/github.com/lmorg/murex/lang/process.go:196 +0x158d + created by github.com/lmorg/murex/lang.runModeNormal - /Users/laurencemorgan/go/src/github.com/lmorg/murex/lang/interpreter.go:180 +0x7e + + /Users/laurencemorgan/go/src/github.com/lmorg/murex/lang/interpreter.go:180 +0x7e + murex-dev» */ func TestBugFix(t *testing.T) { @@ -31,7 +36,7 @@ func TestBugFix(t *testing.T) { }) lang.InitEnv() defaults.Config(lang.ShellProcess.Config, false) - shell.SignalHandler(false) + signalhandler.EventLoop(false) tests := []test.MurexTest{ { diff --git a/main.go b/main.go index a6e77f8fb..4010e24c9 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,8 @@ import ( "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/shell" + signalhandler "github.com/lmorg/murex/shell/signal_handler" + "github.com/lmorg/murex/shell/signal_handler/sigfns" "github.com/lmorg/murex/utils/cache" "github.com/lmorg/murex/utils/readline" ) @@ -48,7 +50,7 @@ func runTests() error { lang.InitEnv() defaults.Config(lang.ShellProcess.Config, nonInteractive) - shell.SignalHandler(nonInteractive) + signalhandler.EventLoop(nonInteractive) // compiled profile defaultProfile() @@ -84,7 +86,7 @@ func runCommandLine(commandLine string) { // default config defaults.Config(lang.ShellProcess.Config, nonInteractive) - shell.SignalHandler(nonInteractive) + signalhandler.EventLoop(nonInteractive) // compiled profile defaultProfile() @@ -113,7 +115,7 @@ func runSource(filename string) { // default config defaults.Config(lang.ShellProcess.Config, nonInteractive) - shell.SignalHandler(nonInteractive) + signalhandler.EventLoop(nonInteractive) // compiled profile defaultProfile() @@ -162,3 +164,14 @@ func startMurex() { // start interactive shell shell.Start() } + +func registerSignalHandlers() { + signalhandler.Handlers = &signalhandler.SignalFunctionsT{ + Sigint: sigfns.Sigint, + Sigterm: sigfns.Sigterm, + Sigquit: sigfns.Sigquit, + Sigtstp: sigfns.Sigtstp, + Sigchld: sigfns.Sigchld, + } + signalhandler.EventLoop(nonInteractive) +} diff --git a/main_test.go b/main_test.go index 8c88009e8..566a8df6f 100644 --- a/main_test.go +++ b/main_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package main import ( diff --git a/shell/shell.go b/shell/shell.go index 8a08b16dd..c0aedf620 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -19,6 +19,7 @@ import ( "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/shell/autocomplete" "github.com/lmorg/murex/shell/history" + signalhandler "github.com/lmorg/murex/shell/signal_handler" "github.com/lmorg/murex/utils" "github.com/lmorg/murex/utils/ansi" "github.com/lmorg/murex/utils/ansititle" @@ -120,7 +121,7 @@ func showPrompt() { } lang.UnixPidToFg(0) - SignalHandler(true) + //signalhandler.Register(true) v, err := lang.ShellProcess.Config.Get("shell", "max-suggestions", types.Integer) if err != nil { @@ -158,7 +159,7 @@ func showPrompt() { ansititle.Tmux([]byte(app.Name)) } - signalRegister(true) + signalhandler.Register(true) setPromptHistory() Prompt.TabCompleter = tabCompletion @@ -190,7 +191,7 @@ func showPrompt() { case readline.ErrCtrlC: merged = "" nLines = 1 - fmt.Fprintln(os.Stdout, PromptSIGINT) + fmt.Fprintln(os.Stdout, signalhandler.PromptSIGINT) callEventsPrompt(promptops.Cancel, nil) continue diff --git a/shell/signals.go b/shell/signal_handler/sigfns/sigfns.go similarity index 68% rename from shell/signals.go rename to shell/signal_handler/sigfns/sigfns.go index 475ce7436..f337b1324 100644 --- a/shell/signals.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -1,4 +1,4 @@ -package shell +package sigfns import ( "fmt" @@ -9,29 +9,12 @@ import ( "github.com/lmorg/murex/utils" ) -var signalChan chan os.Signal = make(chan os.Signal, 1) - -const ( - // PromptSIGINT defines the string to write when ctrl+c is pressed - PromptSIGINT = "^C" - - // PromptSIGQUIT defines the string to write when ctrl+\ is pressed - PromptSIGQUIT = "^\\" - - // PromptEOF defines the string to write when ctrl+d is pressed - PromptEOF = "^D" -) - -func sigint(interactive bool) { +func Sigint(interactive bool) { //tty.Stderr.WriteString(PromptSIGINT) - sigterm(interactive) + Sigterm(interactive) } -/*func sigtstp() { - // see signals_unix.go -}*/ - -func sigterm(interactive bool) { +func Sigterm(interactive bool) { if !interactive { lang.Exit(0) } @@ -51,14 +34,14 @@ func sigterm(interactive bool) { var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) -func sigquit(interactive bool) { +func Sigquit(interactive bool) { if !interactive { - os.Stderr.WriteString("!!! Murex received SIGQUIT!" + utils.NewLineString) + os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) lang.Exit(2) } //tty.Stderr.WriteString(PromptSIGQUIT) - os.Stderr.WriteString("!!! Murex received SIGQUIT!" + utils.NewLineString) + os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) fids := lang.GlobalFIDs.ListAll() for _, p := range fids { @@ -76,7 +59,7 @@ func sigquit(interactive bool) { lang.ShellProcess.Stderr.Writeln([]byte( fmt.Sprintf( - "!!! Force closing FID %d: %s %s !!!", + "!!! Force closing FID %d: %s %s", p.Id, procName, procParam))) p.Kill() diff --git a/shell/signal_handler/sigfns/sigfns_plan9.go b/shell/signal_handler/sigfns/sigfns_plan9.go new file mode 100644 index 000000000..bb014d403 --- /dev/null +++ b/shell/signal_handler/sigfns/sigfns_plan9.go @@ -0,0 +1,4 @@ +//go:build plan9 +// +build plan9 + +package sigfns diff --git a/shell/signals_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go similarity index 66% rename from shell/signals_unix.go rename to shell/signal_handler/sigfns/sigfns_unix.go index 7ea035355..15f63d834 100644 --- a/shell/signals_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -1,11 +1,10 @@ //go:build !windows && !plan9 && !js // +build !windows,!plan9,!js -package shell +package sigfns import ( "fmt" - "os/signal" "syscall" "github.com/lmorg/murex/lang" @@ -14,49 +13,7 @@ import ( "github.com/lmorg/murex/utils/humannumbers" ) -// SignalHandler is an internal function to capture and handle OS signals (eg SIGTERM). -func SignalHandler(interactive bool) { - signalRegister(interactive) - - go func() { - for { - sig := <-signalChan - switch sig.String() { - - case syscall.SIGINT.String(): - go sigint(interactive) - - case syscall.SIGTERM.String(): - go sigterm(interactive) - - case syscall.SIGQUIT.String(): - go sigquit(interactive) - - case syscall.SIGTSTP.String(): - go sigtstp() - - case syscall.SIGCHLD.String(): - // TODO - - default: - panic("unhandled signal: " + sig.String()) // this shouldn't ever happen - } - } - }() -} - -func signalRegister(interactive bool) { - if interactive { - // Interactive, so we will handle stop - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) - - } else { - // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - } -} - -func sigtstp() { +func Sigtstp(_ bool) { panic("bob04") p := lang.ForegroundProc.Get() //debug.Json("p =", p) @@ -85,6 +42,10 @@ func sigtstp() { lang.ShowPrompt <- true } +func Sigchld(_ bool) { + // TODO +} + func stopStatus(p *lang.Process) { var ( stdinR, stdinW uint64 diff --git a/shell/signal_handler/sigfns/sigfns_windows.go b/shell/signal_handler/sigfns/sigfns_windows.go new file mode 100644 index 000000000..10b7a9713 --- /dev/null +++ b/shell/signal_handler/sigfns/sigfns_windows.go @@ -0,0 +1,4 @@ +//go:build windows +// +build windows + +package sigfns diff --git a/shell/signal_handler/signals.go b/shell/signal_handler/signals.go new file mode 100644 index 000000000..2f2792a37 --- /dev/null +++ b/shell/signal_handler/signals.go @@ -0,0 +1,19 @@ +package signalhandler + +import ( + "os" +) + +var signalChan chan os.Signal = make(chan os.Signal, 1) + +const ( + // PromptSIGINT defines the string to write when ctrl+c is pressed + PromptSIGINT = "^C" + + // PromptSIGQUIT defines the string to write when ctrl+\ is pressed + PromptSIGQUIT = "^\\" + + // PromptEOF defines the string to write when ctrl+d is pressed + PromptEOF = "^D" +) + diff --git a/shell/signal_handler/signals_js.go b/shell/signal_handler/signals_js.go new file mode 100644 index 000000000..d02a7de2b --- /dev/null +++ b/shell/signal_handler/signals_js.go @@ -0,0 +1,15 @@ +//go:build js +// +build js + +package signalhandler + +// EventLoop is an internal function to capture and handle OS signals. +// However since no signals will be sent via a webpage, this is just an empty +// function when compiled against js/wasm +func EventLoop(_ bool) {} + +func Register(_ bool) {} + +var Handlers *SignalFunctionsT + +type SignalFunctionsT struct{} diff --git a/shell/signals_plan9.go b/shell/signal_handler/signals_plan9.go similarity index 50% rename from shell/signals_plan9.go rename to shell/signal_handler/signals_plan9.go index 977dd05f3..9c48cdb95 100644 --- a/shell/signals_plan9.go +++ b/shell/signal_handler/signals_plan9.go @@ -1,7 +1,7 @@ //go:build plan9 // +build plan9 -package shell +package signalhandler import ( "os" @@ -9,9 +9,9 @@ import ( "syscall" ) -// SignalHandler is an internal function to capture and handle OS signals (eg SIGTERM). -func SignalHandler(interactive bool) { - signalRegister(interactive) +// EventLoop is an internal function to capture and handle OS signals (eg SIGTERM). +func EventLoop(interactive bool) { + Register(interactive) go func() { for { @@ -19,10 +19,10 @@ func SignalHandler(interactive bool) { switch sig.String() { case syscall.SIGINT.String(): - sigint(interactive) + Handlers.Sigint(interactive) case syscall.SIGTERM.String(): - sigterm(interactive) + Handlers.Sigterm(interactive) default: os.Stderr.WriteString("Unhandled signal: " + sig.String()) @@ -31,6 +31,13 @@ func SignalHandler(interactive bool) { }() } -func signalRegister(_ bool) { +func Register(_ bool) { signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM) } + +var Handlers *SignalFunctionsT + +type SignalFunctionsT struct { + Sigint func(bool) + Sigterm func(bool) +} diff --git a/shell/signal_handler/signals_unix.go b/shell/signal_handler/signals_unix.go new file mode 100644 index 000000000..a916a98d9 --- /dev/null +++ b/shell/signal_handler/signals_unix.go @@ -0,0 +1,61 @@ +//go:build !windows && !plan9 && !js +// +build !windows,!plan9,!js + +package signalhandler + +import ( + "os/signal" + "syscall" +) + +// EventLoop is an internal function to capture and handle OS signals (eg SIGTERM). +func EventLoop(interactive bool) { + Register(interactive) + + go func() { + for { + sig := <-signalChan + switch sig.String() { + + case syscall.SIGINT.String(): + go Handlers.Sigint(interactive) + + case syscall.SIGTERM.String(): + go Handlers.Sigterm(interactive) + + case syscall.SIGQUIT.String(): + go Handlers.Sigquit(interactive) + + case syscall.SIGTSTP.String(): + go Handlers.Sigtstp(interactive) + + case syscall.SIGCHLD.String(): + go Handlers.Sigchld(interactive) + + default: + panic("unhandled signal: " + sig.String()) // this shouldn't ever happen + } + } + }() +} + +func Register(interactive bool) { + if interactive { + // Interactive, so we will handle stop + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) + + } else { + // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + } +} + +var Handlers *SignalFunctionsT + +type SignalFunctionsT struct { + Sigint func(bool) + Sigterm func(bool) + Sigquit func(bool) + Sigtstp func(bool) + Sigchld func(bool) +} diff --git a/shell/signals_windows.go b/shell/signal_handler/signals_windows.go similarity index 50% rename from shell/signals_windows.go rename to shell/signal_handler/signals_windows.go index ba8a47452..be4e1d253 100644 --- a/shell/signals_windows.go +++ b/shell/signal_handler/signals_windows.go @@ -1,7 +1,7 @@ //go:build windows // +build windows -package shell +package signalhandler import ( "os" @@ -9,9 +9,9 @@ import ( "syscall" ) -// Handler is an internal function to capture and handle OS signals (eg SIGTERM). -func SignalHandler(interactive bool) { - signalRegister(interactive) +// EventLoop is an internal function to capture and handle OS signals (eg SIGTERM). +func EventLoop(interactive bool) { + Register(interactive) go func() { for { @@ -19,13 +19,13 @@ func SignalHandler(interactive bool) { switch sig.String() { case syscall.SIGINT.String(): - sigint(interactive) + Handlers.Sigint(interactive) case syscall.SIGTERM.String(): - sigterm(interactive) + Handlers.Sigterm(interactive) case syscall.SIGQUIT.String(): - sigquit(interactive) + Handlers.Sigquit(interactive) default: os.Stderr.WriteString("Unhandled signal: " + sig.String()) @@ -34,6 +34,14 @@ func SignalHandler(interactive bool) { }() } -func signalRegister(_ bool) { +func Register(_ bool) { signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) } + +var Handlers *SignalFunctionsT + +type SignalFunctionsT struct { + Sigint func(bool) + Sigterm func(bool) + Sigquit func(bool) +} diff --git a/shell/signals_js.go b/shell/signals_js.go deleted file mode 100644 index 2f5f35868..000000000 --- a/shell/signals_js.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build js -// +build js - -package shell - -// SignalHandler is an internal function to capture and handle OS signals. -// However since no signals will be sent via a webpage, this is just an empty -// function when compiled against js/wasm -func SignalHandler(_ bool) {} - -func signalRegister(_ bool) {} diff --git a/version.svg b/version.svg index 55a97f4ec..9a4828d5c 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0409Version6.3.0409 +Version: 6.3.0416Version6.3.0416 From 284d83cca412c863ac806c896fab1a832e395b87 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 25 Aug 2024 20:13:50 +0100 Subject: [PATCH 051/142] forcetty gid fix + helix integration --- app/app.go | 2 +- builtins/core/processes/bgfg_unix.go | 22 ++++---- integrations/helix-editor_posix.mx | 14 +++++ lang/exec.go | 10 +--- lang/exec_js.go | 2 + lang/exec_plan9.go | 2 + lang/exec_unix.go | 9 ++-- lang/exec_windows.go | 2 + lang/process/sysproc.go | 2 + lang/process_test.go | 1 - main.go | 11 ++-- shell/shell.go | 3 +- shell/signal_handler/sigfns/sigfns.go | 5 +- shell/signal_handler/sigfns/sigfns_unix.go | 59 +++++++++++++++------- shell/signal_handler/signals_unix.go | 2 +- version.svg | 2 +- 16 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 integrations/helix-editor_posix.mx diff --git a/app/app.go b/app/app.go index 0856aa3c5..fccd4903b 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%04d JC863" Major = 6 Minor = 3 - Revision = 416 + Revision = 445 ) // Copyright is the copyright owner string diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index 2c39e7cd0..ab61c7787 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -27,8 +27,8 @@ func mkbg(p *lang.Process) error { return errors.New("FID is not a stopped process. Run `jobs` or `fid-list` to see a list of stopped processes") } - if p.SystemProcess != nil { - err = p.SystemProcess.Signal(syscall.SIGCONT) + if f.SystemProcess != nil { + err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err } @@ -57,20 +57,22 @@ func cmdForeground(p *lang.Process) error { } lang.HidePrompt <- true + go unstop(f) + updateTree(f, false) + + lang.ForegroundProc.Set(f) + f.State.Set(state.Executing) - if p.SystemProcess != nil { - err = p.SystemProcess.Signal(syscall.SIGCONT) + if f.SystemProcess != nil { + if f.SystemProcess.ForcedTTY() { + lang.UnixPidToFg(f.SystemProcess.Pid()) + } + err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err } } - go unstop(f) - - updateTree(f, false) - lang.ForegroundProc.Set(f) - - f.State.Set(state.Executing) <-f.Context.Done() return nil } diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx new file mode 100644 index 000000000..4db90fb64 --- /dev/null +++ b/integrations/helix-editor_posix.mx @@ -0,0 +1,14 @@ +!if { which hx } then { + return +} + +summary hx "Helix: a post-modern text editor" + +function hx { + # Wrapper function for Helix editor to fix ^Z in job control + + config set proc strict-arrays false + config set proc force-tty true + + exec hx @PARAMS +} diff --git a/lang/exec.go b/lang/exec.go index 7656495b1..ef60a5ea8 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -128,15 +128,7 @@ func execForkFallback(p *Process, argv []string) error { if p.Stdout.IsTTY() { // If Stdout is a TTY then set the appropriate syscalls to allow the calling program to own the TTY.... - //osSyscalls(cmd, int(p.ttyout.Fd())) - //osSyscalls(cmd, int(os.Stdin.Fd())) - //if reflect.TypeOf(p.Stdout).String() == termOut { - // osSyscalls(cmd, int(p.ttyout.Fd())) - // cmd.Stdout = p.ttyout - //} else { - cmd.SysProcAttr = osSysProcAttr(int(p.Stdout.File().Fd())) - cmd.Stdout = p.Stdout.File() //} } else { @@ -241,3 +233,5 @@ func (sp *sysProcT) Pid() int { return sp.cmd.Process.Pid } func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.ExitCode() } func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } +func (sp *sysProcT) State() *os.ProcessState { return sp.cmd.ProcessState } +func (sp *sysProcT) ForcedTTY() bool { return false } diff --git a/lang/exec_js.go b/lang/exec_js.go index 7d4a9b1ed..e7403afa8 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -14,3 +14,5 @@ func osExecFork(p *Process, argv []string) error { func osSysProcAttr(_ int) *syscall.SysProcAttr { return nil } + +func UnixPidToFg(_ int) {} diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index c7a7fd957..93fc1c580 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -14,3 +14,5 @@ func osExecFork(p *Process, argv []string) error { func osSysProcAttr(_ int) *syscall.SysProcAttr { return nil } + +func UnixPidToFg(_ int) {} diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 5e2cf09bb..a81aaaaec 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -7,7 +7,6 @@ import ( "fmt" "os" "os/signal" - "strings" "syscall" "github.com/lmorg/murex/debug" @@ -95,9 +94,9 @@ func osExecFork(p *Process, argv []string) error { UnixPidToFg(0) if err != nil { - if !strings.HasPrefix(err.Error(), "signal:") { - return err - } + //if !strings.HasPrefix(err.Error(), "signal:") { + return err + //} } return nil @@ -135,6 +134,8 @@ func (sp *sysProcUnixT) Pid() int { return sp.p.Pid } func (sp *sysProcUnixT) ExitNum() int { return sp.state.ExitCode() } func (sp *sysProcUnixT) Kill() error { return sp.p.Kill() } func (sp *sysProcUnixT) Signal(sig os.Signal) error { return sp.p.Signal(sig) } +func (sp *sysProcUnixT) State() *os.ProcessState { return sp.state } +func (sp *sysProcUnixT) ForcedTTY() bool { return true } // UnixPidToFg brings a UNIX process to the foreground. // If pid == 0 then UnixPidToFg will assume Murex Pid instead. diff --git a/lang/exec_windows.go b/lang/exec_windows.go index 98b83e89a..fdcdde312 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -20,3 +20,5 @@ func osExecFork(p *Process, argv []string) error { func osSysProcAttr(_ int) *syscall.SysProcAttr { return nil } + +func UnixPidToFg(_ int) {} diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index ee11cf5a6..a0acc13ef 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -7,4 +7,6 @@ type SystemProcess interface { Kill() error Pid() int ExitNum() int + State() *os.ProcessState + ForcedTTY() bool } diff --git a/lang/process_test.go b/lang/process_test.go index d67878bb9..bf176e6a6 100644 --- a/lang/process_test.go +++ b/lang/process_test.go @@ -36,7 +36,6 @@ func TestBugFix(t *testing.T) { }) lang.InitEnv() defaults.Config(lang.ShellProcess.Config, false) - signalhandler.EventLoop(false) tests := []test.MurexTest{ { diff --git a/main.go b/main.go index 4010e24c9..452ee2a16 100644 --- a/main.go +++ b/main.go @@ -50,7 +50,7 @@ func runTests() error { lang.InitEnv() defaults.Config(lang.ShellProcess.Config, nonInteractive) - signalhandler.EventLoop(nonInteractive) + registerSignalHandlers(nonInteractive) // compiled profile defaultProfile() @@ -86,7 +86,7 @@ func runCommandLine(commandLine string) { // default config defaults.Config(lang.ShellProcess.Config, nonInteractive) - signalhandler.EventLoop(nonInteractive) + registerSignalHandlers(nonInteractive) // compiled profile defaultProfile() @@ -115,7 +115,7 @@ func runSource(filename string) { // default config defaults.Config(lang.ShellProcess.Config, nonInteractive) - signalhandler.EventLoop(nonInteractive) + registerSignalHandlers(nonInteractive) // compiled profile defaultProfile() @@ -162,10 +162,11 @@ func startMurex() { profile.Execute(profile.F_PRELOAD | profile.F_MODULES | profile.F_PROFILE) // start interactive shell + registerSignalHandlers(interactive) shell.Start() } -func registerSignalHandlers() { +func registerSignalHandlers(interactiveMode bool) { signalhandler.Handlers = &signalhandler.SignalFunctionsT{ Sigint: sigfns.Sigint, Sigterm: sigfns.Sigterm, @@ -173,5 +174,5 @@ func registerSignalHandlers() { Sigtstp: sigfns.Sigtstp, Sigchld: sigfns.Sigchld, } - signalhandler.EventLoop(nonInteractive) + signalhandler.EventLoop(interactiveMode) } diff --git a/shell/shell.go b/shell/shell.go index c0aedf620..f36b39c60 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -120,8 +120,7 @@ func showPrompt() { panic("shell.ShowPrompt() called before initialising prompt with shell.Start()") } - lang.UnixPidToFg(0) - //signalhandler.Register(true) + //lang.UnixPidToFg(0) v, err := lang.ShellProcess.Config.Get("shell", "max-suggestions", types.Integer) if err != nil { diff --git a/shell/signal_handler/sigfns/sigfns.go b/shell/signal_handler/sigfns/sigfns.go index f337b1324..6fa729bc4 100644 --- a/shell/signal_handler/sigfns/sigfns.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -10,7 +10,6 @@ import ( ) func Sigint(interactive bool) { - //tty.Stderr.WriteString(PromptSIGINT) Sigterm(interactive) } @@ -20,7 +19,6 @@ func Sigterm(interactive bool) { } p := lang.ForegroundProc.Get() - //p.Json("p =", p) switch { case p == nil: @@ -40,7 +38,6 @@ func Sigquit(interactive bool) { lang.Exit(2) } - //tty.Stderr.WriteString(PromptSIGQUIT) os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) fids := lang.GlobalFIDs.ListAll() @@ -75,6 +72,6 @@ func Sigquit(interactive bool) { } } - lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) + //lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) lang.ShowPrompt <- true } diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 15f63d834..42915f700 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -13,37 +13,60 @@ import ( "github.com/lmorg/murex/utils/humannumbers" ) -func Sigtstp(_ bool) { - panic("bob04") +func Sigtstp(interactive bool) { p := lang.ForegroundProc.Get() - //debug.Json("p =", p) + if p.SystemProcess != nil { + err := p.SystemProcess.Signal(syscall.SIGSTOP) + if err != nil { + lang.ShellProcess.Stderr.Write([]byte(err.Error())) + } + } + + if p.State.Get() != state.Stopped { + returnFromSigtstp(p) + } +} + +func returnFromSigtstp(p *lang.Process) { + p.State.Set(state.Stopped) + if p.SystemProcess != nil && p.SystemProcess.ForcedTTY() { + lang.UnixPidToFg(0) + } show, err := lang.ShellProcess.Config.Get("shell", "stop-status-enabled", types.Boolean) if err != nil { show = false } - panic("bob03") - if show.(bool) { stopStatus(p) } - if p.SystemProcess != nil { - err = p.SystemProcess.Signal(syscall.SIGSTOP) - if err != nil { - lang.ShellProcess.Stderr.Write([]byte(err.Error())) - } - } - p.State.Set(state.Stopped) go func() { p.HasStopped <- true }() lang.ShowPrompt <- true } -func Sigchld(_ bool) { - // TODO +func Sigchld(interactive bool) { + if !interactive { + return + } + + p := lang.ForegroundProc.Get() + if p.SystemProcess == nil { + return + } + + if !p.SystemProcess.ForcedTTY() { + return + } + + if p.SystemProcess.State() == nil || p.SystemProcess.State().Sys().(syscall.WaitStatus).Stopped() { + if p.State.Get() != state.Stopped { + returnFromSigtstp(p) + } + } } func stopStatus(p *lang.Process) { @@ -64,7 +87,7 @@ func stopStatus(p *lang.Process) { } pipeStatus := fmt.Sprintf( - "\nSTDIN: %s written / %s read\nSTDOUT: %s written / %s read\nSTDERR: %s written / %s read", + "\n!!! STDIN: %s written / %s read\n!!! STDOUT: %s written / %s read\n!!! STDERR: %s written / %s read", humannumbers.Bytes(stdinW), humannumbers.Bytes(stdinR), humannumbers.Bytes(stdoutW), humannumbers.Bytes(stdoutR), humannumbers.Bytes(stderrW), humannumbers.Bytes(stderrR), @@ -90,7 +113,9 @@ func stopStatus(p *lang.Process) { } lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( - "FID %d has been stopped.\nUse `fg %d` / `bg %d` to manage the FID or `jobs` to see a list of background and suspended functions", - p.Id, p.Id, p.Id, + "!!! FID %d has been stopped:\n!!! %s %s\n!!! Use `fg %d` / `bg %d` to manage the FID\n!!! ...or `jobs` to see a list of background and suspended functions", + p.Id, + p.Name.String(), p.Parameters.StringAll(), + p.Id, p.Id, ))) } diff --git a/shell/signal_handler/signals_unix.go b/shell/signal_handler/signals_unix.go index a916a98d9..98eaaf010 100644 --- a/shell/signal_handler/signals_unix.go +++ b/shell/signal_handler/signals_unix.go @@ -42,7 +42,7 @@ func EventLoop(interactive bool) { func Register(interactive bool) { if interactive { // Interactive, so we will handle stop - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) } else { // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us diff --git a/version.svg b/version.svg index 9a4828d5c..f5a924acb 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0416Version6.3.0416 +Version: 6.3.0445Version6.3.0445 From 753ceb1fe02eaeac6343deb79c976db2c3c4355d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 25 Aug 2024 23:33:55 +0100 Subject: [PATCH 052/142] pgid enabled by default for all system processes --- app/app.go | 2 +- builtins/core/processes/bgfg_unix.go | 4 +- integrations/helix-editor_posix.mx | 8 -- lang/exec.go | 18 ++- lang/exec_test.go | 2 +- lang/exec_unix.go | 55 ++++---- lang/fork.go | 2 + lang/init.go | 3 + lang/interpreter.go | 2 + lang/process/name_test.go | 11 ++ lang/process/sysproc.go | 41 +++++- lang/process/sysproc_test.go | 95 +++++++++++++ lang/process_structs.go | 4 +- shell/shell.go | 2 +- shell/signal_handler/functions/signals.go | 93 ++++++++++++ .../signal_handler/functions/signals_unix.go | 132 ++++++++++++++++++ shell/signal_handler/sigfns/sigfns.go | 2 +- shell/signal_handler/sigfns/sigfns_unix.go | 11 +- version.svg | 2 +- 19 files changed, 430 insertions(+), 59 deletions(-) create mode 100644 lang/process/sysproc_test.go create mode 100644 shell/signal_handler/functions/signals.go create mode 100644 shell/signal_handler/functions/signals_unix.go diff --git a/app/app.go b/app/app.go index fccd4903b..ac3b99f06 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%04d JC863" Major = 6 Minor = 3 - Revision = 445 + Revision = 466 ) // Copyright is the copyright owner string diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index ab61c7787..982832978 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -27,7 +27,7 @@ func mkbg(p *lang.Process) error { return errors.New("FID is not a stopped process. Run `jobs` or `fid-list` to see a list of stopped processes") } - if f.SystemProcess != nil { + if f.SystemProcess.Defined() { err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err @@ -63,7 +63,7 @@ func cmdForeground(p *lang.Process) error { lang.ForegroundProc.Set(f) f.State.Set(state.Executing) - if f.SystemProcess != nil { + if f.SystemProcess.Defined() { if f.SystemProcess.ForcedTTY() { lang.UnixPidToFg(f.SystemProcess.Pid()) } diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 4db90fb64..f301b8e80 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -4,11 +4,3 @@ summary hx "Helix: a post-modern text editor" -function hx { - # Wrapper function for Helix editor to fix ^Z in job control - - config set proc strict-arrays false - config set proc force-tty true - - exec hx @PARAMS -} diff --git a/lang/exec.go b/lang/exec.go index ef60a5ea8..9e297feee 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "os/exec" + "os/signal" "strings" "syscall" @@ -42,7 +43,7 @@ func forceTTY(p *Process) bool { func External(p *Process) error { err := execute(p) if err != nil { - if p.SystemProcess != nil { + if p.SystemProcess.Defined() { p.ExitNum = p.SystemProcess.ExitNum() } else { p.ExitNum = 1 @@ -77,7 +78,6 @@ func execForkFallback(p *Process, argv []string) error { defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway } - //ctxCancel() err := cmd.Process.Signal(syscall.SIGTERM) if err != nil { if err.Error() == os.ErrProcessDone.Error() { @@ -210,13 +210,21 @@ func execForkFallback(p *Process, argv []string) error { ///////// - p.SystemProcess = &sysProcT{cmd} + p.SystemProcess.Set(&sysProcT{cmd}) /*if err := mxdtW.Close(); err != nil { tty.Stderr.WriteString("error closing murex data type output file write pipe:" + err.Error() + "\n") }*/ - if err := cmd.Wait(); err != nil { + if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { + signal.Ignore(syscall.SIGTTOU) + defer signal.Reset(syscall.SIGTTOU) + UnixPidToFg(cmd.Process.Pid) + defer UnixPidToFg(0) + //signalhandler.Register(Interactive) + } + err := cmd.Wait() + if err != nil { if !strings.HasPrefix(err.Error(), "signal:") { //mxdtR.Close() return err @@ -234,4 +242,4 @@ func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.Exi func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } func (sp *sysProcT) State() *os.ProcessState { return sp.cmd.ProcessState } -func (sp *sysProcT) ForcedTTY() bool { return false } +func (sp *sysProcT) ForcedTTY() bool { return true } diff --git a/lang/exec_test.go b/lang/exec_test.go index ffa95a179..d50d2361f 100644 --- a/lang/exec_test.go +++ b/lang/exec_test.go @@ -33,7 +33,7 @@ func TestProcessExecStruct(t *testing.T) { return } - if p.SystemProcess == nil { + if !p.SystemProcess.Defined() { t.Errorf("Expecting a non-nil p.SystemProcess") return } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index a81aaaaec..87873e2b9 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -11,7 +11,6 @@ import ( "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/state" - signalhandler "github.com/lmorg/murex/shell/signal_handler" "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/which" "golang.org/x/sys/unix" @@ -26,7 +25,6 @@ func osExecFork(p *Process, argv []string) error { defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway } - //ctxCancel() err := p.SystemProcess.Signal(syscall.SIGTERM) if err != nil { if err.Error() == os.ErrProcessDone.Error() { @@ -83,13 +81,12 @@ func osExecFork(p *Process, argv []string) error { sysProc := sysProcUnixT{ p: unixProcess, } - - p.SystemProcess = &sysProc + p.SystemProcess.Set(&sysProc) signal.Ignore(syscall.SIGTTOU) defer signal.Reset(syscall.SIGTTOU) UnixPidToFg(sysProc.p.Pid) - signalhandler.Register(Interactive) + //signalhandler.Register(Interactive) sysProc.state, err = sysProc.p.Wait() UnixPidToFg(0) @@ -102,29 +99,6 @@ func osExecFork(p *Process, argv []string) error { return nil } -func osSysProcAttr(fd int) *syscall.SysProcAttr { - return &syscall.SysProcAttr{ - //Setsid: true, // Create session. - // Setpgid sets the process group ID of the child to Pgid, - // or, if Pgid == 0, to the new child's process ID. - //Setpgid: true, - // Setctty sets the controlling terminal of the child to - // file descriptor Ctty. Ctty must be a descriptor number - // in the child process: an index into ProcAttr.Files. - // This is only meaningful if Setsid is true. - //Setctty: true, - //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: fd, // Controlling TTY fd - // Foreground places the child process group in the foreground. - // This implies Setpgid. The Ctty field must be set to - // the descriptor of the controlling TTY. - // Unlike Setctty, in this case Ctty must be a descriptor - // number in the parent process. - //Foreground: true, - //Pgid: 0, // Child's process group ID if Setpgid. - } -} - type sysProcUnixT struct { p *os.Process state *os.ProcessState @@ -153,3 +127,28 @@ func UnixPidToFg(pid int) { ) } } + +///// + +func osSysProcAttr(fd int) *syscall.SysProcAttr { + return &syscall.SysProcAttr{ + //Setsid: true, // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + Setpgid: true, + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. + //Setctty: true, + //Noctty: true, // Detach fd 0 from controlling terminal + Ctty: fd, // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. + } +} diff --git a/lang/fork.go b/lang/fork.go index 922d99e48..c433e3f8a 100644 --- a/lang/fork.go +++ b/lang/fork.go @@ -9,6 +9,7 @@ import ( "github.com/lmorg/murex/builtins/pipes/streams" "github.com/lmorg/murex/builtins/pipes/term" "github.com/lmorg/murex/debug" + "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/runmode" "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" @@ -97,6 +98,7 @@ const ForkSuffix = " (fork)" func (p *Process) Fork(flags int) *Fork { fork := new(Fork) fork.Process = new(Process) + fork.SystemProcess = process.NewSystemProcessStruct() fork.SetTerminatedState(true) fork.Forks = p.Forks trace(fork.Process) diff --git a/lang/init.go b/lang/init.go index 22626a274..ff20ab24d 100644 --- a/lang/init.go +++ b/lang/init.go @@ -10,6 +10,7 @@ import ( "github.com/lmorg/murex/builtins/pipes/null" "github.com/lmorg/murex/builtins/pipes/term" "github.com/lmorg/murex/config" + "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/lang/runmode" "github.com/lmorg/murex/lang/state" @@ -59,6 +60,7 @@ func InitEnv() { ShellProcess.Done = func() { /* we don't want to accidentally terminate the shell process */ } ShellProcess.Kill = func() { /* we don't want to accidentally terminate the shell process */ } ShellProcess.Forks = NewForkManagement() + ShellProcess.SystemProcess = process.NewSystemProcessStruct() switch { case FlagTry: @@ -117,6 +119,7 @@ func NewTestProcess() (p *Process) { p.Next = ShellProcess p.Previous = ShellProcess p.Forks = NewForkManagement() + p.SystemProcess = process.NewSystemProcessStruct() GlobalFIDs.Register(p) diff --git a/lang/interpreter.go b/lang/interpreter.go index 1aa382360..68e15fee0 100644 --- a/lang/interpreter.go +++ b/lang/interpreter.go @@ -6,6 +6,7 @@ import ( "github.com/lmorg/murex/builtins/pipes/streams" "github.com/lmorg/murex/lang/expressions/functions" + "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/lang/runmode" "github.com/lmorg/murex/lang/state" @@ -108,6 +109,7 @@ func compile(tree *[]functions.FunctionT, parent *Process) (*[]Process, int) { procs[i].CCExists = parent.CCExists procs[i].FileRef = &ref.File{Source: parent.FileRef.Source} procs[i].Forks = NewForkManagement() + procs[i].SystemProcess = process.NewSystemProcessStruct() procs[i].FileRef.Column = parent.FileRef.Column + (*tree)[i].ColumnN procs[i].FileRef.Line = (*tree)[i].LineN diff --git a/lang/process/name_test.go b/lang/process/name_test.go index 0a574d116..72909b599 100644 --- a/lang/process/name_test.go +++ b/lang/process/name_test.go @@ -22,3 +22,14 @@ func TestName(t *testing.T) { t.Errorf("Set and/or String failed. Didn't return 'foobar'") } } + +func TestNameSetRune(t *testing.T) { + count.Tests(t, 2) + + name := new(process.Name) + + name.SetRune([]rune{'f', 'o', 'o', 'b', 'a', 'r'}) + if name.String() != "foobar" { + t.Errorf("SetRune and/or String failed. Didn't return 'foobar'") + } +} diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index a0acc13ef..f52f980e7 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -1,8 +1,11 @@ package process -import "os" +import ( + "os" + "sync" +) -type SystemProcess interface { +type systemProcessInheritance interface { Signal(sig os.Signal) error Kill() error Pid() int @@ -10,3 +13,37 @@ type SystemProcess interface { State() *os.ProcessState ForcedTTY() bool } + +type SystemProcess struct { + mutex sync.Mutex + inheritance systemProcessInheritance +} + +func NewSystemProcessStruct() *SystemProcess { + return &SystemProcess{inheritance: nil} +} + +func (sp *SystemProcess) getInheritance() systemProcessInheritance { + sp.mutex.Lock() + defer sp.mutex.Unlock() + return sp.inheritance +} + +func (sp *SystemProcess) Set(i systemProcessInheritance) { + sp.mutex.Lock() + sp.inheritance = i + sp.mutex.Unlock() +} + +func (sp *SystemProcess) Defined() bool { + sp.mutex.Lock() + defer sp.mutex.Unlock() + return sp.inheritance != nil +} + +func (sp *SystemProcess) Signal(sig os.Signal) error { return sp.getInheritance().Signal(sig) } +func (sp *SystemProcess) Kill() error { return sp.getInheritance().Kill() } +func (sp *SystemProcess) Pid() int { return sp.getInheritance().Pid() } +func (sp *SystemProcess) ExitNum() int { return sp.getInheritance().ExitNum() } +func (sp *SystemProcess) State() *os.ProcessState { return sp.getInheritance().State() } +func (sp *SystemProcess) ForcedTTY() bool { return sp.getInheritance().ForcedTTY() } diff --git a/lang/process/sysproc_test.go b/lang/process/sysproc_test.go new file mode 100644 index 000000000..66ebce341 --- /dev/null +++ b/lang/process/sysproc_test.go @@ -0,0 +1,95 @@ +package process_test + +import ( + "errors" + "os" + "testing" + + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/test/count" +) + +type sysProcTest1T struct{} + +func (sp *sysProcTest1T) Pid() int { return 0 } +func (sp *sysProcTest1T) ExitNum() int { return 1 } +func (sp *sysProcTest1T) Kill() error { return nil } +func (sp *sysProcTest1T) Signal(sig os.Signal) error { return errors.New("3") } +func (sp *sysProcTest1T) State() *os.ProcessState { return nil } +func (sp *sysProcTest1T) ForcedTTY() bool { return false } + +type sysProcTest2T struct{} + +func (sp *sysProcTest2T) Pid() int { return 4 } +func (sp *sysProcTest2T) ExitNum() int { return 5 } +func (sp *sysProcTest2T) Kill() error { return errors.New("6") } +func (sp *sysProcTest2T) Signal(sig os.Signal) error { return nil } +func (sp *sysProcTest2T) State() *os.ProcessState { return nil } +func (sp *sysProcTest2T) ForcedTTY() bool { return true } + +func TestSystemProcess(t *testing.T) { + count.Tests(t, (6*2)+1) + + p := lang.NewTestProcess() + + if p.SystemProcess.Defined() { + t.Errorf("p.SystemProcess.Defined() returned true, should be false") + return + } + + var success bool + + p.SystemProcess.Set(&sysProcTest1T{}) + switch { + case !p.SystemProcess.Defined(): + t.Errorf("invalid return for: p.SystemProcess.Defined() in test 1") + + case p.SystemProcess.Pid() != 0: + t.Errorf("invalid return for: p.SystemProcess.Pid() in test 1") + + case p.SystemProcess.ExitNum() != 1: + t.Errorf("invalid return for: p.SystemProcess.ExitNum() in test 1") + + case p.SystemProcess.Kill() != nil: + t.Errorf("invalid return for: p.SystemProcess.Kill() in test 1") + + case p.SystemProcess.Signal(nil).Error() != "3": + t.Errorf("invalid return for: p.SystemProcess.Signal(nil).Error() in test 1") + + case p.SystemProcess.ForcedTTY() != false: + t.Errorf("invalid return for: p.SystemProcess.ForcedTTY() in test 1") + + default: + success = true + } + + if !success { + return + } + + success = false + + p.SystemProcess.Set(&sysProcTest2T{}) + switch { + case !p.SystemProcess.Defined(): + t.Errorf("invalid return for: p.SystemProcess.Defined() in test 2") + + case p.SystemProcess.Pid() != 4: + t.Errorf("invalid return for: p.SystemProcess.Pid() in test 2") + + case p.SystemProcess.ExitNum() != 5: + t.Errorf("invalid return for: p.SystemProcess.ExitNum() in test 2") + + case p.SystemProcess.Kill().Error() != "6": + t.Errorf("invalid return for: p.SystemProcess.Kill() in test 2") + + case p.SystemProcess.Signal(nil) != nil: + t.Errorf("invalid return for: p.SystemProcess.Signal(nil).Error() in test 2") + + case p.SystemProcess.ForcedTTY() != true: + t.Errorf("invalid return for: p.SystemProcess.ForcedTTY() in test 2") + + default: + success = true + } +} diff --git a/lang/process_structs.go b/lang/process_structs.go index 69ffdc438..b6d70dd9a 100644 --- a/lang/process_structs.go +++ b/lang/process_structs.go @@ -39,7 +39,7 @@ type Process struct { HasStopped chan bool `json:"-"` Done func() `json:"-"` Kill func() `json:"-"` - SystemProcess process.SystemProcess + SystemProcess *process.SystemProcess Envs []string Scope *Process `json:"-"` Parent *Process `json:"-"` @@ -123,7 +123,7 @@ func (p *Process) Dump() map[string]any { } func _jsonfySysProc(p *Process) any { - if p.SystemProcess == nil { + if !p.SystemProcess.Defined() { return nil } diff --git a/shell/shell.go b/shell/shell.go index f36b39c60..7eee77dbc 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -120,7 +120,7 @@ func showPrompt() { panic("shell.ShowPrompt() called before initialising prompt with shell.Start()") } - //lang.UnixPidToFg(0) + lang.UnixPidToFg(0) v, err := lang.ShellProcess.Config.Get("shell", "max-suggestions", types.Integer) if err != nil { diff --git a/shell/signal_handler/functions/signals.go b/shell/signal_handler/functions/signals.go new file mode 100644 index 000000000..fcc1f0e51 --- /dev/null +++ b/shell/signal_handler/functions/signals.go @@ -0,0 +1,93 @@ +package signalhandler + +import ( + "fmt" + "os" + "regexp" + + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/utils" +) + +var signalChan chan os.Signal = make(chan os.Signal, 1) + +const ( + // PromptSIGINT defines the string to write when ctrl+c is pressed + PromptSIGINT = "^C" + + // PromptSIGQUIT defines the string to write when ctrl+\ is pressed + PromptSIGQUIT = "^\\" + + // PromptEOF defines the string to write when ctrl+d is pressed + PromptEOF = "^D" +) + +func sigint(interactive bool) { + //tty.Stderr.WriteString(PromptSIGINT) + sigterm(interactive) +} + +func sigterm(interactive bool) { + if !interactive { + lang.Exit(0) + } + + p := lang.ForegroundProc.Get() + //p.Json("p =", p) + + switch { + case p == nil: + //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground process")) + case p.Kill == nil: + //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground kill function")) + default: + p.Kill() + } +} + +var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) + +func sigquit(interactive bool) { + if !interactive { + os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) + lang.Exit(2) + } + + //tty.Stderr.WriteString(PromptSIGQUIT) + os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) + + fids := lang.GlobalFIDs.ListAll() + for _, p := range fids { + if p.Kill != nil /*&& !p.HasTerminated()*/ { + procName := p.Name.String() + procParam, _ := p.Parameters.String(0) + if procName == "exec" { + procName = procParam + procParam, _ = p.Parameters.String(1) + } + if len(procParam) > 60 { + procParam = procParam[:60] + "..." + } + procParam = rxWhiteSpace.ReplaceAllString(procParam, " ") + + lang.ShellProcess.Stderr.Writeln([]byte( + fmt.Sprintf( + "!!! Force closing FID %d: %s %s !!!", + p.Id, procName, procParam))) + p.Kill() + + if p.SystemProcess.Defined() { + err := p.SystemProcess.Kill() + if err != nil { + lang.ShellProcess.Stderr.Writeln([]byte( + fmt.Sprintf( + "!!! Error terminating FID %d (%d), `%s`: %s", + p.Id, p.SystemProcess.Pid(), procName, err.Error()))) + } + } + } + } + + lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) + lang.ShowPrompt <- true +} diff --git a/shell/signal_handler/functions/signals_unix.go b/shell/signal_handler/functions/signals_unix.go new file mode 100644 index 000000000..4c9500246 --- /dev/null +++ b/shell/signal_handler/functions/signals_unix.go @@ -0,0 +1,132 @@ +//go:build !windows && !plan9 && !js +// +build !windows,!plan9,!js + +package signalhandler + +import ( + "fmt" + "os/signal" + "syscall" + + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/state" + "github.com/lmorg/murex/lang/types" + "github.com/lmorg/murex/utils/humannumbers" +) + +// EventLoop is an internal function to capture and handle OS signals (eg SIGTERM). +func EventLoop(interactive bool) { + Register(interactive) + + go func() { + for { + sig := <-signalChan + switch sig.String() { + + case syscall.SIGINT.String(): + go sigint(interactive) + + case syscall.SIGTERM.String(): + go sigterm(interactive) + + case syscall.SIGQUIT.String(): + go sigquit(interactive) + + case syscall.SIGTSTP.String(): + go sigtstp() + + case syscall.SIGCHLD.String(): + // TODO + + default: + panic("unhandled signal: " + sig.String()) // this shouldn't ever happen + } + } + }() +} + +func Register(interactive bool) { + if interactive { + // Interactive, so we will handle stop + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) + + } else { + // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + } +} + +func sigtstp() { + p := lang.ForegroundProc.Get() + //debug.Json("p =", p) + + show, err := lang.ShellProcess.Config.Get("shell", "stop-status-enabled", types.Boolean) + if err != nil { + show = false + } + + if show.(bool) { + stopStatus(p) + } + + if p.SystemProcess.Defined() { + err = p.SystemProcess.Signal(syscall.SIGSTOP) + if err != nil { + lang.ShellProcess.Stderr.Write([]byte(err.Error())) + } + } + + p.State.Set(state.Stopped) + go func() { p.HasStopped <- true }() + + lang.ShowPrompt <- true +} + +func stopStatus(p *lang.Process) { + var ( + stdinR, stdinW uint64 + stdoutR, stdoutW uint64 + stderrR, stderrW uint64 + ) + + if p.Stdin != nil { + stdinW, stdinR = p.Stdin.Stats() + } + if p.Stdout != nil { + stdoutW, stdoutR = p.Stdout.Stats() + } + if p.Stderr != nil { + stderrW, stderrR = p.Stderr.Stats() + } + + pipeStatus := fmt.Sprintf( + "\nSTDIN: %s written / %s read\nSTDOUT: %s written / %s read\nSTDERR: %s written / %s read", + humannumbers.Bytes(stdinW), humannumbers.Bytes(stdinR), + humannumbers.Bytes(stdoutW), humannumbers.Bytes(stdoutR), + humannumbers.Bytes(stderrW), humannumbers.Bytes(stderrR), + ) + lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) + + if p.SystemProcess.Defined() { + block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) + if err != nil { + lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) + return + } + + fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN) + fork.Name.Set("(SIGSTOP)") + fork.FileRef = fileRef + fork.Variables.Set(fork.Process, "PID", p.SystemProcess.Pid(), types.Integer) + _, err = fork.Execute([]rune(block.(string))) + + if err != nil { + lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) + } + } + + lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( + "FID %d has been stopped.\nUse `fg %d` / `bg %d` to manage the FID or `jobs` to see a list of background and suspended functions", + p.Id, p.Id, p.Id, + ))) +} diff --git a/shell/signal_handler/sigfns/sigfns.go b/shell/signal_handler/sigfns/sigfns.go index 6fa729bc4..9a4e5eda3 100644 --- a/shell/signal_handler/sigfns/sigfns.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -60,7 +60,7 @@ func Sigquit(interactive bool) { p.Id, procName, procParam))) p.Kill() - if p.SystemProcess != nil { + if p.SystemProcess.Defined() { err := p.SystemProcess.Kill() if err != nil { lang.ShellProcess.Stderr.Writeln([]byte( diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 42915f700..48e55c4d0 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -15,7 +15,7 @@ import ( func Sigtstp(interactive bool) { p := lang.ForegroundProc.Get() - if p.SystemProcess != nil { + if p.SystemProcess.Defined() { err := p.SystemProcess.Signal(syscall.SIGSTOP) if err != nil { lang.ShellProcess.Stderr.Write([]byte(err.Error())) @@ -29,7 +29,7 @@ func Sigtstp(interactive bool) { func returnFromSigtstp(p *lang.Process) { p.State.Set(state.Stopped) - if p.SystemProcess != nil && p.SystemProcess.ForcedTTY() { + if p.SystemProcess.Defined() && p.SystemProcess.ForcedTTY() { lang.UnixPidToFg(0) } @@ -54,11 +54,8 @@ func Sigchld(interactive bool) { } p := lang.ForegroundProc.Get() - if p.SystemProcess == nil { - return - } - if !p.SystemProcess.ForcedTTY() { + if !p.SystemProcess.Defined() || !p.SystemProcess.ForcedTTY() { return } @@ -94,7 +91,7 @@ func stopStatus(p *lang.Process) { ) lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) - if p.SystemProcess != nil { + if p.SystemProcess.Defined() { block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) if err != nil { lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) diff --git a/version.svg b/version.svg index f5a924acb..d88b87b1b 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0445Version6.3.0445 +Version: 6.3.0466Version6.3.0466 From d194848450b85afe93b316024f5354704f2755fc Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 25 Aug 2024 23:55:51 +0100 Subject: [PATCH 053/142] add branch name to app version --- app/app.go | 11 +++++++---- app/app_test.go | 2 +- app/update-version.mx | 25 +++++++++++++++++++++++++ version.svg | 2 +- 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100755 app/update-version.mx diff --git a/app/app.go b/app/app.go index ac3b99f06..ef92854b2 100644 --- a/app/app.go +++ b/app/app.go @@ -1,3 +1,5 @@ +//go:generate ./update-version.mx + package app import ( @@ -10,12 +12,13 @@ import ( const Name = "murex" // Version number of $SHELL -// Format of version string should be "(major).(minor).(revision) DESCRIPTION" +// Format of version string should be "(major).(minor).(revision) BRANCH-NAME" const ( - version = "%d.%d.%04d JC863" + version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 466 + Revision = 469 + Branch = "863/job-control" ) // Copyright is the copyright owner string @@ -35,7 +38,7 @@ func init() { var v string func Version() string { - return v + return fmt.Sprintf("%s %s", v, Branch) } var sv *semver.Version diff --git a/app/app_test.go b/app/app_test.go index 2318e8d5d..b2aa60c83 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -21,7 +21,7 @@ func TestAppName(t *testing.T) { func TestVersion(t *testing.T) { count.Tests(t, 1) - rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( (ALPHA|BETA|RC[0-9]))?$`) + rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( ([A-Z]+[0-9]+))?$`) if !rx.MatchString(Version()) { t.Error("Release version doesn't contain a valid string:") diff --git a/app/update-version.mx b/app/update-version.mx new file mode 100755 index 000000000..85092d18b --- /dev/null +++ b/app/update-version.mx @@ -0,0 +1,25 @@ +#!/usr/bin/env murex + +$GLOBAL.APP_GO = "./app.go" + +function get_revision_number { + $rev = ${ open $GLOBAL.APP_GO -> :str: regexp 'f/Revision\s+=\s+([0-9]+)' } + out ($rev+1) +} + +function get_branch_name { + git(rev-parse --abbrev-ref HEAD) +} + +!if { g $GLOBAL.APP_GO } then { return } + +$rev = get_revision_number() +$branch = get_branch_name() + +open $GLOBAL.APP_GO \ +-> :str: regexp %(s/Revision\s+=\s+[0-9]+/Revision = $rev) \ +-> regexp %(s#Branch\s+=\s+".*?"#Branch = "$branch"#) \ +-> set app_go + +$app_go |> $GLOBAL.APP_GO +go fmt $GLOBAL.APP_GO diff --git a/version.svg b/version.svg index d88b87b1b..11a94dffe 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0466Version6.3.0466 +Version: 6.3.0470Version6.3.0470 From 757f1ef7615ea997a7bc0b96ae19abcaf6abefb0 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 00:32:29 +0100 Subject: [PATCH 054/142] disable syscall error when not in debug mode --- app/app.go | 2 +- lang/exec_unix.go | 2 +- version.svg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index ef92854b2..9b940c51a 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 469 + Revision = 472 Branch = "863/job-control" ) diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 87873e2b9..f5380cae1 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -119,7 +119,7 @@ func UnixPidToFg(pid int) { } err := unix.IoctlSetPointerInt(0, unix.TIOCSPGRP, pid) - if err != nil { + if err != nil && debug.Enabled { os.Stderr.WriteString( fmt.Sprintf("!!! failed syscall in unix.IoctlSetPointerInt -> unixResetFg()...\n!!! %s\n", err.Error(), diff --git a/version.svg b/version.svg index 11a94dffe..f0d2cc1c5 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0470Version6.3.0470 +Version: 6.3.0473Version6.3.0473 From b4c074242f46442f611d05d4b76db33bfa399d53 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 00:35:21 +0100 Subject: [PATCH 055/142] fix app_text test --- app/app.go | 2 +- app/app_test.go | 2 +- builtins/core/management/version_test.go | 4 ++-- version.svg | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/app.go b/app/app.go index 9b940c51a..72d1122c4 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 472 + Revision = 476 Branch = "863/job-control" ) diff --git a/app/app_test.go b/app/app_test.go index b2aa60c83..004f973a0 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -21,7 +21,7 @@ func TestAppName(t *testing.T) { func TestVersion(t *testing.T) { count.Tests(t, 1) - rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( ([A-Z]+[0-9]+))?$`) + rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( ([-._/a-zA-Z0-9]+))?$`) if !rx.MatchString(Version()) { t.Error("Release version doesn't contain a valid string:") diff --git a/builtins/core/management/version_test.go b/builtins/core/management/version_test.go index 24af02453..cec4b146b 100644 --- a/builtins/core/management/version_test.go +++ b/builtins/core/management/version_test.go @@ -11,7 +11,7 @@ func TestVersion(t *testing.T) { tests := []test.MurexTest{ { Block: `version`, - Stdout: `murex: [0-9]+\.[0-9]+\.[0-9]+( (ALPHA|BETA|RC[0-9]))?\nLicense .*?\n© 2018-[0-9]{4} Laurence Morgan\n`, + Stdout: `murex: [0-9]+\.[0-9]+\.[0-9]+( (.*?))?\nLicense .*?\n© 2018-[0-9]{4} Laurence Morgan\n`, }, { Block: `version: --copyright`, @@ -23,7 +23,7 @@ func TestVersion(t *testing.T) { }, { Block: `version: --no-app-name`, - Stdout: `[0-9]+\.[0-9]+\.[0-9]+( (ALPHA|BETA|RC[0-9]))?\n`, + Stdout: `[0-9]+\.[0-9]+\.[0-9]+( (.*?))?\n`, }, { Block: `version: --short`, diff --git a/version.svg b/version.svg index f0d2cc1c5..9f6c0fc4d 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0473Version6.3.0473 +Version: 6.3.0477Version6.3.0477 From 4b901c77d7ac8325b9045dd0906910c555b66edd Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 00:50:11 +0100 Subject: [PATCH 056/142] add `docgen` to go generate --- app/app.go | 2 +- docs.go | 4 ++++ test/pre-commit | 10 ++-------- version.svg | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/app.go b/app/app.go index 72d1122c4..9de29eea9 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 476 + Revision = 481 Branch = "863/job-control" ) diff --git a/docs.go b/docs.go index f5f6570c5..d764f9863 100644 --- a/docs.go +++ b/docs.go @@ -1,3 +1,7 @@ +//go:generate go build -v github.com/lmorg/murex/utils/docgen +//go:generate ./docgen -warning -panic -config gen/docgen.yaml +//go:generate go fmt builtins/docs/summaries.go + package main import ( diff --git a/test/pre-commit b/test/pre-commit index d433d4184..f67a1c892 100755 --- a/test/pre-commit +++ b/test/pre-commit @@ -24,14 +24,8 @@ ctrl_c() { echo "Updating auto-generated code...." go generate ./... -echo "Compiling docgen...." -go install github.com/lmorg/murex/utils/docgen - -echo "Compiling Murex docs...." -docgen -config gen/docgen.yaml -warning - -echo "Formatting autogen docs...." -go fmt $cdocs/*.go +#echo "Compiling docgen...." +#go install github.com/lmorg/murex/utils/docgen export MUREXVERSION="$(go run github.com/lmorg/murex --version | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+')" sed "s/\$MUREXVERSION/$MUREXVERSION/g" \ diff --git a/version.svg b/version.svg index 9f6c0fc4d..ee380b799 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0477Version6.3.0477 +Version: 6.3.0482Version6.3.0482 From 7003e020557fa39a2e741b2ee6405faa85bf5a2d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 01:07:24 +0100 Subject: [PATCH 057/142] re-introduce `pid` var named pipe --- app/app.go | 2 +- lang/redirection.go | 16 +++++++++++----- version.svg | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 9de29eea9..66cd5b271 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 481 + Revision = 482 Branch = "863/job-control" ) diff --git a/lang/redirection.go b/lang/redirection.go index c90e994b1..36f3e6a98 100644 --- a/lang/redirection.go +++ b/lang/redirection.go @@ -4,6 +4,7 @@ import ( "crypto/md5" "fmt" "strings" + "time" "github.com/lmorg/murex/lang/types" ) @@ -45,16 +46,21 @@ func parseRedirection(p *Process) { } case len(name) > 4 && name[:4] == "pid:": - panic("TODO") - /*varName := name[4:] - p.Exec.Callback = func(pid int) { - err := p.Variables.Set(p, varName, pid, types.Integer) + varName := name[4:] + go func() { + for { + time.Sleep(10 * time.Millisecond) + if p.SystemProcess.Defined() { + break + } + } + err := p.Variables.Set(p, varName, p.SystemProcess.Pid(), types.Integer) if err != nil { ShellProcess.Stderr.Writeln([]byte( fmt.Sprintf("Cannot write variable '%s': %s", varName, err.Error()), )) } - }*/ + }() case name[0] == '!': if p.NamedPipeErr == "" { diff --git a/version.svg b/version.svg index ee380b799..a3f204322 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0482Version6.3.0482 +Version: 6.3.0483Version6.3.0483 From 31ec3ce11f9977f7a55cdb8f7f3e500e552ff733 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 01:27:48 +0100 Subject: [PATCH 058/142] make pid named pipe a blocking call --- app/app.go | 2 +- lang/process/sysproc.go | 11 ++++++++++- lang/redirection.go | 9 +-------- version.svg | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/app.go b/app/app.go index 66cd5b271..ed2f0ba8c 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 482 + Revision = 485 Branch = "863/job-control" ) diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index f52f980e7..76e6176fc 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -17,10 +17,13 @@ type systemProcessInheritance interface { type SystemProcess struct { mutex sync.Mutex inheritance systemProcessInheritance + pid chan int } func NewSystemProcessStruct() *SystemProcess { - return &SystemProcess{inheritance: nil} + sp := new(SystemProcess) + sp.pid = make(chan int, 2) + return sp } func (sp *SystemProcess) getInheritance() systemProcessInheritance { @@ -32,6 +35,7 @@ func (sp *SystemProcess) getInheritance() systemProcessInheritance { func (sp *SystemProcess) Set(i systemProcessInheritance) { sp.mutex.Lock() sp.inheritance = i + sp.pid <- i.Pid() sp.mutex.Unlock() } @@ -47,3 +51,8 @@ func (sp *SystemProcess) Pid() int { return sp.getInheritance( func (sp *SystemProcess) ExitNum() int { return sp.getInheritance().ExitNum() } func (sp *SystemProcess) State() *os.ProcessState { return sp.getInheritance().State() } func (sp *SystemProcess) ForcedTTY() bool { return sp.getInheritance().ForcedTTY() } + +// WaitForPid should only be used in redirection.go +func (sp *SystemProcess) WaitForPid() int { + return <-sp.pid +} diff --git a/lang/redirection.go b/lang/redirection.go index 36f3e6a98..e26707562 100644 --- a/lang/redirection.go +++ b/lang/redirection.go @@ -4,7 +4,6 @@ import ( "crypto/md5" "fmt" "strings" - "time" "github.com/lmorg/murex/lang/types" ) @@ -48,13 +47,7 @@ func parseRedirection(p *Process) { case len(name) > 4 && name[:4] == "pid:": varName := name[4:] go func() { - for { - time.Sleep(10 * time.Millisecond) - if p.SystemProcess.Defined() { - break - } - } - err := p.Variables.Set(p, varName, p.SystemProcess.Pid(), types.Integer) + err := p.Variables.Set(p, varName, p.SystemProcess.WaitForPid(), types.Integer) if err != nil { ShellProcess.Stderr.Writeln([]byte( fmt.Sprintf("Cannot write variable '%s': %s", varName, err.Error()), diff --git a/version.svg b/version.svg index a3f204322..c5eb4029b 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0483Version6.3.0483 +Version: 6.3.0486Version6.3.0486 From 77148063bb3c4bdbb1b10e90a6834598328d1193 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 10:03:43 +0100 Subject: [PATCH 059/142] exec: don't force-tty by default --- app/app.go | 24 ++-- lang/exec.go | 9 +- lang/exec_unix.go | 6 +- shell/shell.go | 2 +- shell/signal_handler/functions/signals.go | 93 ------------ .../signal_handler/functions/signals_unix.go | 132 ------------------ shell/signal_handler/sigfns/sigfns.go | 8 +- version.svg | 2 +- 8 files changed, 25 insertions(+), 251 deletions(-) delete mode 100644 shell/signal_handler/functions/signals.go delete mode 100644 shell/signal_handler/functions/signals_unix.go diff --git a/app/app.go b/app/app.go index ed2f0ba8c..5353b37de 100644 --- a/app/app.go +++ b/app/app.go @@ -3,9 +3,9 @@ package app import ( - "fmt" +"fmt" - "github.com/lmorg/murex/utils/semver" +"github.com/lmorg/murex/utils/semver" ) // Name is the name of the $SHELL @@ -14,11 +14,11 @@ const Name = "murex" // Version number of $SHELL // Format of version string should be "(major).(minor).(revision) BRANCH-NAME" const ( - version = "%d.%d.%04d" - Major = 6 - Minor = 3 - Revision = 485 - Branch = "863/job-control" +version = "%d.%d.%04d" +Major = 6 +Minor = 3 +Revision = 494 +Branch = "863/job-control" ) // Copyright is the copyright owner string @@ -31,18 +31,18 @@ const License = "License GPL v2" var ShellModule = Name + "/shell" func init() { - v = fmt.Sprintf(version, Major, Minor, Revision) - sv, _ = semver.Parse(v) +v = fmt.Sprintf(version, Major, Minor, Revision) +sv, _ = semver.Parse(v) } var v string func Version() string { - return fmt.Sprintf("%s %s", v, Branch) +return fmt.Sprintf("%s %s", v, Branch) } var sv *semver.Version func Semver() *semver.Version { - return sv -} +return sv +} \ No newline at end of file diff --git a/lang/exec.go b/lang/exec.go index 9e297feee..b4a489fce 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -79,6 +79,7 @@ func execForkFallback(p *Process, argv []string) error { } err := cmd.Process.Signal(syscall.SIGTERM) + UnixPidToFg(0) if err != nil { if err.Error() == os.ErrProcessDone.Error() { return @@ -218,12 +219,12 @@ func execForkFallback(p *Process, argv []string) error { if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { signal.Ignore(syscall.SIGTTOU) - defer signal.Reset(syscall.SIGTTOU) UnixPidToFg(cmd.Process.Pid) - defer UnixPidToFg(0) - //signalhandler.Register(Interactive) } err := cmd.Wait() + signal.Reset(syscall.SIGTTOU) + UnixPidToFg(0) + //signalhandler.Register(Interactive) if err != nil { if !strings.HasPrefix(err.Error(), "signal:") { //mxdtR.Close() @@ -242,4 +243,4 @@ func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.Exi func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } func (sp *sysProcT) State() *os.ProcessState { return sp.cmd.ProcessState } -func (sp *sysProcT) ForcedTTY() bool { return true } +func (sp *sysProcT) ForcedTTY() bool { return false } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index f5380cae1..3afd79bc6 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -135,7 +135,7 @@ func osSysProcAttr(fd int) *syscall.SysProcAttr { //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, // or, if Pgid == 0, to the new child's process ID. - Setpgid: true, + //Setpgid: true, // Setctty sets the controlling terminal of the child to // file descriptor Ctty. Ctty must be a descriptor number // in the child process: an index into ProcAttr.Files. @@ -148,7 +148,7 @@ func osSysProcAttr(fd int) *syscall.SysProcAttr { // the descriptor of the controlling TTY. // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. - Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. + //Foreground: true, + //Pgid: 0, // Child's process group ID if Setpgid. } } diff --git a/shell/shell.go b/shell/shell.go index 7eee77dbc..f36b39c60 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -120,7 +120,7 @@ func showPrompt() { panic("shell.ShowPrompt() called before initialising prompt with shell.Start()") } - lang.UnixPidToFg(0) + //lang.UnixPidToFg(0) v, err := lang.ShellProcess.Config.Get("shell", "max-suggestions", types.Integer) if err != nil { diff --git a/shell/signal_handler/functions/signals.go b/shell/signal_handler/functions/signals.go deleted file mode 100644 index fcc1f0e51..000000000 --- a/shell/signal_handler/functions/signals.go +++ /dev/null @@ -1,93 +0,0 @@ -package signalhandler - -import ( - "fmt" - "os" - "regexp" - - "github.com/lmorg/murex/lang" - "github.com/lmorg/murex/utils" -) - -var signalChan chan os.Signal = make(chan os.Signal, 1) - -const ( - // PromptSIGINT defines the string to write when ctrl+c is pressed - PromptSIGINT = "^C" - - // PromptSIGQUIT defines the string to write when ctrl+\ is pressed - PromptSIGQUIT = "^\\" - - // PromptEOF defines the string to write when ctrl+d is pressed - PromptEOF = "^D" -) - -func sigint(interactive bool) { - //tty.Stderr.WriteString(PromptSIGINT) - sigterm(interactive) -} - -func sigterm(interactive bool) { - if !interactive { - lang.Exit(0) - } - - p := lang.ForegroundProc.Get() - //p.Json("p =", p) - - switch { - case p == nil: - //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground process")) - case p.Kill == nil: - //lang.ShellProcess.Stderr.Writeln([]byte("!!! Unable to identify foreground kill function")) - default: - p.Kill() - } -} - -var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) - -func sigquit(interactive bool) { - if !interactive { - os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) - lang.Exit(2) - } - - //tty.Stderr.WriteString(PromptSIGQUIT) - os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) - - fids := lang.GlobalFIDs.ListAll() - for _, p := range fids { - if p.Kill != nil /*&& !p.HasTerminated()*/ { - procName := p.Name.String() - procParam, _ := p.Parameters.String(0) - if procName == "exec" { - procName = procParam - procParam, _ = p.Parameters.String(1) - } - if len(procParam) > 60 { - procParam = procParam[:60] + "..." - } - procParam = rxWhiteSpace.ReplaceAllString(procParam, " ") - - lang.ShellProcess.Stderr.Writeln([]byte( - fmt.Sprintf( - "!!! Force closing FID %d: %s %s !!!", - p.Id, procName, procParam))) - p.Kill() - - if p.SystemProcess.Defined() { - err := p.SystemProcess.Kill() - if err != nil { - lang.ShellProcess.Stderr.Writeln([]byte( - fmt.Sprintf( - "!!! Error terminating FID %d (%d), `%s`: %s", - p.Id, p.SystemProcess.Pid(), procName, err.Error()))) - } - } - } - } - - lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) - lang.ShowPrompt <- true -} diff --git a/shell/signal_handler/functions/signals_unix.go b/shell/signal_handler/functions/signals_unix.go deleted file mode 100644 index 4c9500246..000000000 --- a/shell/signal_handler/functions/signals_unix.go +++ /dev/null @@ -1,132 +0,0 @@ -//go:build !windows && !plan9 && !js -// +build !windows,!plan9,!js - -package signalhandler - -import ( - "fmt" - "os/signal" - "syscall" - - "github.com/lmorg/murex/lang" - "github.com/lmorg/murex/lang/state" - "github.com/lmorg/murex/lang/types" - "github.com/lmorg/murex/utils/humannumbers" -) - -// EventLoop is an internal function to capture and handle OS signals (eg SIGTERM). -func EventLoop(interactive bool) { - Register(interactive) - - go func() { - for { - sig := <-signalChan - switch sig.String() { - - case syscall.SIGINT.String(): - go sigint(interactive) - - case syscall.SIGTERM.String(): - go sigterm(interactive) - - case syscall.SIGQUIT.String(): - go sigquit(interactive) - - case syscall.SIGTSTP.String(): - go sigtstp() - - case syscall.SIGCHLD.String(): - // TODO - - default: - panic("unhandled signal: " + sig.String()) // this shouldn't ever happen - } - } - }() -} - -func Register(interactive bool) { - if interactive { - // Interactive, so we will handle stop - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP) //, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) - - } else { - // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - } -} - -func sigtstp() { - p := lang.ForegroundProc.Get() - //debug.Json("p =", p) - - show, err := lang.ShellProcess.Config.Get("shell", "stop-status-enabled", types.Boolean) - if err != nil { - show = false - } - - if show.(bool) { - stopStatus(p) - } - - if p.SystemProcess.Defined() { - err = p.SystemProcess.Signal(syscall.SIGSTOP) - if err != nil { - lang.ShellProcess.Stderr.Write([]byte(err.Error())) - } - } - - p.State.Set(state.Stopped) - go func() { p.HasStopped <- true }() - - lang.ShowPrompt <- true -} - -func stopStatus(p *lang.Process) { - var ( - stdinR, stdinW uint64 - stdoutR, stdoutW uint64 - stderrR, stderrW uint64 - ) - - if p.Stdin != nil { - stdinW, stdinR = p.Stdin.Stats() - } - if p.Stdout != nil { - stdoutW, stdoutR = p.Stdout.Stats() - } - if p.Stderr != nil { - stderrW, stderrR = p.Stderr.Stats() - } - - pipeStatus := fmt.Sprintf( - "\nSTDIN: %s written / %s read\nSTDOUT: %s written / %s read\nSTDERR: %s written / %s read", - humannumbers.Bytes(stdinW), humannumbers.Bytes(stdinR), - humannumbers.Bytes(stdoutW), humannumbers.Bytes(stdoutR), - humannumbers.Bytes(stderrW), humannumbers.Bytes(stderrR), - ) - lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) - - if p.SystemProcess.Defined() { - block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) - if err != nil { - lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) - return - } - - fork := lang.ShellProcess.Fork(lang.F_FUNCTION | lang.F_BACKGROUND | lang.F_NO_STDIN) - fork.Name.Set("(SIGSTOP)") - fork.FileRef = fileRef - fork.Variables.Set(fork.Process, "PID", p.SystemProcess.Pid(), types.Integer) - _, err = fork.Execute([]rune(block.(string))) - - if err != nil { - lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) - } - } - - lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( - "FID %d has been stopped.\nUse `fg %d` / `bg %d` to manage the FID or `jobs` to see a list of background and suspended functions", - p.Id, p.Id, p.Id, - ))) -} diff --git a/shell/signal_handler/sigfns/sigfns.go b/shell/signal_handler/sigfns/sigfns.go index 9a4e5eda3..c2a04a1fd 100644 --- a/shell/signal_handler/sigfns/sigfns.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -2,11 +2,9 @@ package sigfns import ( "fmt" - "os" "regexp" "github.com/lmorg/murex/lang" - "github.com/lmorg/murex/utils" ) func Sigint(interactive bool) { @@ -34,12 +32,12 @@ var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) func Sigquit(interactive bool) { if !interactive { - os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) + //os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) lang.Exit(2) } - os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) - + //os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) + //lang.UnixPidToFg(0) fids := lang.GlobalFIDs.ListAll() for _, p := range fids { if p.Kill != nil /*&& !p.HasTerminated()*/ { diff --git a/version.svg b/version.svg index c5eb4029b..167bf60fd 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0486Version6.3.0486 +Version: 6.3.0495Version6.3.0495 From 867e5db18c61de3b463deb81e4063afecc2109ff Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 10:06:45 +0100 Subject: [PATCH 060/142] ci: add app.go to pre-commit hook --- app/app.go | 24 ++++++++++++------------ test/pre-commit | 7 +------ version.svg | 2 +- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/app/app.go b/app/app.go index 5353b37de..d22a283b5 100644 --- a/app/app.go +++ b/app/app.go @@ -3,9 +3,9 @@ package app import ( -"fmt" + "fmt" -"github.com/lmorg/murex/utils/semver" + "github.com/lmorg/murex/utils/semver" ) // Name is the name of the $SHELL @@ -14,11 +14,11 @@ const Name = "murex" // Version number of $SHELL // Format of version string should be "(major).(minor).(revision) BRANCH-NAME" const ( -version = "%d.%d.%04d" -Major = 6 -Minor = 3 -Revision = 494 -Branch = "863/job-control" + version = "%d.%d.%04d" + Major = 6 + Minor = 3 + Revision = 496 + Branch = "863/job-control" ) // Copyright is the copyright owner string @@ -31,18 +31,18 @@ const License = "License GPL v2" var ShellModule = Name + "/shell" func init() { -v = fmt.Sprintf(version, Major, Minor, Revision) -sv, _ = semver.Parse(v) + v = fmt.Sprintf(version, Major, Minor, Revision) + sv, _ = semver.Parse(v) } var v string func Version() string { -return fmt.Sprintf("%s %s", v, Branch) + return fmt.Sprintf("%s %s", v, Branch) } var sv *semver.Version func Semver() *semver.Version { -return sv -} \ No newline at end of file + return sv +} diff --git a/test/pre-commit b/test/pre-commit index f67a1c892..a958d8966 100755 --- a/test/pre-commit +++ b/test/pre-commit @@ -6,8 +6,6 @@ set -e PATH=$PATH:$GOPATH/bin -docs=docs -cdocs=builtins/docs flag=${1:-undef} if [ $flag != '--no-cd' ]; then @@ -24,14 +22,11 @@ ctrl_c() { echo "Updating auto-generated code...." go generate ./... -#echo "Compiling docgen...." -#go install github.com/lmorg/murex/utils/docgen - export MUREXVERSION="$(go run github.com/lmorg/murex --version | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+')" sed "s/\$MUREXVERSION/$MUREXVERSION/g" \ gen/website/version.svg > version.svg echo "Updating git...." -git add -v *.md *_string.go *_generated.go version.svg $docs $cdocs +git add -v app/app.go *.md *_string.go *_generated.go version.svg docs/ echo "Allowing git commit to proceed...." diff --git a/version.svg b/version.svg index 167bf60fd..192e859fa 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0495Version6.3.0495 +Version: 6.3.0496Version6.3.0496 From f25d72385087619a35d37302713747c2f6ab80c8 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 10:09:00 +0100 Subject: [PATCH 061/142] exec: remove tty signals & syscalls from regular fork --- app/app.go | 2 +- lang/exec.go | 15 +++++++-------- version.svg | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/app.go b/app/app.go index d22a283b5..dc326bb33 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 496 + Revision = 497 Branch = "863/job-control" ) diff --git a/lang/exec.go b/lang/exec.go index b4a489fce..8c557dcb6 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "os/exec" - "os/signal" "strings" "syscall" @@ -217,14 +216,14 @@ func execForkFallback(p *Process, argv []string) error { tty.Stderr.WriteString("error closing murex data type output file write pipe:" + err.Error() + "\n") }*/ - if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { - signal.Ignore(syscall.SIGTTOU) - UnixPidToFg(cmd.Process.Pid) - } + //if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { + // signal.Ignore(syscall.SIGTTOU) + // UnixPidToFg(cmd.Process.Pid) + //} err := cmd.Wait() - signal.Reset(syscall.SIGTTOU) - UnixPidToFg(0) - //signalhandler.Register(Interactive) + //signal.Reset(syscall.SIGTTOU) + //UnixPidToFg(0) + ////signalhandler.Register(Interactive) if err != nil { if !strings.HasPrefix(err.Error(), "signal:") { //mxdtR.Close() diff --git a/version.svg b/version.svg index 192e859fa..0d278a233 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0496Version6.3.0496 +Version: 6.3.0497Version6.3.0497 From 63b9acb5e06762dcdebbf27ca524d29a30db452b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 26 Aug 2024 22:21:55 +0100 Subject: [PATCH 062/142] #866 ignore panics in vim keys --- utils/readline/vim.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/utils/readline/vim.go b/utils/readline/vim.go index b76b1bdc7..1c1b57eec 100644 --- a/utils/readline/vim.go +++ b/utils/readline/vim.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" + "github.com/lmorg/murex/debug" "github.com/mattn/go-runewidth" ) @@ -18,6 +19,15 @@ const ( ) func (rl *Instance) vi(r rune) string { + if !debug.Enabled { + // This would normally be a massive anti-pattern. But in this instance + // any edge case exceptions are better off ignored and the interactive + // prompt kept alive. The worst case scenario is the cursor might + // become misaligned but that would resolve itself very quickly under + // normal operation. + defer recover() + } + var output string switch r { case 'a': From bcdbd604d2bd8764ec43cba2bbd33a815a2266c6 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 28 Aug 2024 00:36:05 +0100 Subject: [PATCH 063/142] #860 alias namespaces --- app/app.go | 2 +- builtins/core/escape/escape.go | 11 ----- builtins/core/lists/list.go | 23 ----------- integrations/_namespaces_any.mx | 71 +++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 35 deletions(-) delete mode 100644 builtins/core/lists/list.go create mode 100644 integrations/_namespaces_any.mx diff --git a/app/app.go b/app/app.go index 0e7ee0e57..4c3d0e418 100644 --- a/app/app.go +++ b/app/app.go @@ -15,7 +15,7 @@ const ( version = "%d.%d.%d" Major = 6 Minor = 3 - Revision = 3100 + Revision = 3200 ) // Copyright is the copyright owner string diff --git a/builtins/core/escape/escape.go b/builtins/core/escape/escape.go index 81d5675eb..bef16dc06 100644 --- a/builtins/core/escape/escape.go +++ b/builtins/core/escape/escape.go @@ -6,7 +6,6 @@ import ( "strconv" "strings" - "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/escape" @@ -20,16 +19,6 @@ func init() { lang.DefineMethod("escurl", cmdUrl, types.Text, types.String) lang.DefineMethod("!escurl", cmdUrl, types.Text, types.String) lang.DefineMethod("esccli", cmdEscapeCli, types.Text, types.String) - - defaults.AppendProfile(` - alias escape.quote = escape - alias !escape.quote = !escape - alias escape.html = eschtml - alias !escape.html = !eschtml - alias escape.url = escurl - alias !escape.url = !escurl - alias escape.cli = esccli - `) } func cmdEscape(p *lang.Process) error { diff --git a/builtins/core/lists/list.go b/builtins/core/lists/list.go deleted file mode 100644 index 94bc5b56b..000000000 --- a/builtins/core/lists/list.go +++ /dev/null @@ -1,23 +0,0 @@ -package lists - -import ( - "github.com/lmorg/murex/config/defaults" -) - -func init() { - defaults.AppendProfile(` - alias list.sort = msort - alias list.reverse = mtac - alias list.prepend = prepend - alias list.append = append - alias list.prefix = prefix - alias list.suffix = suffix - alias list.left = left - alias list.right = right - alias list.regex = regexp - alias !list.regex = !regexp - alias list.match = match - alias !list.match = !match - alias list.join = mjoin - `) -} diff --git a/integrations/_namespaces_any.mx b/integrations/_namespaces_any.mx new file mode 100644 index 000000000..7965ebdd2 --- /dev/null +++ b/integrations/_namespaces_any.mx @@ -0,0 +1,71 @@ +alias list.sort = msort +alias list.reverse = mtac +alias list.prepend = prepend +alias list.append = append +alias list.prefix = prefix +alias list.suffix = suffix +alias list.left = left +alias list.right = right +alias list.regex = regexp +alias !list.regex = !regexp +alias list.match = match +alias !list.match = !match +alias list.join = mjoin +alias list.new.str = a +alias list.new.type = ta + +alias struct.count = count +alias struct.new.map = map +alias struct.new.2darray = 2darray + +alias escape.quote = escape +alias !escape.quote = !escape +alias escape.html = eschtml +alias !escape.html = !eschtml +alias escape.url = escurl +alias !escape.url = !escurl +alias escape.cli = esccli + +alias io.out = out +alias io.err = err +alias io.pipe = read-named-pipe +alias io.stat = pt + +alias fs.glob = g +alias !fs.glob = !g +alias fs.regex = rx +alias !fs.regex = !rx +alias fs.file = f +alias fs.lockfile = lockfile +alias fs.new.temp.file = tmp + +alias sys.os = os +alias sys.cpu.arch = cpuarch +alias sys.cpu.count = cpucount + +alias shell.alias = alias +alias !shell.alias = !alias +alias shell.function = function +alias !shell.function = !function +alias shell.private = private +alias shell.pipe = pipe +alias !shell.pipe = !pipe +alias shell.event = event +alias !shell.event = !event + +alias shell.exec.builtin = fexec builtin +alias shell.exec.function = fexec function +alias shell.exec.private = fexec private + +alias murex.packages = murex-package +alias murex.rescan.path = murex-update-exe-list +alias murex.runtime = runtime +alias murex.config = config + +alias proc.fg = fg +alias proc.bg = bg +alias proc.jobs = fid-list --jobs +alias proc.list = fid-list +alias proc.kill = fid-kill +alias proc.kill.all = fid-killall +alias proc.send.signal = signal \ No newline at end of file From 8bb0ed501fd63cbaadbd1200c9f1524bd3087a25 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 28 Aug 2024 20:31:05 +0100 Subject: [PATCH 064/142] #860 first draft of builtin namespacing convention --- builtins/core/arraytools/2darray_doc.yaml | 4 +- builtins/core/arraytools/addheading_doc.yaml | 4 +- builtins/core/arraytools/map_doc.yaml | 6 +- builtins/core/arraytools/struct.go | 11 - .../core/autocomplete/autocomplete_doc.yaml | 4 +- builtins/core/config/config_doc.yaml | 4 +- builtins/core/datatools/alter_doc.yaml | 21 +- builtins/core/datatools/count_doc.yaml | 8 +- builtins/core/datatools/struct.go | 11 - builtins/core/datatools/structkeys_doc.yaml | 4 +- builtins/core/escape/escape_doc.yaml | 8 +- builtins/core/io/echo_doc.yaml | 11 +- builtins/core/io/f_doc.yaml | 4 +- builtins/core/io/file_doc.yaml | 11 +- builtins/core/io/g_doc.yaml | 4 +- builtins/core/io/lockfile_doc.yaml | 6 +- builtins/core/io/read_doc.yaml | 20 +- builtins/core/io/rx_doc.yaml | 4 +- builtins/core/io/tmp_doc.yaml | 4 +- builtins/core/lists/append_doc.yaml | 4 +- builtins/core/lists/case_doc.yaml | 4 +- builtins/core/lists/jsplit_doc.yaml | 4 +- builtins/core/lists/mjoin_doc.yaml | 2 +- builtins/core/lists/msort_doc.yaml | 4 +- builtins/core/lists/mtac_doc.yaml | 2 +- builtins/core/lists/push_pop_doc.yaml | 8 +- builtins/core/lists/regexp_doc.yaml | 8 +- builtins/core/management/debug_doc.yaml | 4 +- builtins/core/management/fexec_doc.yaml | 5 +- builtins/core/management/functions_doc.yaml | 17 +- builtins/core/management/history_doc.yaml | 4 +- builtins/core/management/shell_doc.yaml | 8 +- builtins/core/management/source_doc.yaml | 5 +- builtins/core/management/version_doc.yaml | 4 +- builtins/core/mkarray/array_doc.yaml | 9 +- builtins/core/modules/murex-package_doc.yaml | 4 +- builtins/core/open/open_doc.yaml | 8 +- builtins/core/openimage/open-image_doc.yaml | 4 +- builtins/core/pipe/namedpipe_doc.yaml | 3 +- builtins/core/pipe/pipe_doc.yaml | 4 +- builtins/core/pretty/pretty_doc.yaml | 6 +- builtins/core/processes/bgfg_doc.yaml | 10 +- builtins/core/processes/fid-list_doc.yaml | 4 +- builtins/core/processes/kill_doc.yaml | 8 +- builtins/core/runtime/runtime_doc.yaml | 3 +- builtins/core/system/system.go | 7 - builtins/core/system/system_doc.yaml | 8 +- builtins/core/typemgmt/datetime_doc.yaml | 4 +- builtins/core/typemgmt/round_doc.yaml | 4 +- builtins/core/typemgmt/types_doc.yaml | 3 +- builtins/core/typemgmt/variables_doc.yaml | 12 +- builtins/docs/summaries.go | 915 ++++++++++-------- builtins/optional/select/select_doc.yaml | 3 +- docs/blog/reading_lists.md | 6 +- docs/changelog/v2.0.md | 12 +- docs/changelog/v2.1.md | 14 +- docs/changelog/v2.10.md | 16 +- docs/changelog/v2.11.md | 14 +- docs/changelog/v2.2.md | 2 +- docs/changelog/v2.3.md | 4 +- docs/changelog/v2.4.md | 26 +- docs/changelog/v2.5.md | 24 +- docs/changelog/v2.6.md | 10 +- docs/changelog/v2.7.md | 12 +- docs/changelog/v2.8.md | 4 +- docs/changelog/v2.9.md | 10 +- docs/changelog/v3.0.md | 20 +- docs/changelog/v4.0.md | 4 +- docs/changelog/v4.2.md | 16 +- docs/changelog/v4.3.md | 8 +- docs/changelog/v4.4.md | 16 +- docs/changelog/v5.0.md | 12 +- docs/changelog/v5.1.md | 2 +- docs/changelog/v5.2.md | 12 +- docs/changelog/v5.3.md | 14 +- docs/changelog/v6.0.md | 14 +- docs/changelog/v6.1.md | 22 +- docs/changelog/v6.2.md | 6 +- docs/commands/2darray.md | 32 +- docs/commands/README.md | 284 +++--- docs/commands/a.md | 19 +- docs/commands/addheading.md | 36 +- docs/commands/alias.md | 26 +- docs/commands/alter.md | 15 +- docs/commands/append.md | 30 +- docs/commands/autocomplete.md | 16 +- docs/commands/bexists.md | 11 +- docs/commands/bg.md | 22 +- docs/commands/break.md | 4 +- docs/commands/cast.md | 6 +- docs/commands/cd.md | 4 +- docs/commands/config.md | 22 +- docs/commands/continue.md | 4 +- docs/commands/count.md | 42 +- docs/commands/cpuarch.md | 6 +- docs/commands/cpucount.md | 6 +- docs/commands/datetime.md | 10 +- docs/commands/debug.md | 12 +- docs/commands/err.md | 36 +- docs/commands/escape.md | 8 +- docs/commands/esccli.md | 12 +- docs/commands/eschtml.md | 14 +- docs/commands/escurl.md | 14 +- docs/commands/event.md | 6 +- docs/commands/exec.md | 33 +- docs/commands/exitnum.md | 12 +- docs/commands/export.md | 10 +- docs/commands/expr.md | 4 +- docs/commands/f.md | 14 +- docs/commands/fexec.md | 37 +- docs/commands/fg.md | 24 +- docs/commands/fid-kill.md | 36 +- docs/commands/fid-killall.md | 36 +- docs/commands/fid-list.md | 38 +- docs/commands/for.md | 8 +- docs/commands/foreach.md | 16 +- docs/commands/formap.md | 4 +- docs/commands/format.md | 2 +- docs/commands/function.md | 30 +- docs/commands/g.md | 16 +- docs/commands/get-type.md | 14 +- docs/commands/get.md | 4 +- docs/commands/getfile.md | 8 +- docs/commands/global.md | 10 +- docs/commands/history.md | 12 +- docs/commands/if.md | 4 +- docs/commands/is-null.md | 6 +- docs/commands/ja.md | 14 +- docs/commands/jsplit.md | 34 +- docs/commands/key-code.md | 2 +- docs/commands/left.md | 20 +- docs/commands/let.md | 10 +- docs/commands/list.case.md | 2 +- docs/commands/lockfile.md | 14 +- docs/commands/man-get-flags.md | 14 +- docs/commands/man-summary.md | 18 +- docs/commands/map.md | 30 +- docs/commands/match.md | 50 +- docs/commands/method.md | 6 +- docs/commands/mjoin.md | 4 +- docs/commands/msort.md | 28 +- docs/commands/mtac.md | 44 +- docs/commands/murex-docs.md | 18 +- docs/commands/murex-package.md | 14 +- docs/commands/murex-parser.md | 6 +- docs/commands/murex-update-exe-list.md | 14 +- docs/commands/namedpipe.md | 15 +- docs/commands/open-image.md | 12 +- docs/commands/open.md | 28 +- docs/commands/openagent.md | 10 +- docs/commands/os.md | 6 +- docs/commands/out.md | 21 +- docs/commands/pipe.md | 28 +- docs/commands/post.md | 4 +- docs/commands/prefix.md | 20 +- docs/commands/prepend.md | 32 +- docs/commands/pretty.md | 14 +- docs/commands/private.md | 26 +- docs/commands/pt.md | 10 +- docs/commands/rand.md | 2 +- docs/commands/read.md | 22 +- docs/commands/regexp.md | 48 +- docs/commands/return.md | 8 +- docs/commands/right.md | 20 +- docs/commands/round.md | 8 +- docs/commands/runmode.md | 16 +- docs/commands/runtime.md | 51 +- docs/commands/rx.md | 14 +- docs/commands/set.md | 16 +- docs/commands/signal.md | 6 +- docs/commands/source.md | 25 +- docs/commands/stdin.md | 16 +- docs/commands/struct-keys.md | 10 +- docs/commands/suffix.md | 18 +- docs/commands/summary.md | 26 +- docs/commands/switch.md | 4 +- docs/commands/ta.md | 18 +- docs/commands/tabulate.md | 4 +- docs/commands/test.md | 4 +- docs/commands/time.md | 8 +- docs/commands/tmp.md | 16 +- docs/commands/tout.md | 16 +- docs/commands/tread.md | 16 +- docs/commands/try.md | 4 +- docs/commands/tryerr.md | 4 +- docs/commands/trypipe.md | 4 +- docs/commands/trypipeerr.md | 4 +- docs/commands/type.md | 12 +- docs/commands/unsafe.md | 4 +- docs/commands/version.md | 22 +- docs/commands/which.md | 12 +- docs/commands/while.md | 12 +- docs/events/oncommandcompletion.md | 6 +- docs/events/onfilesystemchange.md | 4 +- docs/events/onkeypress.md | 4 +- docs/events/onpreview.md | 4 +- docs/events/onprompt.md | 4 +- docs/events/onsecondselapsed.md | 4 +- docs/integrations/chatgpt.md | 4 +- docs/integrations/cheatsh.md | 4 +- docs/integrations/direnv.md | 2 +- docs/integrations/iterm2.md | 4 +- docs/integrations/kitty.md | 6 +- docs/integrations/make.md | 4 +- docs/integrations/man-pages.md | 4 +- docs/integrations/spellcheck.md | 20 +- docs/integrations/terminology.md | 6 +- docs/integrations/yarn.md | 4 +- docs/mkarray/character.md | 12 +- docs/mkarray/date.md | 20 +- docs/mkarray/decimal.md | 12 +- docs/mkarray/non-decimal.md | 12 +- docs/mkarray/special.md | 20 +- docs/optional/README.md | 6 +- docs/optional/base64.md | 14 +- docs/optional/bz2.md | 14 +- docs/optional/gz.md | 10 +- docs/optional/qr.md | 2 +- docs/optional/select.md | 7 +- docs/optional/sleep.md | 8 +- docs/parser/README.md | 2 - docs/parser/add-with.md | 4 +- docs/parser/addition.md | 4 +- docs/parser/array.md | 8 +- docs/parser/assign-or-merge.md | 6 +- docs/parser/brace-quote-func.md | 16 +- docs/parser/brace-quote.md | 8 +- docs/parser/c-style-fun.md | 10 +- docs/parser/create-array.md | 6 +- docs/parser/curly-brace.md | 16 +- docs/parser/divide-by.md | 4 +- docs/parser/division.md | 4 +- docs/parser/double-quote.md | 8 +- docs/parser/element.md | 14 +- docs/parser/elvis.md | 8 +- docs/parser/equ.md | 14 +- docs/parser/expr-inlined.md | 4 +- docs/parser/file-append.md | 16 +- docs/parser/item-index.md | 14 +- docs/parser/lambda.md | 12 +- docs/parser/logical-and.md | 8 +- docs/parser/logical-or.md | 8 +- docs/parser/multiplication.md | 4 +- docs/parser/multiply-by.md | 4 +- docs/parser/null-coalescing.md | 8 +- docs/parser/pipe-arrow.md | 14 +- docs/parser/pipe-err.md | 14 +- docs/parser/pipe-generic.md | 4 +- docs/parser/pipe-posix.md | 10 +- docs/parser/range.md | 22 +- docs/parser/scalar.md | 8 +- docs/parser/single-quote.md | 8 +- docs/parser/subtract-by.md | 4 +- docs/parser/subtraction.md | 4 +- docs/parser/tilde.md | 8 +- docs/types/csv.md | 8 +- docs/types/generic.md | 8 +- docs/types/hcl.md | 12 +- docs/types/int.md | 8 +- docs/types/json.md | 12 +- docs/types/jsonc.md | 12 +- docs/types/jsonl.md | 12 +- docs/types/mxjson.md | 20 +- docs/types/num.md | 8 +- docs/types/str.md | 6 +- docs/types/toml.md | 8 +- docs/types/yaml.md | 6 +- docs/user-guide/README.md | 286 +++--- docs/user-guide/ansi.md | 8 +- docs/user-guide/bang-prefix.md | 6 +- docs/user-guide/fileref.md | 8 +- docs/user-guide/hint-text.md | 2 +- docs/user-guide/interactive-shell.md | 12 +- docs/user-guide/job-control.md | 18 +- docs/user-guide/modules.md | 8 +- docs/user-guide/namedpipes.md | 4 +- docs/user-guide/pipeline.md | 4 +- docs/user-guide/profile.md | 6 +- docs/user-guide/reserved-vars.md | 6 +- docs/user-guide/rosetta-stone.md | 4 +- docs/user-guide/scoping.md | 20 +- docs/user-guide/strict-types.md | 4 +- docs/variables/argv.md | 12 +- docs/variables/columns.md | 4 +- docs/variables/hostname.md | 4 +- docs/variables/murex_exe.md | 2 +- docs/variables/numeric.md | 12 +- docs/variables/params.md | 12 +- docs/variables/pwd.md | 4 +- docs/variables/pwdhist.md | 4 +- docs/variables/shell.md | 4 +- integrations/_namespaces_any.mx | 147 +-- version.svg | 2 +- 293 files changed, 2674 insertions(+), 2240 deletions(-) delete mode 100644 builtins/core/arraytools/struct.go delete mode 100644 builtins/core/datatools/struct.go diff --git a/builtins/core/arraytools/2darray_doc.yaml b/builtins/core/arraytools/2darray_doc.yaml index 7e7cfded2..7a36652aa 100644 --- a/builtins/core/arraytools/2darray_doc.yaml +++ b/builtins/core/arraytools/2darray_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: 2darray Title: >- - `2darray` + struct.new.2darray: `2darray` CategoryID: commands Summary: >- Create a 2D JSON array from multiple input sources @@ -87,7 +87,7 @@ `2darray` can have as many or as few code blocks as you wish. Synonyms: - 2darray - - struct.2darray + - struct.new.2darray Related: - prepend - append diff --git a/builtins/core/arraytools/addheading_doc.yaml b/builtins/core/arraytools/addheading_doc.yaml index 5fbd39065..0948d083f 100644 --- a/builtins/core/arraytools/addheading_doc.yaml +++ b/builtins/core/arraytools/addheading_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: addheading Title: >- - `addheading` + table.new.heading: `addheading` CategoryID: commands Summary: >- Adds headings to a table @@ -20,6 +20,8 @@ ``` Detail: Synonyms: + - addheading + - table.new.heading Related: - item-index - element diff --git a/builtins/core/arraytools/map_doc.yaml b/builtins/core/arraytools/map_doc.yaml index f0c09213b..079ca618a 100644 --- a/builtins/core/arraytools/map_doc.yaml +++ b/builtins/core/arraytools/map_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: map Title: >- - `map` + struct.new.map: `map` CategoryID: commands Summary: >- Creates a map from two data sources @@ -21,8 +21,10 @@ "key 3": "value 3" } ``` - Detail: |- + Detail: Synonyms: + - map + - struct.new.map Related: - prepend - append diff --git a/builtins/core/arraytools/struct.go b/builtins/core/arraytools/struct.go deleted file mode 100644 index 64181e7bf..000000000 --- a/builtins/core/arraytools/struct.go +++ /dev/null @@ -1,11 +0,0 @@ -package arraytools - -import "github.com/lmorg/murex/config/defaults" - -func init() { - defaults.AppendProfile(` - alias struct.new.2darray = 2darray - alias struct.new.heading = addheading - alias struct.new.map = map - `) -} diff --git a/builtins/core/autocomplete/autocomplete_doc.yaml b/builtins/core/autocomplete/autocomplete_doc.yaml index aeb927691..dd1c5bae0 100644 --- a/builtins/core/autocomplete/autocomplete_doc.yaml +++ b/builtins/core/autocomplete/autocomplete_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: "autocomplete" Title: >+ - `autocomplete` + shell.autocomplete: `autocomplete` CategoryID: commands Summary: >- Set definitions for tab-completion in the command line @@ -27,6 +27,8 @@ get: output all autocompletion schemas set: define a new autocompletion schema Synonyms: + - autocomplete + - shell.autocomplete Related: - config - private diff --git a/builtins/core/config/config_doc.yaml b/builtins/core/config/config_doc.yaml index 6785fd60f..09ba00816 100644 --- a/builtins/core/config/config_doc.yaml +++ b/builtins/core/config/config_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: config Title: >+ - `config` + shell.config: `config` CategoryID: commands Summary: >- Query or define Murex runtime settings @@ -115,6 +115,8 @@ Synonyms: - config - "!config" + - shell.config + - "!shell.config" Related: - runtime - open diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index 294fb98fa..a37608145 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: alter Title: >+ - `alter` + struct.alter: `alter` CategoryID: commands Summary: >- Change a value within a structured data-type and pass that change along the @@ -169,13 +169,14 @@ Synonyms: - alter - "~>" + - struct.alter Related: - - item-index - - element - - format - - append - - prepend - - runtime - - cast - - config - - assign-or-merge \ No newline at end of file + - item-index + - element + - format + - append + - prepend + - runtime + - cast + - config + - assign-or-merge \ No newline at end of file diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index fe1763131..ee7aa7767 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -1,11 +1,15 @@ - DocumentID: count Title: >+ - `count` + struct.count: `count` CategoryID: commands Summary: >- Count items in a map, list or array Description: |- + Counts the number of items in a structure, be that a list, map or other object + type. + `count` has several modes ranging from updating values in place, returning new + structures, or just outputting totals. Usage: |- ``` -> count [ --duplications | --unique | --total ] -> @@ -128,7 +132,7 @@ Synonyms: - count - len - - list.count + - struct.count Related: - prepend - append diff --git a/builtins/core/datatools/struct.go b/builtins/core/datatools/struct.go deleted file mode 100644 index 4353247b4..000000000 --- a/builtins/core/datatools/struct.go +++ /dev/null @@ -1,11 +0,0 @@ -package datatools - -import "github.com/lmorg/murex/config/defaults" - -func init() { - defaults.AppendProfile(` - alias struct.alter = alter - alias struct.count = count - alias struct.keys = struct-keys - `) -} diff --git a/builtins/core/datatools/structkeys_doc.yaml b/builtins/core/datatools/structkeys_doc.yaml index e7540420a..77d347b0c 100644 --- a/builtins/core/datatools/structkeys_doc.yaml +++ b/builtins/core/datatools/structkeys_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: struct-keys Title: >+ - `struct-keys` + struct.keys: `struct-keys` CategoryID: commands Summary: >- Outputs all the keys in a structure as a file path @@ -148,6 +148,8 @@ "-s" : Alias for `--separator` Detail: Synonyms: + - struct-keys + - struct.keys Related: - set - item-index diff --git a/builtins/core/escape/escape_doc.yaml b/builtins/core/escape/escape_doc.yaml index f484eba3e..568b8b19c 100644 --- a/builtins/core/escape/escape_doc.yaml +++ b/builtins/core/escape/escape_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: escape Title: >+ - `escape` + escape.quote: `escape` CategoryID: commands Summary: >- Escape or unescape input @@ -51,7 +51,7 @@ - DocumentID: eschtml Title: >+ - `eschtml` + escape.html: `eschtml` CategoryID: commands Summary: >- Encode or decodes text for HTML @@ -110,7 +110,7 @@ - DocumentID: escurl Title: >+ - `escurl` + escape.url: `escurl` CategoryID: commands Summary: >- Encode or decodes text for the URL @@ -169,7 +169,7 @@ - DocumentID: esccli Title: >+ - `esccli` + escape.cli: `esccli` CategoryID: commands Summary: >- Escapes an array so output is valid shell code diff --git a/builtins/core/io/echo_doc.yaml b/builtins/core/io/echo_doc.yaml index 715c83c51..ad393070d 100644 --- a/builtins/core/io/echo_doc.yaml +++ b/builtins/core/io/echo_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: out Title: >+ - `out` + io.out: `out` CategoryID: commands Summary: >- Print a string to the stdout with a trailing new line character @@ -35,6 +35,7 @@ `out` supports ANSI constants. Synonyms: - out + - io.out - echo Related: - tout @@ -52,7 +53,7 @@ - DocumentID: tout Title: >+ - `tout` + io.out.type: `tout` CategoryID: commands Summary: >- Print a string to the stdout and set it's data-type @@ -76,6 +77,8 @@ Unlike `out`, `tout` does not append a carriage return / line feed. Synonyms: + - tout + - io.out.type Related: - out - err @@ -141,7 +144,7 @@ - DocumentID: err Title: >+ - `err` + io.err: `err` CategoryID: commands Summary: >- Print a line to the stderr @@ -185,6 +188,8 @@ `err` supports ANSI constants. Synonyms: + - err + - io.err Related: - tout - out diff --git a/builtins/core/io/f_doc.yaml b/builtins/core/io/f_doc.yaml index e650bca67..42d50fbca 100644 --- a/builtins/core/io/f_doc.yaml +++ b/builtins/core/io/f_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: f Title: >+ - `f` + fs.files: `f` CategoryID: commands Summary: >- Lists or filters file system objects (eg files) @@ -82,6 +82,8 @@ `+` flags are always matched first. Then the `-` flags are used to filter out any matches from the `+` flags. Synonyms: + - f + - fs.files Related: - g - rx diff --git a/builtins/core/io/file_doc.yaml b/builtins/core/io/file_doc.yaml index 16920f691..9c89a0a08 100644 --- a/builtins/core/io/file_doc.yaml +++ b/builtins/core/io/file_doc.yaml @@ -1,7 +1,7 @@ - DocumentID: file-truncate Title: >+ - `|>` Truncate File - CategoryID: parser + fs.truncate: `>` + CategoryID: command Summary: >- Writes stdin to disk - overwriting contents if file already exists Description: |- @@ -19,8 +19,9 @@ ``` Detail: Synonyms: - - "|>" - ">" + - fs.truncate + - "|>" - "fwrite" Related: - file-append @@ -36,7 +37,7 @@ - DocumentID: pt Title: >+ - `pt` + fs.status: `pt` CategoryID: commands Summary: >- Pipe telemetry. Writes data-types and bytes written @@ -56,6 +57,8 @@ `getfile`) Detail: Synonyms: + - pt + - fs.status Related: - file-truncate - file-append diff --git a/builtins/core/io/g_doc.yaml b/builtins/core/io/g_doc.yaml index 1d81063ef..ea6574933 100644 --- a/builtins/core/io/g_doc.yaml +++ b/builtins/core/io/g_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: g Title: >+ - `g` + fs.glob: `g` CategoryID: commands Summary: >- Glob pattern matching for file system objects (eg `*.txt`) @@ -125,6 +125,8 @@ Synonyms: - g - "!g" + - fs.glob + - "!fs.glob" Related: - rx - f diff --git a/builtins/core/io/lockfile_doc.yaml b/builtins/core/io/lockfile_doc.yaml index df9ee0186..5aa7c91db 100644 --- a/builtins/core/io/lockfile_doc.yaml +++ b/builtins/core/io/lockfile_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: lockfile Title: >+ - `lockfile` + fs.lockfile: `lockfile` CategoryID: commands Summary: >- Create and manage lock files @@ -44,8 +44,10 @@ lockfile wait example out "lock file gone!" ``` - Detail: |- + Detail: Synonyms: + - lockfile + - fs.lockfile Related: - out - bg diff --git a/builtins/core/io/read_doc.yaml b/builtins/core/io/read_doc.yaml index d343d0215..3a6353cbc 100644 --- a/builtins/core/io/read_doc.yaml +++ b/builtins/core/io/read_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: read Title: >+ - `read` + io.input: `read` CategoryID: commands Summary: >- `read` a line of input from the user and store as a variable @@ -73,15 +73,17 @@ --autocomplete: "Autocompletion suggestions. Can be either a JSON array or a JSON object" --mask: "Optional password mask, for reading secrets" Synonyms: + - read + - io.input Related: - - tout - - err - - brace-quote - - cast - - file-truncate - - file-append - - out - - tread + - tout + - err + - brace-quote + - cast + - file-truncate + - file-append + - out + - tread diff --git a/builtins/core/io/rx_doc.yaml b/builtins/core/io/rx_doc.yaml index 01efa5e74..7e7ebe947 100644 --- a/builtins/core/io/rx_doc.yaml +++ b/builtins/core/io/rx_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: rx Title: >+ - `rx` + fs.regex: `rx` CategoryID: commands Summary: >- Regexp pattern matching for file system objects (eg `.*\\.txt`) @@ -107,6 +107,8 @@ Synonyms: - rx - "!rx" + - fs.regex + - "!fs.regex" Related: - g - f diff --git a/builtins/core/io/tmp_doc.yaml b/builtins/core/io/tmp_doc.yaml index df5a88b5f..74b3afa42 100644 --- a/builtins/core/io/tmp_doc.yaml +++ b/builtins/core/io/tmp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: tmp Title: >+ - `tmp` + fs.new.tmpfile: `tmp` CategoryID: commands Summary: >- Create a temporary file and write to it @@ -40,6 +40,8 @@ which itself is located in the appropriate temp directory for the host OS (eg `$TMPDIR` on macOS). Synonyms: + - tmp + - fs.new.tmpfile Related: - open - file-truncate diff --git a/builtins/core/lists/append_doc.yaml b/builtins/core/lists/append_doc.yaml index 391feaa98..d14543ff2 100644 --- a/builtins/core/lists/append_doc.yaml +++ b/builtins/core/lists/append_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: prepend Title: >- - `prepend` + list.prepend: `prepend` CategoryID: commands Summary: >- Add data to the start of an array @@ -55,7 +55,7 @@ - DocumentID: append Title: >+ - `append` + list.append: `append` CategoryID: commands Summary: >- Add data to the end of an array diff --git a/builtins/core/lists/case_doc.yaml b/builtins/core/lists/case_doc.yaml index 38d44f299..74d52d2c9 100644 --- a/builtins/core/lists/case_doc.yaml +++ b/builtins/core/lists/case_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: list.case Title: >- - `list.case` + list.case: `list.case` CategoryID: commands Summary: >- Changes the character case of a string or all elements in an array @@ -38,7 +38,7 @@ "friday" ] ``` - Detail: + Detail: Synonyms: - list.case Related: diff --git a/builtins/core/lists/jsplit_doc.yaml b/builtins/core/lists/jsplit_doc.yaml index 63c984ffc..b806bfd52 100644 --- a/builtins/core/lists/jsplit_doc.yaml +++ b/builtins/core/lists/jsplit_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: jsplit Title: >- - `jsplit` + str.split: `jsplit` CategoryID: commands Summary: >- Splits stdin into a JSON array based on a regex parameter @@ -32,7 +32,7 @@ Synonyms: - jsplit - - list.split + - str.split Related: - prepend - append diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml index 88f6a066a..98bdaec09 100644 --- a/builtins/core/lists/mjoin_doc.yaml +++ b/builtins/core/lists/mjoin_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mjoin Title: >- - `mjoin` + list.join: `mjoin` CategoryID: commands Summary: >- Joins a list or array into a single string diff --git a/builtins/core/lists/msort_doc.yaml b/builtins/core/lists/msort_doc.yaml index 33c199e40..d2e956936 100644 --- a/builtins/core/lists/msort_doc.yaml +++ b/builtins/core/lists/msort_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: msort Title: >- - `msort` + list.sort: `msort` CategoryID: commands Summary: >- Sorts an array - data type agnostic @@ -42,7 +42,7 @@ "a" ] ``` - Detail: |- + Detail: Synonyms: - msort - list.sort diff --git a/builtins/core/lists/mtac_doc.yaml b/builtins/core/lists/mtac_doc.yaml index d4586ae52..ec15d82c2 100644 --- a/builtins/core/lists/mtac_doc.yaml +++ b/builtins/core/lists/mtac_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mtac Title: >+ - `mtac` + list.reverse: `mtac` CategoryID: commands Summary: >- Reverse the order of an array diff --git a/builtins/core/lists/push_pop_doc.yaml b/builtins/core/lists/push_pop_doc.yaml index a68ab423e..8a247ffad 100644 --- a/builtins/core/lists/push_pop_doc.yaml +++ b/builtins/core/lists/push_pop_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: left Title: >+ - `left` + list.left: `left` CategoryID: commands Summary: >- Left substring every item in a list @@ -61,7 +61,7 @@ - DocumentID: right Title: >+ - `right` + list.right: `right` CategoryID: commands Summary: >- Right substring every item in a list @@ -122,7 +122,7 @@ - DocumentID: prefix Title: >+ - `prefix` + list.prefix: `prefix` CategoryID: commands Summary: >- Prefix a string to every item in a list @@ -167,7 +167,7 @@ - DocumentID: suffix Title: >+ - `suffix` + list.suffix: `suffix` CategoryID: commands Summary: >- Prefix a string to every item in a list diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index 4d6c9e2f3..5b023b147 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: match Title: >+ - `match` + list.str: `match` CategoryID: commands Summary: >- Match an exact value in an array @@ -64,8 +64,8 @@ Synonyms: - match - "!match" - - list.string - - "!list.string" + - list.str + - "!list.str" Related: - a - ja @@ -86,7 +86,7 @@ - DocumentID: regexp Title: >+ - `regexp` + list.regex: `regexp` CategoryID: commands Summary: >- Regexp tools for arrays / lists of strings diff --git a/builtins/core/management/debug_doc.yaml b/builtins/core/management/debug_doc.yaml index 09ead5d51..27662eae6 100644 --- a/builtins/core/management/debug_doc.yaml +++ b/builtins/core/management/debug_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: debug Title: >+ - `debug` + shell.debug: `debug` CategoryID: commands Summary: >- Debugging information @@ -184,6 +184,8 @@ debug panic ``` Synonyms: + - debug + - shell.debug Related: - runtime - test \ No newline at end of file diff --git a/builtins/core/management/fexec_doc.yaml b/builtins/core/management/fexec_doc.yaml index a013d14e9..c1e18b60c 100644 --- a/builtins/core/management/fexec_doc.yaml +++ b/builtins/core/management/fexec_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fexec Title: >+ - `fexec` + exec.*: `fexec` CategoryID: commands Summary: >- Execute a command or function, bypassing the usual order of precedence. @@ -36,6 +36,9 @@ Synonyms: - fexec - builtin + - exec.builtin + - exec.function + - exec.private Related: - function - private diff --git a/builtins/core/management/functions_doc.yaml b/builtins/core/management/functions_doc.yaml index c8880be4d..19aa5d45b 100644 --- a/builtins/core/management/functions_doc.yaml +++ b/builtins/core/management/functions_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: exitnum Title: >+ - `exitnum` + proc.exitnum: `exitnum` CategoryID: commands Summary: >- Output the exit number of the previous process @@ -16,8 +16,10 @@ 0 ``` Flags: - Detail: |- + Detail: Synonyms: + - exitnum + - proc.exitnum Related: - runtime - test @@ -26,7 +28,7 @@ - DocumentID: murex-update-exe-list Title: >+ - `murex-update-exe-list` + shell.rescan.path: `murex-update-exe-list` CategoryID: commands Summary: >- Forces Murex to rescan $PATH looking for executables @@ -48,6 +50,8 @@ Murex will automatically update the exe list each time tab completion is invoked for command name completion via the REPL shell. Synonyms: + - murex-update-exe-list + - shell.rescan.path Related: - os - cpuarch @@ -57,7 +61,7 @@ - DocumentID: man-summary Title: >+ - `man-summary` + help.man.summary: `man-summary` CategoryID: commands Summary: >- Outputs a man page summary of a command @@ -91,6 +95,8 @@ 2 ``` Synonyms: + - man-summary + - help.man.summary Related: - summary - config @@ -182,7 +188,7 @@ - DocumentID: bexists Title: >+ - `bexists` + shell.builtins.exist: `bexists` CategoryID: commands Summary: >- Check which builtins exist @@ -216,6 +222,7 @@ might also happen to `bexists` however it is in use by a few modules and for that reason alone it has been spared from the axe. Synonyms: + - bexists Related: - runtime - fexec diff --git a/builtins/core/management/history_doc.yaml b/builtins/core/management/history_doc.yaml index 8be5282ac..6b52212df 100644 --- a/builtins/core/management/history_doc.yaml +++ b/builtins/core/management/history_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: history Title: >+ - `history` + shell.history: `history` CategoryID: commands Summary: >- Outputs murex's command history @@ -35,6 +35,8 @@ Detail: |- The history file is typically located on disk in a file called `~/.murex.history`. Synonyms: + - history + - shell.history Related: - config - runtime diff --git a/builtins/core/management/shell_doc.yaml b/builtins/core/management/shell_doc.yaml index b85b50766..73b26470c 100644 --- a/builtins/core/management/shell_doc.yaml +++ b/builtins/core/management/shell_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: summary Title: >+ - `summary` + shell.summary: `summary` CategoryID: commands Summary: >- Defines a summary help text for a command @@ -43,6 +43,8 @@ Synonyms: - summary - "!summary" + - shell.summary + - "!shell.summary" Related: - config - runtime @@ -117,7 +119,7 @@ - DocumentID: man-get-flags Title: >+ - `man-get-flags` + help.man.flags: `man-get-flags` CategoryID: commands Summary: >- Parses man page files for command line flags @@ -162,6 +164,8 @@ a margin for error with how reliably any parser can autodetect parameters. one requirement is that flags are hyphen prefixed, eg `--flag`. Synonyms: + - man-get-flags + - help.man.flags Related: - murex-docs - summary diff --git a/builtins/core/management/source_doc.yaml b/builtins/core/management/source_doc.yaml index 31ad860cf..2c4878523 100644 --- a/builtins/core/management/source_doc.yaml +++ b/builtins/core/management/source_doc.yaml @@ -1,9 +1,9 @@ - DocumentID: source Title: >+ - `source` + exec.include: `source` CategoryID: commands Summary: >- - Import Murex code from another file of code block + Import Murex code from another file or code block Description: |- `source` imports code from another file or code block. It can be used as either an "import" / "include" directive (eg Python, Go, C, etc) or an "eval" (eg @@ -54,6 +54,7 @@ Synonyms: - source - "." + - exec.include Related: - config - runtime diff --git a/builtins/core/management/version_doc.yaml b/builtins/core/management/version_doc.yaml index d9a4a41c7..252fc087e 100644 --- a/builtins/core/management/version_doc.yaml +++ b/builtins/core/management/version_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: version Title: >+ - `version` + shell.version: `version` CategoryID: commands Summary: >- Get Murex version @@ -38,6 +38,8 @@ Returns full version string minus app name Detail: Synonyms: + - version + - shell.version Related: - config - runtime diff --git a/builtins/core/mkarray/array_doc.yaml b/builtins/core/mkarray/array_doc.yaml index 21dcf8f54..0dd0b003d 100644 --- a/builtins/core/mkarray/array_doc.yaml +++ b/builtins/core/mkarray/array_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: a Title: >+ - `a` (mkarray) + list.new.str: `a` (mkarray) CategoryID: commands Summary: >- A sophisticated yet simple way to build an array or list @@ -129,6 +129,9 @@ {{ include "gen/includes/autogenerated.mkarray.inc.md" }} Synonyms: + - a + - mkarray + - list.new.str Related: - create-array - range @@ -208,7 +211,7 @@ - DocumentID: ta Title: >+ - `ta` (mkarray) + list.new.type: `ta` CategoryID: commands Summary: >- A sophisticated yet simple way to build an array of a user defined data-type @@ -256,6 +259,8 @@ Please read the documentation on `a` for a more detailed breakdown on of `ta`'s supported features. Synonyms: + - ta + - list.new.type Related: - create-array - range diff --git a/builtins/core/modules/murex-package_doc.yaml b/builtins/core/modules/murex-package_doc.yaml index ecad49592..63435fa39 100644 --- a/builtins/core/modules/murex-package_doc.yaml +++ b/builtins/core/modules/murex-package_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: murex-package Title: >+ - `murex-package` + shell.packages: `murex-package` CategoryID: commands Summary: >- Murex's package manager @@ -90,6 +90,8 @@ `murex-package list loaded` instead. This is also equivalent to using `runtime --modules`. Synonyms: + - murex.package + - shell.packages Related: - runtime - config diff --git a/builtins/core/open/open_doc.yaml b/builtins/core/open/open_doc.yaml index 1680a2a2f..39fc26a54 100644 --- a/builtins/core/open/open_doc.yaml +++ b/builtins/core/open/open_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open Title: >+ - `open` + fs.open: `open` CategoryID: commands Summary: >- Open a file with a preferred handler @@ -155,6 +155,8 @@ exec open --flags filename ``` Synonyms: + - open + - fs.open Related: - openagent - fexec @@ -170,7 +172,7 @@ - DocumentID: openagent Title: >+ - `openagent` + shell.open: `openagent` CategoryID: commands Summary: >- Creates a handler function for `open` @@ -205,6 +207,8 @@ Synonyms: - openagent - "!openagent" + - shell.open + - "!shell.open" Related: - open - fexec diff --git a/builtins/core/openimage/open-image_doc.yaml b/builtins/core/openimage/open-image_doc.yaml index 0d31d8d97..32294855a 100644 --- a/builtins/core/openimage/open-image_doc.yaml +++ b/builtins/core/openimage/open-image_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open-image Title: >- - `open-image` + fs.open.image: `open-image` CategoryID: commands Summary: >- Renders bitmap image data on your terminal @@ -29,6 +29,8 @@ Detail: |- `open-image` will fail if stdout is not a TTY. Synonyms: + - open-image + - fs.open.image Related: - qr - open diff --git a/builtins/core/pipe/namedpipe_doc.yaml b/builtins/core/pipe/namedpipe_doc.yaml index 185949fc0..1333ecc7a 100644 --- a/builtins/core/pipe/namedpipe_doc.yaml +++ b/builtins/core/pipe/namedpipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: namedpipe Title: >+ - `` Read Named Pipe + io.pipe: `` Read Named Pipe CategoryID: commands Summary: >- Reads from a Murex named pipe @@ -39,6 +39,7 @@ - "(murex named pipe)" - "<>" - read-named-pipe + - io.pipe Related: - pipe - stdin diff --git a/builtins/core/pipe/pipe_doc.yaml b/builtins/core/pipe/pipe_doc.yaml index c8b9ce696..5173e4f81 100644 --- a/builtins/core/pipe/pipe_doc.yaml +++ b/builtins/core/pipe/pipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pipe Title: >+ - `pipe` + io.new.pipe: `pipe` CategoryID: commands Summary: >- Manage Murex named pipes @@ -46,6 +46,8 @@ Synonyms: - pipe - "!pipe" + - io.new.pipe + - "!io.new.pipe" Related: - namedpipe - stdin diff --git a/builtins/core/pretty/pretty_doc.yaml b/builtins/core/pretty/pretty_doc.yaml index cf147c787..a9ab8f5b6 100644 --- a/builtins/core/pretty/pretty_doc.yaml +++ b/builtins/core/pretty/pretty_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pretty Title: >+ - `pretty` + struct.json.pretty: `pretty` CategoryID: commands Summary: >- Prettifies JSON to make it human readable @@ -27,8 +27,10 @@ } ``` Flags: - Detail: |- + Detail: Synonyms: + - pretty + - struct.json.pretty Related: - tout - out diff --git a/builtins/core/processes/bgfg_doc.yaml b/builtins/core/processes/bgfg_doc.yaml index 85cbfd757..cbbc35827 100644 --- a/builtins/core/processes/bgfg_doc.yaml +++ b/builtins/core/processes/bgfg_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: bg Title: >+ - `bg` + proc.bg: `bg` CategoryID: commands Summary: >- Run processes in the background @@ -30,6 +30,8 @@ non-platforms. This means the usage described in the examples is cross cross platform while `bg int` currently does not work on Windows nor Plan 9. Synonyms: + - bg + - proc.bg Related: - fid-list - fid-kill @@ -42,7 +44,7 @@ - DocumentID: fg Title: >+ - `fg` + proc.fg: `fg` CategoryID: commands Summary: >- Sends a background process into the foreground @@ -54,12 +56,14 @@ ``` fg fid ``` - Examples: |- + Examples: Flags: Detail: |- This builtin is only supported on POSIX systems. There is no support planned for Windows (due to the kernel not supporting the right signals) nor Plan 9. Synonyms: + - fg + - proc.fg Related: - fid-list - fid-kill diff --git a/builtins/core/processes/fid-list_doc.yaml b/builtins/core/processes/fid-list_doc.yaml index 0931704d3..dc621e9d1 100644 --- a/builtins/core/processes/fid-list_doc.yaml +++ b/builtins/core/processes/fid-list_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-list Title: >+ - `fid-list` + proc.list: `fid-list` CategoryID: commands Summary: >- Lists all running functions within the current Murex session @@ -54,6 +54,8 @@ Synonyms: - fid-list - jobs + - proc.list + - proc.jobs Related: - fid-kill - fid-killall diff --git a/builtins/core/processes/kill_doc.yaml b/builtins/core/processes/kill_doc.yaml index fbff51451..4750562b2 100644 --- a/builtins/core/processes/kill_doc.yaml +++ b/builtins/core/processes/kill_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-kill Title: >+ - `fid-kill` + proc.kill: `fid-kill` CategoryID: commands Summary: >- Terminate a running Murex function @@ -16,6 +16,8 @@ Detail: |- {{ include "gen/includes/fid-kill.inc.md" }} Synonyms: + - fid-kill + - proc.kill Related: - fid-list - fid-killall @@ -32,7 +34,7 @@ - DocumentID: fid-killall Title: >+ - `fid-killall` + proc.kill.all: `fid-killall` CategoryID: commands Summary: >- Terminate _all_ running Murex functions @@ -49,6 +51,8 @@ {{ include "gen/includes/fid-kill.inc.md" }} Synonyms: + - fid.killall + - proc.kill.all Related: - fid-list - fid-kill diff --git a/builtins/core/runtime/runtime_doc.yaml b/builtins/core/runtime/runtime_doc.yaml index b2e9769b0..634d0cc07 100644 --- a/builtins/core/runtime/runtime_doc.yaml +++ b/builtins/core/runtime/runtime_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: runtime Title: >+ - `runtime` + shell.runtime: `runtime` CategoryID: commands Summary: >- Returns runtime information on the internal state of Murex @@ -286,6 +286,7 @@ Synonyms: - runtime - builtins + - shell.runtime Related: - set - let diff --git a/builtins/core/system/system.go b/builtins/core/system/system.go index f248a3bad..59a06cb7e 100644 --- a/builtins/core/system/system.go +++ b/builtins/core/system/system.go @@ -4,7 +4,6 @@ import ( "runtime" "strconv" - "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/posix" @@ -14,12 +13,6 @@ func init() { lang.DefineFunction("os", cmdOs, types.String) lang.DefineFunction("cpuarch", cmdCpuArch, types.String) lang.DefineFunction("cpucount", cmdCpuCount, types.Integer) - - defaults.AppendProfile(` - alias sys.os = os - alias sys.cpu.arch = cpuarch - alias sys.cpu.count = cpucount - `) } func cmdOs(p *lang.Process) error { diff --git a/builtins/core/system/system_doc.yaml b/builtins/core/system/system_doc.yaml index 21a1c85f9..ada0d39fb 100644 --- a/builtins/core/system/system_doc.yaml +++ b/builtins/core/system/system_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: os Title: >+ - `os` + sys.os: `os` CategoryID: commands Summary: >- Output the auto-detected OS name @@ -78,7 +78,7 @@ - DocumentID: cpuarch Title: >+ - `cpuarch` + sys.cpu.arch: `cpuarch` CategoryID: commands Summary: >- Output the hosts CPU architecture @@ -106,7 +106,7 @@ - DocumentID: cpucount Title: >+ - `cpucount` + sys.cpu.count: `cpucount` CategoryID: commands Summary: >- Output the number of CPU cores available on your host @@ -122,7 +122,7 @@ 4 ``` Flags: - Detail: |- + Detail: Synonyms: - cpucount - sys.cpu.count diff --git a/builtins/core/typemgmt/datetime_doc.yaml b/builtins/core/typemgmt/datetime_doc.yaml index 235285b91..0aa3704c3 100644 --- a/builtins/core/typemgmt/datetime_doc.yaml +++ b/builtins/core/typemgmt/datetime_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: datetime Title: >+ - `datetime` + str.datetime: `datetime` CategoryID: commands Summary: >- A date and/or time conversion tool (like `printf` but for date and time values) @@ -73,6 +73,8 @@ This is only supported as an input. When it is used `--value` flag is not required. Synonyms: + - datetime + - str.datetime Related: - range - a diff --git a/builtins/core/typemgmt/round_doc.yaml b/builtins/core/typemgmt/round_doc.yaml index d82533a43..1d16959f3 100644 --- a/builtins/core/typemgmt/round_doc.yaml +++ b/builtins/core/typemgmt/round_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: round Title: >+ - `round` + num.round: `round` CategoryID: commands Summary: >- Round a number by a user defined precision @@ -65,5 +65,7 @@ "-u": "shorthand for `--up`" Detail: Synonyms: + - round + - num.round Related: - expr diff --git a/builtins/core/typemgmt/types_doc.yaml b/builtins/core/typemgmt/types_doc.yaml index a4e66e7ba..2a7c725bc 100644 --- a/builtins/core/typemgmt/types_doc.yaml +++ b/builtins/core/typemgmt/types_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: exec Title: >+ - `exec` + exec.file: `exec` CategoryID: commands Summary: >- Runs an executable @@ -64,6 +64,7 @@ Synonyms: - exec - command + - exec.file Related: - fexec - set diff --git a/builtins/core/typemgmt/variables_doc.yaml b/builtins/core/typemgmt/variables_doc.yaml index 88084f899..798c60fcc 100644 --- a/builtins/core/typemgmt/variables_doc.yaml +++ b/builtins/core/typemgmt/variables_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: set Title: >+ - `set` + var.set: `set` CategoryID: commands Summary: >- Define a local variable and set it's value @@ -53,6 +53,8 @@ Synonyms: - set - "!set" + - var.set + - "!var.set" Related: - is-null - null-coalescing @@ -69,7 +71,7 @@ - DocumentID: global Title: >+ - `global` + var.global: `global` CategoryID: commands Summary: >- Define a global variable and set it's value @@ -123,6 +125,8 @@ Synonyms: - global - "!global" + - var.global + - "!var.global" Related: - set - is-null @@ -138,7 +142,7 @@ - DocumentID: export Title: >+ - `export` + var.env: `export` CategoryID: commands Summary: >- Define an environmental variable and set it's value @@ -208,6 +212,8 @@ - export - "!export" - unset + - var.env + - "!var.env" Related: - set - is-null diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 4a21c8529..c035fad28 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -7,117 +7,48 @@ func init() { Summary = map[string]string{ "not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "2darray": "Create a 2D JSON array from multiple input sources", - "namedpipe": "Reads from a Murex named pipe", "stdin": "Read the stdin belonging to the parent code block", - "a": "A sophisticated yet simple way to build an array or list", - "addheading": "Adds headings to a table", "alias": "Create an alias for a command", - "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", "and": "Returns `true` or `false` depending on whether multiple conditions are met", - "append": "Add data to the end of an array", "args": "Command line flag parser for Murex shell scripting", - "autocomplete": "Set definitions for tab-completion in the command line", - "bexists": "Check which builtins exist", - "bg": "Run processes in the background", "break": "Terminate execution of a block within your processes scope", "cast": "Alters the data-type of the previous function without altering its output", "catch": "Handles the exception code raised by `try` or `trypipe`", "cd": "Change (working) directory", - "config": "Query or define Murex runtime settings", "continue": "Terminate process of a block within a caller function", - "count": "Count items in a map, list or array", - "cpuarch": "Output the hosts CPU architecture", - "cpucount": "Output the number of CPU cores available on your host", - "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "debug": "Debugging information", "die": "Terminate murex with an exit number of 1 (deprecated)", - "err": "Print a line to the stderr", - "escape": "Escape or unescape input", - "esccli": "Escapes an array so output is valid shell code", - "eschtml": "Encode or decodes text for HTML", - "escurl": "Encode or decodes text for the URL", "event": "Event driven programming for shell scripts", - "exec": "Runs an executable", "exit": "Exit murex", - "exitnum": "Output the exit number of the previous process", - "export": "Define an environmental variable and set it's value", "expr": "Expressions: mathematical, string comparisons, logical operators", - "f": "Lists or filters file system objects (eg files)", "false": "Returns a `false` value", - "fexec": "Execute a command or function, bypassing the usual order of precedence.", - "fg": "Sends a background process into the foreground", - "fid-kill": "Terminate a running Murex function", - "fid-killall": "Terminate _all_ running Murex functions", - "fid-list": "Lists all running functions within the current Murex session", "for": "A more familiar iteration loop to existing developers", "foreach": "Iterate through an array", "formap": "Iterate through a map or other collection of data", "format": "Reformat one data-type into another data-type", "function": "Define a function block", - "g": "Glob pattern matching for file system objects (eg `*.txt`)", "get-type": "Returns the data-type of a variable or pipe", "get": "Makes a standard HTTP request and returns the result as a JSON object", "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "global": "Define a global variable and set it's value", - "history": "Outputs murex's command history", "if": "Conditional statement to execute different blocks of code depending on the result of the condition", "is-null": "Checks if a variable is null or undefined", "ja": "A sophisticated yet simply way to build a JSON array", - "jsplit": "Splits stdin into a JSON array based on a regex parameter", "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "left": "Left substring every item in a list", "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "list.case": "Changes the character case of a string or all elements in an array", - "lockfile": "Create and manage lock files", - "man-get-flags": "Parses man page files for command line flags", - "man-summary": "Outputs a man page summary of a command", - "map": "Creates a map from two data sources", - "match": "Match an exact value in an array", "method": "Define a methods supported data-types", - "mjoin": "Joins a list or array into a single string", - "msort": "Sorts an array - data type agnostic", - "mtac": "Reverse the order of an array", "murex-docs": "Displays the man pages for Murex builtins", - "murex-package": "Murex's package manager", "murex-parser": "Runs the Murex parser against a block of code", - "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "devnull": "null function. Similar to /dev/null", - "open-image": "Renders bitmap image data on your terminal", - "open": "Open a file with a preferred handler", - "openagent": "Creates a handler function for `open`", "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "os": "Output the auto-detected OS name", - "out": "Print a string to the stdout with a trailing new line character", - "pipe": "Manage Murex named pipes", "post": "HTTP POST request with a JSON-parsable return", - "prefix": "Prefix a string to every item in a list", - "prepend": "Add data to the start of an array", - "pretty": "Prettifies JSON to make it human readable", "private": "Define a private function block", - "pt": "Pipe telemetry. Writes data-types and bytes written", "rand": "Random field generator", - "read": "`read` a line of input from the user and store as a variable", - "regexp": "Regexp tools for arrays / lists of strings", "return": "Exits current function scope", - "right": "Right substring every item in a list", - "round": "Round a number by a user defined precision", "runmode": "Alter the scheduler's behaviour at higher scoping level", - "runtime": "Returns runtime information on the internal state of Murex", - "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "set": "Define a local variable and set it's value", "signal": "Sends a signal RPC", - "source": "Import Murex code from another file of code block", - "struct-keys": "Outputs all the keys in a structure as a file path", - "suffix": "Prefix a string to every item in a list", - "summary": "Defines a summary help text for a command", "switch": "Blocks of cascading conditionals", - "ta": "A sophisticated yet simple way to build an array of a user defined data-type", "tabulate": "Table transformation tools", "test": "Murex's test framework - define tests, run tests and debug shell scripts", "time": "Returns the execution run time of a command or block", - "tmp": "Create a temporary file and write to it", - "tout": "Print a string to the stdout and set it's data-type", "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", "true": "Returns a `true` value", "try": "Handles non-zero exits inside a block of code", @@ -126,129 +57,129 @@ func init() { "trypipeerr": "Checks state of each function in a pipeline and exits block on error", "type": "Command type (function, builtin, alias, etc)", "unsafe": "Execute a block of code, always returning a zero exit number", - "version": "Get Murex version", "which": "Locate command origin", "while": "Loop until condition false", + "esccli": "Escapes an array so output is valid shell code", + "eschtml": "Encode or decodes text for HTML", + "escape": "Escape or unescape input", + "escurl": "Encode or decodes text for the URL", + "fexec": "Execute a command or function, bypassing the usual order of precedence.", + "exec": "Runs an executable", + "source": "Import Murex code from another file or code block", + "f": "Lists or filters file system objects (eg files)", + "g": "Glob pattern matching for file system objects (eg `*.txt`)", + "lockfile": "Create and manage lock files", + "tmp": "Create a temporary file and write to it", + "open-image": "Renders bitmap image data on your terminal", + "open": "Open a file with a preferred handler", + "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "pt": "Pipe telemetry. Writes data-types and bytes written", + "man-get-flags": "Parses man page files for command line flags", + "man-summary": "Outputs a man page summary of a command", + "err": "Print a line to the stderr", + "read": "`read` a line of input from the user and store as a variable", + "pipe": "Manage Murex named pipes", + "tout": "Print a string to the stdout and set it's data-type", + "out": "Print a string to the stdout with a trailing new line character", + "namedpipe": "Reads from a Murex named pipe", + "append": "Add data to the end of an array", + "list.case": "Changes the character case of a string or all elements in an array", + "mjoin": "Joins a list or array into a single string", + "left": "Left substring every item in a list", + "a": "A sophisticated yet simple way to build an array or list", + "ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "prefix": "Prefix a string to every item in a list", + "prepend": "Add data to the start of an array", + "regexp": "Regexp tools for arrays / lists of strings", + "mtac": "Reverse the order of an array", + "right": "Right substring every item in a list", + "msort": "Sorts an array - data type agnostic", + "match": "Match an exact value in an array", + "suffix": "Prefix a string to every item in a list", + "round": "Round a number by a user defined precision", + "bg": "Run processes in the background", + "exitnum": "Output the exit number of the previous process", + "fg": "Sends a background process into the foreground", + "fid-killall": "Terminate _all_ running Murex functions", + "fid-kill": "Terminate a running Murex function", + "fid-list": "Lists all running functions within the current Murex session", + "autocomplete": "Set definitions for tab-completion in the command line", + "bexists": "Check which builtins exist", + "config": "Query or define Murex runtime settings", + "debug": "Debugging information", + "history": "Outputs murex's command history", + "openagent": "Creates a handler function for `open`", + "murex-package": "Murex's package manager", + "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "runtime": "Returns runtime information on the internal state of Murex", + "summary": "Defines a summary help text for a command", + "version": "Get Murex version", + "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "jsplit": "Splits stdin into a JSON array based on a regex parameter", + "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "count": "Count items in a map, list or array", + "pretty": "Prettifies JSON to make it human readable", + "struct-keys": "Outputs all the keys in a structure as a file path", + "2darray": "Create a 2D JSON array from multiple input sources", + "map": "Creates a map from two data sources", + "cpuarch": "Output the hosts CPU architecture", + "cpucount": "Output the number of CPU cores available on your host", + "os": "Output the auto-detected OS name", + "addheading": "Adds headings to a table", + "export": "Define an environmental variable and set it's value", + "global": "Define a global variable and set it's value", + "set": "Define a local variable and set it's value", "bz2": "Decompress a bz2 file", "base64": "Encode or decode a base64 string", "gz": "Compress or decompress a gzip file", "qr": "Creates a QR code from stdin", - "select": "Inlining SQL into shell pipelines", "sleep": "Suspends the shell for a number of seconds", + "select": "Inlining SQL into shell pipelines", "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "commands/2darray": "Create a 2D JSON array from multiple input sources", - "commands/namedpipe": "Reads from a Murex named pipe", "commands/stdin": "Read the stdin belonging to the parent code block", - "commands/a": "A sophisticated yet simple way to build an array or list", - "commands/addheading": "Adds headings to a table", "commands/alias": "Create an alias for a command", - "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", - "commands/append": "Add data to the end of an array", "commands/args": "Command line flag parser for Murex shell scripting", - "commands/autocomplete": "Set definitions for tab-completion in the command line", - "commands/bexists": "Check which builtins exist", - "commands/bg": "Run processes in the background", "commands/break": "Terminate execution of a block within your processes scope", "commands/cast": "Alters the data-type of the previous function without altering its output", "commands/catch": "Handles the exception code raised by `try` or `trypipe`", "commands/cd": "Change (working) directory", - "commands/config": "Query or define Murex runtime settings", "commands/continue": "Terminate process of a block within a caller function", - "commands/count": "Count items in a map, list or array", - "commands/cpuarch": "Output the hosts CPU architecture", - "commands/cpucount": "Output the number of CPU cores available on your host", - "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "commands/debug": "Debugging information", "commands/die": "Terminate murex with an exit number of 1 (deprecated)", - "commands/err": "Print a line to the stderr", - "commands/escape": "Escape or unescape input", - "commands/esccli": "Escapes an array so output is valid shell code", - "commands/eschtml": "Encode or decodes text for HTML", - "commands/escurl": "Encode or decodes text for the URL", "commands/event": "Event driven programming for shell scripts", - "commands/exec": "Runs an executable", "commands/exit": "Exit murex", - "commands/exitnum": "Output the exit number of the previous process", - "commands/export": "Define an environmental variable and set it's value", "commands/expr": "Expressions: mathematical, string comparisons, logical operators", - "commands/f": "Lists or filters file system objects (eg files)", "commands/false": "Returns a `false` value", - "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", - "commands/fg": "Sends a background process into the foreground", - "commands/fid-kill": "Terminate a running Murex function", - "commands/fid-killall": "Terminate _all_ running Murex functions", - "commands/fid-list": "Lists all running functions within the current Murex session", "commands/for": "A more familiar iteration loop to existing developers", "commands/foreach": "Iterate through an array", "commands/formap": "Iterate through a map or other collection of data", "commands/format": "Reformat one data-type into another data-type", "commands/function": "Define a function block", - "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", "commands/get-type": "Returns the data-type of a variable or pipe", "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "commands/global": "Define a global variable and set it's value", - "commands/history": "Outputs murex's command history", "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", "commands/is-null": "Checks if a variable is null or undefined", "commands/ja": "A sophisticated yet simply way to build a JSON array", - "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "commands/left": "Left substring every item in a list", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/list.case": "Changes the character case of a string or all elements in an array", - "commands/lockfile": "Create and manage lock files", - "commands/man-get-flags": "Parses man page files for command line flags", - "commands/man-summary": "Outputs a man page summary of a command", - "commands/map": "Creates a map from two data sources", - "commands/match": "Match an exact value in an array", "commands/method": "Define a methods supported data-types", - "commands/mjoin": "Joins a list or array into a single string", - "commands/msort": "Sorts an array - data type agnostic", - "commands/mtac": "Reverse the order of an array", "commands/murex-docs": "Displays the man pages for Murex builtins", - "commands/murex-package": "Murex's package manager", "commands/murex-parser": "Runs the Murex parser against a block of code", - "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "commands/devnull": "null function. Similar to /dev/null", - "commands/open-image": "Renders bitmap image data on your terminal", - "commands/open": "Open a file with a preferred handler", - "commands/openagent": "Creates a handler function for `open`", "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "commands/os": "Output the auto-detected OS name", - "commands/out": "Print a string to the stdout with a trailing new line character", - "commands/pipe": "Manage Murex named pipes", "commands/post": "HTTP POST request with a JSON-parsable return", - "commands/prefix": "Prefix a string to every item in a list", - "commands/prepend": "Add data to the start of an array", - "commands/pretty": "Prettifies JSON to make it human readable", "commands/private": "Define a private function block", - "commands/pt": "Pipe telemetry. Writes data-types and bytes written", "commands/rand": "Random field generator", - "commands/read": "`read` a line of input from the user and store as a variable", - "commands/regexp": "Regexp tools for arrays / lists of strings", "commands/return": "Exits current function scope", - "commands/right": "Right substring every item in a list", - "commands/round": "Round a number by a user defined precision", "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", - "commands/runtime": "Returns runtime information on the internal state of Murex", - "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "commands/set": "Define a local variable and set it's value", "commands/signal": "Sends a signal RPC", - "commands/source": "Import Murex code from another file of code block", - "commands/struct-keys": "Outputs all the keys in a structure as a file path", - "commands/suffix": "Prefix a string to every item in a list", - "commands/summary": "Defines a summary help text for a command", "commands/switch": "Blocks of cascading conditionals", - "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", "commands/tabulate": "Table transformation tools", "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", "commands/time": "Returns the execution run time of a command or block", - "commands/tmp": "Create a temporary file and write to it", - "commands/tout": "Print a string to the stdout and set it's data-type", "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", "commands/true": "Returns a `true` value", "commands/try": "Handles non-zero exits inside a block of code", @@ -257,9 +188,78 @@ func init() { "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", "commands/type": "Command type (function, builtin, alias, etc)", "commands/unsafe": "Execute a block of code, always returning a zero exit number", - "commands/version": "Get Murex version", "commands/which": "Locate command origin", "commands/while": "Loop until condition false", + "commands/esccli": "Escapes an array so output is valid shell code", + "commands/eschtml": "Encode or decodes text for HTML", + "commands/escape": "Escape or unescape input", + "commands/escurl": "Encode or decodes text for the URL", + "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", + "commands/exec": "Runs an executable", + "commands/source": "Import Murex code from another file or code block", + "commands/f": "Lists or filters file system objects (eg files)", + "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", + "commands/lockfile": "Create and manage lock files", + "commands/tmp": "Create a temporary file and write to it", + "commands/open-image": "Renders bitmap image data on your terminal", + "commands/open": "Open a file with a preferred handler", + "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "commands/pt": "Pipe telemetry. Writes data-types and bytes written", + "commands/man-get-flags": "Parses man page files for command line flags", + "commands/man-summary": "Outputs a man page summary of a command", + "commands/err": "Print a line to the stderr", + "commands/read": "`read` a line of input from the user and store as a variable", + "commands/pipe": "Manage Murex named pipes", + "commands/tout": "Print a string to the stdout and set it's data-type", + "commands/out": "Print a string to the stdout with a trailing new line character", + "commands/namedpipe": "Reads from a Murex named pipe", + "commands/append": "Add data to the end of an array", + "commands/list.case": "Changes the character case of a string or all elements in an array", + "commands/mjoin": "Joins a list or array into a single string", + "commands/left": "Left substring every item in a list", + "commands/a": "A sophisticated yet simple way to build an array or list", + "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "commands/prefix": "Prefix a string to every item in a list", + "commands/prepend": "Add data to the start of an array", + "commands/regexp": "Regexp tools for arrays / lists of strings", + "commands/mtac": "Reverse the order of an array", + "commands/right": "Right substring every item in a list", + "commands/msort": "Sorts an array - data type agnostic", + "commands/match": "Match an exact value in an array", + "commands/suffix": "Prefix a string to every item in a list", + "commands/round": "Round a number by a user defined precision", + "commands/bg": "Run processes in the background", + "commands/exitnum": "Output the exit number of the previous process", + "commands/fg": "Sends a background process into the foreground", + "commands/fid-killall": "Terminate _all_ running Murex functions", + "commands/fid-kill": "Terminate a running Murex function", + "commands/fid-list": "Lists all running functions within the current Murex session", + "commands/autocomplete": "Set definitions for tab-completion in the command line", + "commands/bexists": "Check which builtins exist", + "commands/config": "Query or define Murex runtime settings", + "commands/debug": "Debugging information", + "commands/history": "Outputs murex's command history", + "commands/openagent": "Creates a handler function for `open`", + "commands/murex-package": "Murex's package manager", + "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "commands/runtime": "Returns runtime information on the internal state of Murex", + "commands/summary": "Defines a summary help text for a command", + "commands/version": "Get Murex version", + "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", + "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "commands/count": "Count items in a map, list or array", + "commands/pretty": "Prettifies JSON to make it human readable", + "commands/struct-keys": "Outputs all the keys in a structure as a file path", + "commands/2darray": "Create a 2D JSON array from multiple input sources", + "commands/map": "Creates a map from two data sources", + "commands/cpuarch": "Output the hosts CPU architecture", + "commands/cpucount": "Output the number of CPU cores available on your host", + "commands/os": "Output the auto-detected OS name", + "commands/addheading": "Adds headings to a table", + "commands/export": "Define an environmental variable and set it's value", + "commands/global": "Define a global variable and set it's value", + "commands/set": "Define a local variable and set it's value", "mkarray/date": "Create arrays of dates", "mkarray/character": "Making character arrays (a to z)", "mkarray/decimal": "Create arrays of decimal integers", @@ -269,8 +269,8 @@ func init() { "optional/base64": "Encode or decode a base64 string", "optional/gz": "Compress or decompress a gzip file", "optional/qr": "Creates a QR code from stdin", - "optional/select": "Inlining SQL into shell pipelines", "optional/sleep": "Suspends the shell for a number of seconds", + "optional/select": "Inlining SQL into shell pipelines", "parser/expr-inlined": "Inline expressions", "parser/c-style-fun": "Inlined commands for expressions and statements", "parser/double-quote": "Initiates or terminates a string (variables expanded)", @@ -303,7 +303,6 @@ func init() { "parser/element": "Outputs an element from a nested structure", "parser/lambda": "Iterate through structured data", "parser/curly-brace": "Initiates or terminates a code block", - "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", "parser/logical-or": "Continues next operation only if previous operation fails", "parser/tilde": "Home directory path variable", @@ -419,177 +418,57 @@ func init() { "!": "not-func", "not": "not-func", - "2darray": "2darray", - "struct.2darray": "2darray", - "(murex named pipe)": "namedpipe", - "<>": "namedpipe", - "read-named-pipe": "namedpipe", "": "stdin", - "a": "a", - "addheading": "addheading", "alias": "alias", "!alias": "alias", - "alter": "alter", - "~>": "alter", "and": "and", "!and": "and", - "append": "append", - "list.append": "append", "args": "args", - "autocomplete": "autocomplete", - "bexists": "bexists", - "bg": "bg", "break": "break", "cast": "cast", "catch": "catch", "!catch": "catch", "cd": "cd", - "config": "config", - "!config": "config", "continue": "continue", - "count": "count", - "len": "count", - "list.count": "count", - "cpuarch": "cpuarch", - "sys.cpu.arch": "cpuarch", - "cpucount": "cpucount", - "sys.cpu.count": "cpucount", - "datetime": "datetime", - "debug": "debug", "die": "die", - "err": "err", - "escape": "escape", - "!escape": "escape", - "escape.quote": "escape", - "!escape.quote": "escape", - "esccli": "esccli", - "escape.cli": "esccli", - "eschtml": "eschtml", - "!eschtml": "eschtml", - "escape.html": "eschtml", - "!escape.html": "eschtml", - "escurl": "escurl", - "!escurl": "escurl", - "escape.url": "escurl", - "!escape.url": "escurl", "event": "event", "!event": "event", - "exec": "exec", - "command": "exec", "exit": "exit", - "exitnum": "exitnum", - "export": "export", - "!export": "export", - "unset": "export", "expr": "expr", - "f": "f", "false": "false", - "fexec": "fexec", - "builtin": "fexec", - "fg": "fg", - "fid-kill": "fid-kill", - "fid-killall": "fid-killall", - "fid-list": "fid-list", - "jobs": "fid-list", "for": "for", "foreach": "foreach", "formap": "formap", "format": "format", "function": "function", "!function": "function", - "g": "g", - "!g": "g", "get-type": "get-type", "get": "get", "getfile": "getfile", - "global": "global", - "!global": "global", - "history": "history", "if": "if", "!if": "if", "is-null": "is-null", "ja": "ja", - "jsplit": "jsplit", - "list.split": "jsplit", "key-code": "key-code", - "left": "left", - "list.left": "left", "let": "let", - "list.case": "list.case", - "lockfile": "lockfile", - "man-get-flags": "man-get-flags", - "man-summary": "man-summary", - "map": "map", - "match": "match", - "!match": "match", - "list.string": "match", - "!list.string": "match", "method": "method", - "mjoin": "mjoin", - "list.join": "mjoin", - "msort": "msort", - "list.sort": "msort", - "mtac": "mtac", - "list.reverse": "mtac", "murex-docs": "murex-docs", "help": "murex-docs", - "murex-package": "murex-package", "murex-parser": "murex-parser", - "murex-update-exe-list": "murex-update-exe-list", "null": "devnull", - "open-image": "open-image", - "open": "open", - "openagent": "openagent", - "!openagent": "openagent", "or": "or", "!or": "or", - "os": "os", - "sys.os": "os", - "out": "out", - "echo": "out", - "pipe": "pipe", - "!pipe": "pipe", "post": "post", - "prefix": "prefix", - "list.prefix": "prefix", - "prepend": "prepend", - "list.prepend": "prepend", - "pretty": "pretty", "private": "private", - "pt": "pt", "rand": "rand", - "read": "read", - "regexp": "regexp", - "!regexp": "regexp", - "list.regex": "regexp", - "!list.regex": "regexp", "return": "return", - "right": "right", - "list.right": "right", - "round": "round", "runmode": "runmode", - "runtime": "runtime", - "builtins": "runtime", - "rx": "rx", - "!rx": "rx", - "set": "set", - "!set": "set", "signal": "signal", - "source": "source", - ".": "source", - "struct-keys": "struct-keys", - "suffix": "suffix", - "list.suffix": "suffix", - "summary": "summary", - "!summary": "summary", "switch": "switch", - "ta": "ta", "tabulate": "tabulate", "test": "test", "!test": "test", "time": "time", - "tmp": "tmp", - "tout": "tout", "tread": "tread", "true": "true", "try": "try", @@ -598,19 +477,200 @@ func init() { "trypipeerr": "trypipeerr", "type": "type", "unsafe": "unsafe", - "version": "version", "which": "which", "while": "while", "!while": "while", + "esccli": "esccli", + "escape.cli": "esccli", + "eschtml": "eschtml", + "!eschtml": "eschtml", + "escape.html": "eschtml", + "!escape.html": "eschtml", + "escape": "escape", + "!escape": "escape", + "escape.quote": "escape", + "!escape.quote": "escape", + "escurl": "escurl", + "!escurl": "escurl", + "escape.url": "escurl", + "!escape.url": "escurl", + "fexec": "fexec", + "builtin": "fexec", + "exec.builtin": "fexec", + "exec.function": "fexec", + "exec.private": "fexec", + "exec": "exec", + "command": "exec", + "exec.file": "exec", + "source": "source", + ".": "source", + "exec.include": "source", + "f": "f", + "fs.files": "f", + "g": "g", + "!g": "g", + "fs.glob": "g", + "!fs.glob": "g", + "lockfile": "lockfile", + "fs.lockfile": "lockfile", + "tmp": "tmp", + "fs.new.tmpfile": "tmp", + "open-image": "open-image", + "fs.open.image": "open-image", + "open": "open", + "fs.open": "open", + "rx": "rx", + "!rx": "rx", + "fs.regex": "rx", + "!fs.regex": "rx", + "pt": "pt", + "fs.status": "pt", + "man-get-flags": "man-get-flags", + "help.man.flags": "man-get-flags", + "man-summary": "man-summary", + "help.man.summary": "man-summary", + "err": "err", + "io.err": "err", + "read": "read", + "io.input": "read", + "pipe": "pipe", + "!pipe": "pipe", + "io.new.pipe": "pipe", + "!io.new.pipe": "pipe", + "tout": "tout", + "io.out.type": "tout", + "out": "out", + "io.out": "out", + "echo": "out", + "(murex named pipe)": "namedpipe", + "<>": "namedpipe", + "read-named-pipe": "namedpipe", + "io.pipe": "namedpipe", + "append": "append", + "list.append": "append", + "list.case": "list.case", + "mjoin": "mjoin", + "list.join": "mjoin", + "left": "left", + "list.left": "left", + "a": "a", + "mkarray": "a", + "list.new.str": "a", + "ta": "ta", + "list.new.type": "ta", + "prefix": "prefix", + "list.prefix": "prefix", + "prepend": "prepend", + "list.prepend": "prepend", + "regexp": "regexp", + "!regexp": "regexp", + "list.regex": "regexp", + "!list.regex": "regexp", + "mtac": "mtac", + "list.reverse": "mtac", + "right": "right", + "list.right": "right", + "msort": "msort", + "list.sort": "msort", + "match": "match", + "!match": "match", + "list.str": "match", + "!list.str": "match", + "suffix": "suffix", + "list.suffix": "suffix", + "round": "round", + "num.round": "round", + "bg": "bg", + "proc.bg": "bg", + "exitnum": "exitnum", + "proc.exitnum": "exitnum", + "fg": "fg", + "proc.fg": "fg", + "fid.killall": "fid-killall", + "proc.kill.all": "fid-killall", + "fid-kill": "fid-kill", + "proc.kill": "fid-kill", + "fid-list": "fid-list", + "jobs": "fid-list", + "proc.list": "fid-list", + "proc.jobs": "fid-list", + "autocomplete": "autocomplete", + "shell.autocomplete": "autocomplete", + "bexists": "bexists", + "config": "config", + "!config": "config", + "shell.config": "config", + "!shell.config": "config", + "debug": "debug", + "shell.debug": "debug", + "history": "history", + "shell.history": "history", + "openagent": "openagent", + "!openagent": "openagent", + "shell.open": "openagent", + "!shell.open": "openagent", + "murex.package": "murex-package", + "shell.packages": "murex-package", + "murex-update-exe-list": "murex-update-exe-list", + "shell.rescan.path": "murex-update-exe-list", + "runtime": "runtime", + "builtins": "runtime", + "shell.runtime": "runtime", + "summary": "summary", + "!summary": "summary", + "shell.summary": "summary", + "!shell.summary": "summary", + "version": "version", + "shell.version": "version", + "datetime": "datetime", + "str.datetime": "datetime", + "jsplit": "jsplit", + "str.split": "jsplit", + "alter": "alter", + "~>": "alter", + "struct.alter": "alter", + "count": "count", + "len": "count", + "struct.count": "count", + "pretty": "pretty", + "struct.json.pretty": "pretty", + "struct-keys": "struct-keys", + "struct.keys": "struct-keys", + "2darray": "2darray", + "struct.new.2darray": "2darray", + "map": "map", + "struct.new.map": "map", + "cpuarch": "cpuarch", + "sys.cpu.arch": "cpuarch", + "cpucount": "cpucount", + "sys.cpu.count": "cpucount", + "os": "os", + "sys.os": "os", + "addheading": "addheading", + "table.new.heading": "addheading", + "export": "export", + "!export": "export", + "unset": "export", + "var.env": "export", + "!var.env": "export", + "global": "global", + "!global": "global", + "var.global": "global", + "!var.global": "global", + "set": "set", + "!set": "set", + "var.set": "set", + "!var.set": "set", - "!bz2": "optional/bz2", - "base64": "optional/base64", - "!base64": "optional/base64", - "gz": "optional/gz", - "!gz": "optional/gz", - "qr": "optional/qr", - "select": "optional/select", - "sleep": "optional/sleep", + "!bz2": "optional/bz2", + "base64": "optional/base64", + "!base64": "optional/base64", + "gz": "optional/gz", + "!gz": "optional/gz", + "qr": "optional/qr", + "sleep": "optional/sleep", + "select": "optional/select", + "table.select": "optional/select", "expr-inlined": "parser/expr-inlined", "c-style-fun": "parser/c-style-fun", @@ -649,186 +709,63 @@ func init() { "element": "parser/element", "lambda": "parser/lambda", "curly-brace": "parser/curly-brace", - "|>": "parser/file-truncate", - ">": "parser/file-truncate", - "fwrite": "parser/file-truncate", "pipe-posix": "parser/pipe-posix", "logical-or": "parser/logical-or", "tilde": "parser/tilde", "commands/!": "commands/not-func", "commands/not": "commands/not-func", - "commands/2darray": "commands/2darray", - "commands/struct.2darray": "commands/2darray", - "commands/(murex named pipe)": "commands/namedpipe", - "commands/<>": "commands/namedpipe", - "commands/read-named-pipe": "commands/namedpipe", "commands/": "commands/stdin", - "commands/a": "commands/a", - "commands/addheading": "commands/addheading", "commands/alias": "commands/alias", "commands/!alias": "commands/alias", - "commands/alter": "commands/alter", - "commands/~>": "commands/alter", "commands/and": "commands/and", "commands/!and": "commands/and", - "commands/append": "commands/append", - "commands/list.append": "commands/append", "commands/args": "commands/args", - "commands/autocomplete": "commands/autocomplete", - "commands/bexists": "commands/bexists", - "commands/bg": "commands/bg", "commands/break": "commands/break", "commands/cast": "commands/cast", "commands/catch": "commands/catch", "commands/!catch": "commands/catch", "commands/cd": "commands/cd", - "commands/config": "commands/config", - "commands/!config": "commands/config", "commands/continue": "commands/continue", - "commands/count": "commands/count", - "commands/len": "commands/count", - "commands/list.count": "commands/count", - "commands/cpuarch": "commands/cpuarch", - "commands/sys.cpu.arch": "commands/cpuarch", - "commands/cpucount": "commands/cpucount", - "commands/sys.cpu.count": "commands/cpucount", - "commands/datetime": "commands/datetime", - "commands/debug": "commands/debug", "commands/die": "commands/die", - "commands/err": "commands/err", - "commands/escape": "commands/escape", - "commands/!escape": "commands/escape", - "commands/escape.quote": "commands/escape", - "commands/!escape.quote": "commands/escape", - "commands/esccli": "commands/esccli", - "commands/escape.cli": "commands/esccli", - "commands/eschtml": "commands/eschtml", - "commands/!eschtml": "commands/eschtml", - "commands/escape.html": "commands/eschtml", - "commands/!escape.html": "commands/eschtml", - "commands/escurl": "commands/escurl", - "commands/!escurl": "commands/escurl", - "commands/escape.url": "commands/escurl", - "commands/!escape.url": "commands/escurl", "commands/event": "commands/event", "commands/!event": "commands/event", - "commands/exec": "commands/exec", - "commands/command": "commands/exec", "commands/exit": "commands/exit", - "commands/exitnum": "commands/exitnum", - "commands/export": "commands/export", - "commands/!export": "commands/export", - "commands/unset": "commands/export", "commands/expr": "commands/expr", - "commands/f": "commands/f", "commands/false": "commands/false", - "commands/fexec": "commands/fexec", - "commands/builtin": "commands/fexec", - "commands/fg": "commands/fg", - "commands/fid-kill": "commands/fid-kill", - "commands/fid-killall": "commands/fid-killall", - "commands/fid-list": "commands/fid-list", - "commands/jobs": "commands/fid-list", "commands/for": "commands/for", "commands/foreach": "commands/foreach", "commands/formap": "commands/formap", "commands/format": "commands/format", "commands/function": "commands/function", "commands/!function": "commands/function", - "commands/g": "commands/g", - "commands/!g": "commands/g", "commands/get-type": "commands/get-type", "commands/get": "commands/get", "commands/getfile": "commands/getfile", - "commands/global": "commands/global", - "commands/!global": "commands/global", - "commands/history": "commands/history", "commands/if": "commands/if", "commands/!if": "commands/if", "commands/is-null": "commands/is-null", "commands/ja": "commands/ja", - "commands/jsplit": "commands/jsplit", - "commands/list.split": "commands/jsplit", "commands/key-code": "commands/key-code", - "commands/left": "commands/left", - "commands/list.left": "commands/left", "commands/let": "commands/let", - "commands/list.case": "commands/list.case", - "commands/lockfile": "commands/lockfile", - "commands/man-get-flags": "commands/man-get-flags", - "commands/man-summary": "commands/man-summary", - "commands/map": "commands/map", - "commands/match": "commands/match", - "commands/!match": "commands/match", - "commands/list.string": "commands/match", - "commands/!list.string": "commands/match", "commands/method": "commands/method", - "commands/mjoin": "commands/mjoin", - "commands/list.join": "commands/mjoin", - "commands/msort": "commands/msort", - "commands/list.sort": "commands/msort", - "commands/mtac": "commands/mtac", - "commands/list.reverse": "commands/mtac", "commands/murex-docs": "commands/murex-docs", "commands/help": "commands/murex-docs", - "commands/murex-package": "commands/murex-package", "commands/murex-parser": "commands/murex-parser", - "commands/murex-update-exe-list": "commands/murex-update-exe-list", "commands/null": "commands/devnull", - "commands/open-image": "commands/open-image", - "commands/open": "commands/open", - "commands/openagent": "commands/openagent", - "commands/!openagent": "commands/openagent", "commands/or": "commands/or", "commands/!or": "commands/or", - "commands/os": "commands/os", - "commands/sys.os": "commands/os", - "commands/out": "commands/out", - "commands/echo": "commands/out", - "commands/pipe": "commands/pipe", - "commands/!pipe": "commands/pipe", "commands/post": "commands/post", - "commands/prefix": "commands/prefix", - "commands/list.prefix": "commands/prefix", - "commands/prepend": "commands/prepend", - "commands/list.prepend": "commands/prepend", - "commands/pretty": "commands/pretty", "commands/private": "commands/private", - "commands/pt": "commands/pt", "commands/rand": "commands/rand", - "commands/read": "commands/read", - "commands/regexp": "commands/regexp", - "commands/!regexp": "commands/regexp", - "commands/list.regex": "commands/regexp", - "commands/!list.regex": "commands/regexp", "commands/return": "commands/return", - "commands/right": "commands/right", - "commands/list.right": "commands/right", - "commands/round": "commands/round", "commands/runmode": "commands/runmode", - "commands/runtime": "commands/runtime", - "commands/builtins": "commands/runtime", - "commands/rx": "commands/rx", - "commands/!rx": "commands/rx", - "commands/set": "commands/set", - "commands/!set": "commands/set", "commands/signal": "commands/signal", - "commands/source": "commands/source", - "commands/.": "commands/source", - "commands/struct-keys": "commands/struct-keys", - "commands/suffix": "commands/suffix", - "commands/list.suffix": "commands/suffix", - "commands/summary": "commands/summary", - "commands/!summary": "commands/summary", "commands/switch": "commands/switch", - "commands/ta": "commands/ta", "commands/tabulate": "commands/tabulate", "commands/test": "commands/test", "commands/!test": "commands/test", "commands/time": "commands/time", - "commands/tmp": "commands/tmp", - "commands/tout": "commands/tout", "commands/tread": "commands/tread", "commands/true": "commands/true", "commands/try": "commands/try", @@ -837,10 +774,190 @@ func init() { "commands/trypipeerr": "commands/trypipeerr", "commands/type": "commands/type", "commands/unsafe": "commands/unsafe", - "commands/version": "commands/version", "commands/which": "commands/which", "commands/while": "commands/while", "commands/!while": "commands/while", + "commands/esccli": "commands/esccli", + "commands/escape.cli": "commands/esccli", + "commands/eschtml": "commands/eschtml", + "commands/!eschtml": "commands/eschtml", + "commands/escape.html": "commands/eschtml", + "commands/!escape.html": "commands/eschtml", + "commands/escape": "commands/escape", + "commands/!escape": "commands/escape", + "commands/escape.quote": "commands/escape", + "commands/!escape.quote": "commands/escape", + "commands/escurl": "commands/escurl", + "commands/!escurl": "commands/escurl", + "commands/escape.url": "commands/escurl", + "commands/!escape.url": "commands/escurl", + "commands/fexec": "commands/fexec", + "commands/builtin": "commands/fexec", + "commands/exec.builtin": "commands/fexec", + "commands/exec.function": "commands/fexec", + "commands/exec.private": "commands/fexec", + "commands/exec": "commands/exec", + "commands/command": "commands/exec", + "commands/exec.file": "commands/exec", + "commands/source": "commands/source", + "commands/.": "commands/source", + "commands/exec.include": "commands/source", + "commands/f": "commands/f", + "commands/fs.files": "commands/f", + "commands/g": "commands/g", + "commands/!g": "commands/g", + "commands/fs.glob": "commands/g", + "commands/!fs.glob": "commands/g", + "commands/lockfile": "commands/lockfile", + "commands/fs.lockfile": "commands/lockfile", + "commands/tmp": "commands/tmp", + "commands/fs.new.tmpfile": "commands/tmp", + "commands/open-image": "commands/open-image", + "commands/fs.open.image": "commands/open-image", + "commands/open": "commands/open", + "commands/fs.open": "commands/open", + "commands/rx": "commands/rx", + "commands/!rx": "commands/rx", + "commands/fs.regex": "commands/rx", + "commands/!fs.regex": "commands/rx", + "commands/pt": "commands/pt", + "commands/fs.status": "commands/pt", + "commands/man-get-flags": "commands/man-get-flags", + "commands/help.man.flags": "commands/man-get-flags", + "commands/man-summary": "commands/man-summary", + "commands/help.man.summary": "commands/man-summary", + "commands/err": "commands/err", + "commands/io.err": "commands/err", + "commands/read": "commands/read", + "commands/io.input": "commands/read", + "commands/pipe": "commands/pipe", + "commands/!pipe": "commands/pipe", + "commands/io.new.pipe": "commands/pipe", + "commands/!io.new.pipe": "commands/pipe", + "commands/tout": "commands/tout", + "commands/io.out.type": "commands/tout", + "commands/out": "commands/out", + "commands/io.out": "commands/out", + "commands/echo": "commands/out", + "commands/(murex named pipe)": "commands/namedpipe", + "commands/<>": "commands/namedpipe", + "commands/read-named-pipe": "commands/namedpipe", + "commands/io.pipe": "commands/namedpipe", + "commands/append": "commands/append", + "commands/list.append": "commands/append", + "commands/list.case": "commands/list.case", + "commands/mjoin": "commands/mjoin", + "commands/list.join": "commands/mjoin", + "commands/left": "commands/left", + "commands/list.left": "commands/left", + "commands/a": "commands/a", + "commands/mkarray": "commands/a", + "commands/list.new.str": "commands/a", + "commands/ta": "commands/ta", + "commands/list.new.type": "commands/ta", + "commands/prefix": "commands/prefix", + "commands/list.prefix": "commands/prefix", + "commands/prepend": "commands/prepend", + "commands/list.prepend": "commands/prepend", + "commands/regexp": "commands/regexp", + "commands/!regexp": "commands/regexp", + "commands/list.regex": "commands/regexp", + "commands/!list.regex": "commands/regexp", + "commands/mtac": "commands/mtac", + "commands/list.reverse": "commands/mtac", + "commands/right": "commands/right", + "commands/list.right": "commands/right", + "commands/msort": "commands/msort", + "commands/list.sort": "commands/msort", + "commands/match": "commands/match", + "commands/!match": "commands/match", + "commands/list.str": "commands/match", + "commands/!list.str": "commands/match", + "commands/suffix": "commands/suffix", + "commands/list.suffix": "commands/suffix", + "commands/round": "commands/round", + "commands/num.round": "commands/round", + "commands/bg": "commands/bg", + "commands/proc.bg": "commands/bg", + "commands/exitnum": "commands/exitnum", + "commands/proc.exitnum": "commands/exitnum", + "commands/fg": "commands/fg", + "commands/proc.fg": "commands/fg", + "commands/fid.killall": "commands/fid-killall", + "commands/proc.kill.all": "commands/fid-killall", + "commands/fid-kill": "commands/fid-kill", + "commands/proc.kill": "commands/fid-kill", + "commands/fid-list": "commands/fid-list", + "commands/jobs": "commands/fid-list", + "commands/proc.list": "commands/fid-list", + "commands/proc.jobs": "commands/fid-list", + "commands/autocomplete": "commands/autocomplete", + "commands/shell.autocomplete": "commands/autocomplete", + "commands/bexists": "commands/bexists", + "commands/config": "commands/config", + "commands/!config": "commands/config", + "commands/shell.config": "commands/config", + "commands/!shell.config": "commands/config", + "commands/debug": "commands/debug", + "commands/shell.debug": "commands/debug", + "commands/history": "commands/history", + "commands/shell.history": "commands/history", + "commands/openagent": "commands/openagent", + "commands/!openagent": "commands/openagent", + "commands/shell.open": "commands/openagent", + "commands/!shell.open": "commands/openagent", + "commands/murex.package": "commands/murex-package", + "commands/shell.packages": "commands/murex-package", + "commands/murex-update-exe-list": "commands/murex-update-exe-list", + "commands/shell.rescan.path": "commands/murex-update-exe-list", + "commands/runtime": "commands/runtime", + "commands/builtins": "commands/runtime", + "commands/shell.runtime": "commands/runtime", + "commands/summary": "commands/summary", + "commands/!summary": "commands/summary", + "commands/shell.summary": "commands/summary", + "commands/!shell.summary": "commands/summary", + "commands/version": "commands/version", + "commands/shell.version": "commands/version", + "commands/datetime": "commands/datetime", + "commands/str.datetime": "commands/datetime", + "commands/jsplit": "commands/jsplit", + "commands/str.split": "commands/jsplit", + "commands/alter": "commands/alter", + "commands/~>": "commands/alter", + "commands/struct.alter": "commands/alter", + "commands/count": "commands/count", + "commands/len": "commands/count", + "commands/struct.count": "commands/count", + "commands/pretty": "commands/pretty", + "commands/struct.json.pretty": "commands/pretty", + "commands/struct-keys": "commands/struct-keys", + "commands/struct.keys": "commands/struct-keys", + "commands/2darray": "commands/2darray", + "commands/struct.new.2darray": "commands/2darray", + "commands/map": "commands/map", + "commands/struct.new.map": "commands/map", + "commands/cpuarch": "commands/cpuarch", + "commands/sys.cpu.arch": "commands/cpuarch", + "commands/cpucount": "commands/cpucount", + "commands/sys.cpu.count": "commands/cpucount", + "commands/os": "commands/os", + "commands/sys.os": "commands/os", + "commands/addheading": "commands/addheading", + "commands/table.new.heading": "commands/addheading", + "commands/export": "commands/export", + "commands/!export": "commands/export", + "commands/unset": "commands/export", + "commands/var.env": "commands/export", + "commands/!var.env": "commands/export", + "commands/global": "commands/global", + "commands/!global": "commands/global", + "commands/var.global": "commands/global", + "commands/!var.global": "commands/global", + "commands/set": "commands/set", + "commands/!set": "commands/set", + "commands/var.set": "commands/set", + "commands/!var.set": "commands/set", "mkarray/date": "mkarray/date", "mkarray/character": "mkarray/character", "mkarray/decimal": "mkarray/decimal", @@ -852,8 +969,9 @@ func init() { "optional/gz": "optional/gz", "optional/!gz": "optional/gz", "optional/qr": "optional/qr", - "optional/select": "optional/select", "optional/sleep": "optional/sleep", + "optional/select": "optional/select", + "optional/table.select": "optional/select", "parser/expr-inlined": "parser/expr-inlined", "parser/c-style-fun": "parser/c-style-fun", "parser/double-quote": "parser/double-quote", @@ -891,9 +1009,6 @@ func init() { "parser/element": "parser/element", "parser/lambda": "parser/lambda", "parser/curly-brace": "parser/curly-brace", - "parser/|>": "parser/file-truncate", - "parser/>": "parser/file-truncate", - "parser/fwrite": "parser/file-truncate", "parser/pipe-posix": "parser/pipe-posix", "parser/logical-or": "parser/logical-or", "parser/tilde": "parser/tilde", diff --git a/builtins/optional/select/select_doc.yaml b/builtins/optional/select/select_doc.yaml index 96a0eda49..e92609644 100644 --- a/builtins/optional/select/select_doc.yaml +++ b/builtins/optional/select/select_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: select Title: >- - `select` + table.select: `select` CategoryID: optional Summary: >- Inlining SQL into shell pipelines @@ -121,6 +121,7 @@ If you do run into any issues then please raise them on [Github](https://github.com/lmorg/murex/issues). Synonyms: - select + - table.select Related: - v2.1 - csv diff --git a/docs/blog/reading_lists.md b/docs/blog/reading_lists.md index 4e654e2a8..948c69e2b 100644 --- a/docs/blog/reading_lists.md +++ b/docs/blog/reading_lists.md @@ -145,16 +145,16 @@ Published: 22.04.2023 at 11:43 * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list
diff --git a/docs/changelog/v2.0.md b/docs/changelog/v2.0.md index db5cceec1..a69fcda6d 100644 --- a/docs/changelog/v2.0.md +++ b/docs/changelog/v2.0.md @@ -37,14 +37,14 @@ Published: 17.04.2021 at 12:49 An introduction to Murex modules and packages * [Spellcheck](../integrations/spellcheck.md): How to enable inline spellchecking -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`murex-package`](../commands/murex-package.md): - Murex's package manager -* [`open-image`](../commands/open-image.md): +* [fs.open.image: `open-image`](../commands/open-image.md): Renders bitmap image data on your terminal -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.packages: `murex-package`](../commands/murex-package.md): + Murex's package manager
diff --git a/docs/changelog/v2.1.md b/docs/changelog/v2.1.md index 90ca6c571..9d8d55fd3 100644 --- a/docs/changelog/v2.1.md +++ b/docs/changelog/v2.1.md @@ -81,19 +81,19 @@ Published: 30.04.2021 at 10:00 generic (primitive) * [`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): Read from a data type one array element at a time and return the elements contents and data type -* [`bg`](../commands/bg.md): - Run processes in the background * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`fg`](../commands/fg.md): - Sends a background process into the foreground * [`foreach`](../commands/foreach.md): Iterate through an array -* [`jobs`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`jsonl`](../types/jsonl.md): JSON Lines -* [`select`](../optional/select.md): +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): + Sends a background process into the foreground +* [proc.list: `jobs`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines
diff --git a/docs/changelog/v2.10.md b/docs/changelog/v2.10.md index ff87d6ab4..3801f374a 100644 --- a/docs/changelog/v2.10.md +++ b/docs/changelog/v2.10.md @@ -62,22 +62,22 @@ Published: 01.08.2022 at 20:10 Continues next operation if previous operation passes * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`f`](../commands/f.md): - Lists or filters file system objects (eg files) -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) * [`runmode`](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`rx`](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [fs.files: `f`](../commands/f.md): + Lists or filters file system objects (eg files) +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [fs.regex: `rx`](../commands/rx.md): + Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v2.11.md b/docs/changelog/v2.11.md index 7edffd679..e27eec479 100644 --- a/docs/changelog/v2.11.md +++ b/docs/changelog/v2.11.md @@ -56,18 +56,18 @@ Published: 12.09.2022 at 08:10 A breakdown of the different files loaded on start up * [`alias`](../commands/alias.md): Create an alias for a command -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`cd`](../commands/cd.md): Change (working) directory -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`set`](../commands/set.md): - Define a local variable and set it's value -* [`struct-keys`](../commands/struct-keys.md): +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [struct.keys: `struct-keys`](../commands/struct-keys.md): Outputs all the keys in a structure as a file path +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/changelog/v2.2.md b/docs/changelog/v2.2.md index c17ce0591..06ebec99c 100644 --- a/docs/changelog/v2.2.md +++ b/docs/changelog/v2.2.md @@ -64,7 +64,7 @@ Published: 21.06.2021 at 21:51 * [`*` (generic)](../types/generic.md): generic (primitive) -* [`fg`](../commands/fg.md): +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground
diff --git a/docs/changelog/v2.3.md b/docs/changelog/v2.3.md index f6bf2eb89..d3befbe7f 100644 --- a/docs/changelog/v2.3.md +++ b/docs/changelog/v2.3.md @@ -84,10 +84,10 @@ Published: 26.09.2021 at 11:33 Pipes stdout from the left hand command to stdin of the right hand command * [`method`](../commands/method.md): Define a methods supported data-types -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/changelog/v2.4.md b/docs/changelog/v2.4.md index 4ccba5310..3d276ddd4 100644 --- a/docs/changelog/v2.4.md +++ b/docs/changelog/v2.4.md @@ -104,24 +104,24 @@ Published: 09.12.2021 at 08:00 An introduction to Murex modules and packages * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values)
diff --git a/docs/changelog/v2.5.md b/docs/changelog/v2.5.md index 61540a1d8..4609d60c9 100644 --- a/docs/changelog/v2.5.md +++ b/docs/changelog/v2.5.md @@ -58,23 +58,23 @@ Published: 12.02.2022 at 16:16 * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`` Read Named Pipe](../commands/namedpipe.md): +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated) +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): Reads from a Murex named pipe -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings -* [`count`](../commands/count.md): +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): Count items in a map, list or array -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`select`](../optional/select.md): +* [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/changelog/v2.6.md b/docs/changelog/v2.6.md index a85503632..99b00b389 100644 --- a/docs/changelog/v2.6.md +++ b/docs/changelog/v2.6.md @@ -48,14 +48,14 @@ Published: 26.02.2022 at 18:33 ## See Also -* [`autocomplete`](../commands/autocomplete.md): +* [`while`](../commands/while.md): + Loop until condition false +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings -* [`select`](../optional/select.md): +* [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines -* [`while`](../commands/while.md): - Loop until condition false
diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index 2795d35ba..937da98a4 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -82,18 +82,18 @@ Published: 15.05.2022 at 22:49 Special variables reserved by Murex * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`function`](../commands/function.md): Define a function block -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [`read`](../commands/read.md): - `read` a line of input from the user and store as a variable * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [io.input: `read`](../commands/read.md): + `read` a line of input from the user and store as a variable +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open`
diff --git a/docs/changelog/v2.8.md b/docs/changelog/v2.8.md index dc0e7ab1b..70b75ae21 100644 --- a/docs/changelog/v2.8.md +++ b/docs/changelog/v2.8.md @@ -40,14 +40,14 @@ Published: 23.05.2022 at 22:23 Special variables reserved by Murex * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`function`](../commands/function.md): Define a function block * [`jsonc`](../types/jsonc.md): Concatenated JSON * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v2.9.md b/docs/changelog/v2.9.md index bbd36e99d..0ae79f56d 100644 --- a/docs/changelog/v2.9.md +++ b/docs/changelog/v2.9.md @@ -68,10 +68,6 @@ Published: 15.07.2022 at 20:35 Writes stdin to disk - appending contents if file already exists * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`function`](../commands/function.md): Define a function block * [`murex-docs`](../commands/murex-docs.md): @@ -84,8 +80,12 @@ Published: 15.07.2022 at 20:35 Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/changelog/v3.0.md b/docs/changelog/v3.0.md index c906cd969..52fe87d9b 100644 --- a/docs/changelog/v3.0.md +++ b/docs/changelog/v3.0.md @@ -100,14 +100,8 @@ Published: 31.12.2022 at 08:10 * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array * [`break`](../commands/break.md): Terminate execution of a block within your processes scope -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`continue`](../commands/continue.md): Terminate process of a block within a caller function * [`expr`](../commands/expr.md): @@ -120,12 +114,18 @@ Published: 31.12.2022 at 08:10 A sophisticated yet simply way to build a JSON array * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`prepend`](../commands/prepend.md): - Add data to the start of an array -* [`regexp`](../commands/regexp.md): - Regexp tools for arrays / lists of strings * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): + Add data to the start of an array +* [list.regex: `regexp`](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/changelog/v4.0.md b/docs/changelog/v4.0.md index b4b22d8e5..e42c5b7af 100644 --- a/docs/changelog/v4.0.md +++ b/docs/changelog/v4.0.md @@ -82,8 +82,6 @@ Published: 26.03.2023 at 17:50 Quickly generate arrays * [`%{}` Object Builder](../parser/create-object.md): Quickly generate objects (dictionaries / maps) -* [`count`](../commands/count.md): - Count items in a map, list or array * [`function`](../commands/function.md): Define a function block * [`path`](../types/path.md): @@ -92,6 +90,8 @@ Published: 26.03.2023 at 17:50 Structured array for working with `$PATH` style data * [`string` (stringing)](../types/str.md): string (primitive) +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/changelog/v4.2.md b/docs/changelog/v4.2.md index 95f9f69d1..ceea51bd8 100644 --- a/docs/changelog/v4.2.md +++ b/docs/changelog/v4.2.md @@ -74,22 +74,22 @@ Published: 19.06.2023 at 23:15 A list of all the terminal hotkeys and their uses * [`alias`](../commands/alias.md): Create an alias for a command -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data * [`method`](../commands/method.md): Define a methods supported data-types -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`while`](../commands/while.md): Loop until condition false +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index 7d0c77767..01dcd0939 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -28,14 +28,14 @@ Published: 02.07.2023 at 09:55 ## See Also -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/changelog/v4.4.md b/docs/changelog/v4.4.md index e0028c8f4..a585767e6 100644 --- a/docs/changelog/v4.4.md +++ b/docs/changelog/v4.4.md @@ -138,10 +138,6 @@ Published: 27.07.2023 at 23:12 How to track what code was loaded and from where * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`expr`](../commands/expr.md): @@ -150,8 +146,6 @@ Published: 27.07.2023 at 23:12 Define a function block * [`int`](../types/int.md): Whole number (primitive) -* [`man-get-flags` ](../commands/man-get-flags.md): - Parses man page files for command line flags * [`num` (number)](../types/num.md): Floating point number (primitive) * [`onCommandCompletion`](../events/oncommandcompletion.md): @@ -160,10 +154,16 @@ Published: 27.07.2023 at 23:12 Define a private function block * [`return`](../commands/return.md): Exits current function scope -* [`round`](../commands/round.md): - Round a number by a user defined precision * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): + Parses man page files for command line flags +* [num.round: `round`](../commands/round.md): + Round a number by a user defined precision +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/changelog/v5.0.md b/docs/changelog/v5.0.md index e44e33074..3d788d2ee 100644 --- a/docs/changelog/v5.0.md +++ b/docs/changelog/v5.0.md @@ -99,10 +99,6 @@ Published: 07.09.2023 at 00:12 Meta information about the running scope. * [`alias`](../commands/alias.md): Create an alias for a command -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`csv`](../types/csv.md): CSV files (and other character delimited tables) * [`event`](../commands/event.md): @@ -111,14 +107,18 @@ Published: 07.09.2023 at 00:12 Floating point number (primitive) * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-package`](../commands/murex-package.md): - Murex's package manager * [`onSignalReceived`](../events/onsignalreceived.md): Trap OS signals * [`signal`](../commands/signal.md): Sends a signal RPC * [`which`](../commands/which.md): Locate command origin +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.packages: `murex-package`](../commands/murex-package.md): + Murex's package manager
diff --git a/docs/changelog/v5.1.md b/docs/changelog/v5.1.md index 029d81315..5ffeb3f30 100644 --- a/docs/changelog/v5.1.md +++ b/docs/changelog/v5.1.md @@ -48,7 +48,7 @@ Published: 09.10.2023 at 22:13 ## See Also -* [`debug`](../commands/debug.md): +* [shell.debug: `debug`](../commands/debug.md): Debugging information
diff --git a/docs/changelog/v5.2.md b/docs/changelog/v5.2.md index dae04647e..57d4d8662 100644 --- a/docs/changelog/v5.2.md +++ b/docs/changelog/v5.2.md @@ -88,14 +88,14 @@ Published: 18.11.2023 at 20:59 A list of all the terminal hotkeys and their uses * [`[{ Lambda }]`](../parser/lambda.md): Iterate through structured data -* [`bg`](../commands/bg.md): +* [proc.bg: `bg`](../commands/bg.md): Run processes in the background -* [`count`](../commands/count.md): - Count items in a map, list or array -* [`debug`](../commands/debug.md): - Debugging information -* [`fg`](../commands/fg.md): +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/changelog/v5.3.md b/docs/changelog/v5.3.md index 115f6a54b..567251793 100644 --- a/docs/changelog/v5.3.md +++ b/docs/changelog/v5.3.md @@ -91,16 +91,16 @@ Published: 02.01.2024 at 15:45 * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [`runtime`](../commands/runtime.md): +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/docs/changelog/v6.0.md b/docs/changelog/v6.0.md index efa56a717..f67487df9 100644 --- a/docs/changelog/v6.0.md +++ b/docs/changelog/v6.0.md @@ -46,16 +46,16 @@ Published: 17.02.2024 at 20:47 * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [`runtime`](../commands/runtime.md): +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index f8a16f9b9..dfb7b5120 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -152,32 +152,32 @@ Published: 17.06.2024 at 22:54 What's different about Murex's interactive shell? * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [`debug`](../commands/debug.md): - Debugging information * [`event`](../commands/event.md): Event driven programming for shell scripts * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`key-code`](../commands/key-code.md): Returns character sequences for any key pressed (ie sent from the terminal) -* [`man-summary`](../commands/man-summary.md): - Outputs a man page summary of a command * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`runtime`](../commands/runtime.md): +* [help.man.summary: `man-summary`](../commands/man-summary.md): + Outputs a man page summary of a command +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values)
diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 99123ef0c..8706d5779 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -90,14 +90,14 @@ Published: 19.07.2024 at 08:54 Guide to contributing to Murex * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-package`](../commands/murex-package.md): +* [shell.packages: `murex-package`](../commands/murex-package.md): Murex's package manager +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/docs/commands/2darray.md b/docs/commands/2darray.md index 5f44880a1..c5c6999e0 100644 --- a/docs/commands/2darray.md +++ b/docs/commands/2darray.md @@ -1,4 +1,4 @@ -# `2darray` +# struct.new.2darray: `2darray` > Create a 2D JSON array from multiple input sources @@ -94,7 +94,7 @@ ## Synonyms * `2darray` -* `struct.2darray` +* `struct.new.2darray` ## See Also @@ -103,26 +103,26 @@ Outputs a ranged subset of data from stdin * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`jsplit` ](../commands/jsplit.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): + Add data to the start of an array +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [str.split: `jsplit` ](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [`map`](../commands/map.md): +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.new.map: `map`](../commands/map.md): Creates a map from two data sources -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): - Add data to the start of an array
diff --git a/docs/commands/README.md b/docs/commands/README.md index feadaaebc..57d15c222 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -38,32 +38,14 @@ murex-docs trypipe * [`!` (not)](../commands/not-func.md): Reads the stdin and exit number from previous process and not's it's condition -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`addheading` ](../commands/addheading.md): - Adds headings to a table * [`alias`](../commands/alias.md): Create an alias for a command -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [`and`](../commands/and.md): Returns `true` or `false` depending on whether multiple conditions are met -* [`append`](../commands/append.md): - Add data to the end of an array * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`cast`](../commands/cast.md): @@ -72,58 +54,18 @@ murex-docs trypipe Handles the exception code raised by `try` or `trypipe` * [`cd`](../commands/cd.md): Change (working) directory -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`continue`](../commands/continue.md): Terminate process of a block within a caller function -* [`count`](../commands/count.md): - Count items in a map, list or array -* [`cpuarch`](../commands/cpuarch.md): - Output the hosts CPU architecture -* [`cpucount`](../commands/cpucount.md): - Output the number of CPU cores available on your host -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [`debug`](../commands/debug.md): - Debugging information * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) -* [`err`](../commands/err.md): - Print a line to the stderr -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): - Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): - Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): - Encode or decodes text for the URL * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`exec`](../commands/exec.md): - Runs an executable * [`exit`](../commands/exit.md): Exit murex -* [`exitnum`](../commands/exitnum.md): - Output the exit number of the previous process -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`f`](../commands/f.md): - Lists or filters file system objects (eg files) * [`false`](../commands/false.md): Returns a `false` value -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): - Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`for`](../commands/for.md): A more familiar iteration loop to existing developers * [`foreach`](../commands/foreach.md): @@ -134,132 +76,52 @@ murex-docs trypipe Reformat one data-type into another data-type * [`function`](../commands/function.md): Define a function block -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`global`](../commands/global.md): - Define a global variable and set it's value -* [`history`](../commands/history.md): - Outputs murex's command history * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter * [`key-code`](../commands/key-code.md): Returns character sequences for any key pressed (ie sent from the terminal) -* [`left`](../commands/left.md): - Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`list.case` ](../commands/list.case.md): - Changes the character case of a string or all elements in an array -* [`lockfile`](../commands/lockfile.md): - Create and manage lock files -* [`man-get-flags` ](../commands/man-get-flags.md): - Parses man page files for command line flags -* [`man-summary`](../commands/man-summary.md): - Outputs a man page summary of a command -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`match`](../commands/match.md): - Match an exact value in an array * [`method`](../commands/method.md): Define a methods supported data-types -* [`mjoin` ](../commands/mjoin.md): - Joins a list or array into a single string -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-package`](../commands/murex-package.md): - Murex's package manager * [`murex-parser` ](../commands/murex-parser.md): Runs the Murex parser against a block of code -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): - Forces Murex to rescan $PATH looking for executables * [`null`](../commands/devnull.md): null function. Similar to /dev/null -* [`open-image`](../commands/open-image.md): - Renders bitmap image data on your terminal -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`os`](../commands/os.md): - Output the auto-detected OS name -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`prefix`](../commands/prefix.md): - Prefix a string to every item in a list -* [`prepend`](../commands/prepend.md): - Add data to the start of an array -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable * [`private`](../commands/private.md): Define a private function block -* [`pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written * [`rand`](../commands/rand.md): Random field generator -* [`read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [`regexp`](../commands/regexp.md): - Regexp tools for arrays / lists of strings * [`return`](../commands/return.md): Exits current function scope -* [`right`](../commands/right.md): - Right substring every item in a list -* [`round`](../commands/round.md): - Round a number by a user defined precision * [`runmode`](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`rx`](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`signal`](../commands/signal.md): Sends a signal RPC -* [`source`](../commands/source.md): - Import Murex code from another file of code block -* [`struct-keys`](../commands/struct-keys.md): - Outputs all the keys in a structure as a file path -* [`suffix`](../commands/suffix.md): - Prefix a string to every item in a list -* [`summary` ](../commands/summary.md): - Defines a summary help text for a command * [`switch`](../commands/switch.md): Blocks of cascading conditionals -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [`tabulate`](../commands/tabulate.md): Table transformation tools * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts * [`time`](../commands/time.md): Returns the execution run time of a command or block -* [`tmp`](../commands/tmp.md): - Create a temporary file and write to it -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`tread`](../commands/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) * [`true`](../commands/true.md): @@ -276,12 +138,150 @@ murex-docs trypipe Command type (function, builtin, alias, etc) * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [`version`](../commands/version.md): - Get Murex version * [`which`](../commands/which.md): Locate command origin * [`while`](../commands/while.md): Loop until condition false +* [escape.cli: `esccli`](../commands/esccli.md): + Escapes an array so output is valid shell code +* [escape.html: `eschtml`](../commands/eschtml.md): + Encode or decodes text for HTML +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): + Encode or decodes text for the URL +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.files: `f`](../commands/f.md): + Lists or filters file system objects (eg files) +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [fs.lockfile: `lockfile`](../commands/lockfile.md): + Create and manage lock files +* [fs.new.tmpfile: `tmp`](../commands/tmp.md): + Create a temporary file and write to it +* [fs.open.image: `open-image`](../commands/open-image.md): + Renders bitmap image data on your terminal +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [fs.regex: `rx`](../commands/rx.md): + Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [fs.status: `pt`](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): + Parses man page files for command line flags +* [help.man.summary: `man-summary`](../commands/man-summary.md): + Outputs a man page summary of a command +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.input: `read`](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.case: `list.case` ](../commands/list.case.md): + Changes the character case of a string or all elements in an array +* [list.join: `mjoin` ](../commands/mjoin.md): + Joins a list or array into a single string +* [list.left: `left`](../commands/left.md): + Left substring every item in a list +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prefix: `prefix`](../commands/prefix.md): + Prefix a string to every item in a list +* [list.prepend: `prepend`](../commands/prepend.md): + Add data to the start of an array +* [list.regex: `regexp`](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.right: `right`](../commands/right.md): + Right substring every item in a list +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [list.suffix: `suffix`](../commands/suffix.md): + Prefix a string to every item in a list +* [num.round: `round`](../commands/round.md): + Round a number by a user defined precision +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.exitnum: `exitnum`](../commands/exitnum.md): + Output the exit number of the previous process +* [proc.fg: `fg`](../commands/fg.md): + Sends a background process into the foreground +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [shell.history: `history`](../commands/history.md): + Outputs murex's command history +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` +* [shell.packages: `murex-package`](../commands/murex-package.md): + Murex's package manager +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): + Forces Murex to rescan $PATH looking for executables +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.summary: `summary` ](../commands/summary.md): + Defines a summary help text for a command +* [shell.version: `version`](../commands/version.md): + Get Murex version +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [struct.keys: `struct-keys`](../commands/struct-keys.md): + Outputs all the keys in a structure as a file path +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources +* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): + Output the hosts CPU architecture +* [sys.cpu.count: `cpucount`](../commands/cpucount.md): + Output the number of CPU cores available on your host +* [sys.os: `os`](../commands/os.md): + Output the auto-detected OS name +* [table.new.heading: `addheading` ](../commands/addheading.md): + Adds headings to a table +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value ## Optional Builtins @@ -293,7 +293,7 @@ murex-docs trypipe Compress or decompress a gzip file * [`qr`](../optional/qr.md): Creates a QR code from stdin -* [`select`](../optional/select.md): - Inlining SQL into shell pipelines * [`sleep`](../optional/sleep.md): Suspends the shell for a number of seconds +* [table.select: `select`](../optional/select.md): + Inlining SQL into shell pipelines diff --git a/docs/commands/a.md b/docs/commands/a.md index 6c147d54d..91096510b 100644 --- a/docs/commands/a.md +++ b/docs/commands/a.md @@ -1,4 +1,4 @@ -# `a` (mkarray) +# list.new.str: `a` (mkarray) > A sophisticated yet simple way to build an array or list @@ -159,6 +159,13 @@ arrays. For more details on these please refer to the documents for each format * [Special Ranges](../mkarray/special.md): Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) +## Synonyms + +* `a` +* `mkarray` +* `list.new.str` + + ## See Also * [`%[]` Array Builder](../parser/create-array.md): @@ -169,16 +176,16 @@ arrays. For more details on these please refer to the documents for each format Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): - Reverse the order of an array * [`str` (string)](../types/str.md): string (primitive) -* [`ta` (mkarray)](../commands/ta.md): +* [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/addheading.md b/docs/commands/addheading.md index f84ffdf61..2d61f74ac 100644 --- a/docs/commands/addheading.md +++ b/docs/commands/addheading.md @@ -1,4 +1,4 @@ -# `addheading` +# table.new.heading: `addheading` > Adds headings to a table @@ -22,32 +22,38 @@ prepend to tables. ["Bob","23","true"] ``` +## Synonyms + +* `addheading` +* `table.new.heading` + + ## See Also * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`match`](../commands/match.md): - Match an exact value in an array -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`regexp`](../commands/regexp.md): +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/alias.md b/docs/commands/alias.md index ab2be75b6..a1f7feb4f 100644 --- a/docs/commands/alias.md +++ b/docs/commands/alias.md @@ -123,28 +123,28 @@ You can override this order of precedence via the `fexec` and `exec` builtins. ## See Also -* [`exec`](../commands/exec.md): - Runs an executable -* [`export`](../commands/export.md): - Define an environmental variable and set it's value -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`function`](../commands/function.md): Define a function block -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`method`](../commands/method.md): Define a methods supported data-types * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value -* [`source`](../commands/source.md): - Import Murex code from another file of code block
diff --git a/docs/commands/alter.md b/docs/commands/alter.md index bd8120fcd..d3e94ab69 100644 --- a/docs/commands/alter.md +++ b/docs/commands/alter.md @@ -1,4 +1,4 @@ -# `alter` +# struct.alter: `alter` > Change a value within a structured data-type and pass that change along the pipeline without altering the original source input @@ -181,6 +181,7 @@ Marshallers are enabled at compile time from the `builtins/data-types` directory * `alter` * `~>` +* `struct.alter` ## See Also @@ -191,17 +192,17 @@ Marshallers are enabled at compile time from the `builtins/data-types` directory Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`append`](../commands/append.md): - Add data to the end of an array * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`runtime`](../commands/runtime.md): +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/append.md b/docs/commands/append.md index 34b5ee45a..52e21cc80 100644 --- a/docs/commands/append.md +++ b/docs/commands/append.md @@ -1,4 +1,4 @@ -# `append` +# list.append: `append` > Add data to the end of an array @@ -51,26 +51,26 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`addheading` ](../commands/addheading.md): - Adds headings to a table * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`match`](../commands/match.md): - Match an exact value in an array -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`regexp`](../commands/regexp.md): +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [table.new.heading: `addheading` ](../commands/addheading.md): + Adds headings to a table
diff --git a/docs/commands/autocomplete.md b/docs/commands/autocomplete.md index 972812290..60c564c7d 100644 --- a/docs/commands/autocomplete.md +++ b/docs/commands/autocomplete.md @@ -1,4 +1,4 @@ -# `autocomplete` +# shell.autocomplete: `autocomplete` > Set definitions for tab-completion in the command line @@ -604,6 +604,12 @@ for that command rather than for `sudo` itself. Specifies if a match is required for the index in this schema. ie optional flags. +## Synonyms + +* `autocomplete` +* `shell.autocomplete` + + ## See Also * [``](../commands/stdin.md): @@ -612,20 +618,20 @@ flags. Outputs an element from an array, map or table * [`alias`](../commands/alias.md): Create an alias for a command -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`function`](../commands/function.md): Define a function block * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe * [`private`](../commands/private.md): Define a private function block -* [`summary` ](../commands/summary.md): - Defines a summary help text for a command * [`switch`](../commands/switch.md): Blocks of cascading conditionals * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.summary: `summary` ](../commands/summary.md): + Defines a summary help text for a command
diff --git a/docs/commands/bexists.md b/docs/commands/bexists.md index 958107e30..c90350c5e 100644 --- a/docs/commands/bexists.md +++ b/docs/commands/bexists.md @@ -1,4 +1,4 @@ -# `bexists` +# shell.builtins.exist: `bexists` > Check which builtins exist @@ -38,13 +38,18 @@ a number of similar commands which have since been deprecated. The same fate might also happen to `bexists` however it is in use by a few modules and for that reason alone it has been spared from the axe. +## Synonyms + +* `bexists` + + ## See Also * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/bg.md b/docs/commands/bg.md index 07060a3b3..b3c396cf4 100644 --- a/docs/commands/bg.md +++ b/docs/commands/bg.md @@ -1,4 +1,4 @@ -# `bg` +# proc.bg: `bg` > Run processes in the background @@ -33,19 +33,25 @@ supported on POSIX systems due to the limitation of required signals on non-platforms. This means the usage described in the examples is cross cross platform while `bg int` currently does not work on Windows nor Plan 9. +## Synonyms + +* `bg` +* `proc.bg` + + ## See Also -* [`exec`](../commands/exec.md): +* [exec.file: `exec`](../commands/exec.md): Runs an executable -* [`fg`](../commands/fg.md): +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/break.md b/docs/commands/break.md index 13c88db71..c4a24f80c 100644 --- a/docs/commands/break.md +++ b/docs/commands/break.md @@ -110,12 +110,12 @@ Error in `break` (7,17): no block found named `bar` within the scope of `foo` Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block * [`return`](../commands/return.md): Exits current function scope +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/cast.md b/docs/commands/cast.md index 02da638b0..d174b8cd9 100644 --- a/docs/commands/cast.md +++ b/docs/commands/cast.md @@ -70,10 +70,10 @@ instead. Quickly generate objects (dictionaries / maps) * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/cd.md b/docs/commands/cd.md index 4f031a9f7..29f086851 100644 --- a/docs/commands/cd.md +++ b/docs/commands/cd.md @@ -81,8 +81,8 @@ config set shell auto-cd true * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`source`](../commands/source.md): - Import Murex code from another file of code block +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block
diff --git a/docs/commands/config.md b/docs/commands/config.md index 0bc177666..e8f33235b 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -1,4 +1,4 @@ -# `config` +# shell.config: `config` > Query or define Murex runtime settings @@ -231,6 +231,8 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, * `config` * `!config` +* `shell.config` +* `!shell.config` ## See Also @@ -241,10 +243,6 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`append`](../commands/append.md): - Add data to the end of an array * [`event`](../commands/event.md): Event driven programming for shell scripts * [`function`](../commands/function.md): @@ -253,14 +251,18 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`match`](../commands/match.md): - Match an exact value in an array -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`runtime`](../commands/runtime.md): +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/commands/continue.md b/docs/commands/continue.md index 5b297d27c..b5a09f58c 100644 --- a/docs/commands/continue.md +++ b/docs/commands/continue.md @@ -88,12 +88,12 @@ Error in `continue` (7,17): no block found named `bar` within the scope of `foo` Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block * [`return`](../commands/return.md): Exits current function scope +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/count.md b/docs/commands/count.md index e924255a2..3049e18a2 100644 --- a/docs/commands/count.md +++ b/docs/commands/count.md @@ -1,10 +1,14 @@ -# `count` +# struct.count: `count` > Count items in a map, list or array ## Description +Counts the number of items in a structure, be that a list, map or other object +type. +`count` has several modes ranging from updating values in place, returning new +structures, or just outputting totals. ## Usage @@ -133,7 +137,7 @@ unique count should be one less than the total count: * `count` * `len` -* `list.count` +* `struct.count` ## See Also @@ -144,28 +148,28 @@ unique count should be one less than the total count: Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prepend: `prepend`](../commands/prepend.md): + Add data to the start of an array +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [str.split: `jsplit` ](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [`jsplit` ](../commands/jsplit.md): +* [str.split: `jsplit` ](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [`map`](../commands/map.md): +* [struct.new.map: `map`](../commands/map.md): Creates a map from two data sources -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): - Add data to the start of an array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type
diff --git a/docs/commands/cpuarch.md b/docs/commands/cpuarch.md index c38ee022b..7ea49a8e7 100644 --- a/docs/commands/cpuarch.md +++ b/docs/commands/cpuarch.md @@ -1,4 +1,4 @@ -# `cpuarch` +# sys.cpu.arch: `cpuarch` > Output the hosts CPU architecture @@ -27,9 +27,9 @@ amd64 ## See Also -* [`cpucount`](../commands/cpucount.md): +* [sys.cpu.count: `cpucount`](../commands/cpucount.md): Output the number of CPU cores available on your host -* [`os`](../commands/os.md): +* [sys.os: `os`](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/cpucount.md b/docs/commands/cpucount.md index 43b4f4cce..1c6a80865 100644 --- a/docs/commands/cpucount.md +++ b/docs/commands/cpucount.md @@ -1,4 +1,4 @@ -# `cpucount` +# sys.cpu.count: `cpucount` > Output the number of CPU cores available on your host @@ -27,9 +27,9 @@ cpucount -> ## See Also -* [`cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): Output the hosts CPU architecture -* [`os`](../commands/os.md): +* [sys.os: `os`](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/datetime.md b/docs/commands/datetime.md index 4c0adfaac..c0d5bda92 100644 --- a/docs/commands/datetime.md +++ b/docs/commands/datetime.md @@ -1,4 +1,4 @@ -# `datetime` +# str.datetime: `datetime` > A date and/or time conversion tool (like `printf` but for date and time values) @@ -81,11 +81,17 @@ Documentation regarding these format codes can be found on [pkg.go.dev](https:// This is only supported as an input. When it is used `--value` flag is not required. +## Synonyms + +* `datetime` +* `str.datetime` + + ## See Also * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`a` (mkarray)](../commands/a.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): A sophisticated yet simple way to build an array or list
diff --git a/docs/commands/debug.md b/docs/commands/debug.md index 816c84b8a..e717c70e5 100644 --- a/docs/commands/debug.md +++ b/docs/commands/debug.md @@ -1,4 +1,4 @@ -# `debug` +# shell.debug: `debug` > Debugging information @@ -186,12 +186,18 @@ this via: debug panic ``` +## Synonyms + +* `debug` +* `shell.debug` + + ## See Also -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/err.md b/docs/commands/err.md index fe0bcf646..db4084432 100644 --- a/docs/commands/err.md +++ b/docs/commands/err.md @@ -1,4 +1,4 @@ -# `err` +# io.err: `err` > Print a line to the stderr @@ -49,32 +49,38 @@ a new Murex named pipe. `err` supports ANSI constants. +## Synonyms + +* `err` +* `io.err` + + ## See Also * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences * [`(brace quote)`](../parser/brace-quote-func.md): Write a string to the stdout without new line (deprecated) -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists -* [`bg`](../commands/bg.md): - Run processes in the background * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`pt`](../commands/pt.md): +* [fs.status: `pt`](../commands/pt.md): Pipe telemetry. Writes data-types and bytes written -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable
diff --git a/docs/commands/escape.md b/docs/commands/escape.md index 51c916e6b..b13d37dca 100644 --- a/docs/commands/escape.md +++ b/docs/commands/escape.md @@ -1,4 +1,4 @@ -# `escape` +# escape.quote: `escape` > Escape or unescape input @@ -49,11 +49,11 @@ escape string to escape -> ## See Also -* [`esccli`](../commands/esccli.md): +* [escape.cli: `esccli`](../commands/esccli.md): Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): +* [escape.html: `eschtml`](../commands/eschtml.md): Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): +* [escape.url: `escurl`](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/commands/esccli.md b/docs/commands/esccli.md index 0564c2597..5c2b49910 100644 --- a/docs/commands/esccli.md +++ b/docs/commands/esccli.md @@ -1,4 +1,4 @@ -# `esccli` +# escape.cli: `esccli` > Escapes an array so output is valid shell code @@ -53,13 +53,13 @@ out foo\$b\@r Outputs an element from an array, map or table * [`alias`](../commands/alias.md): Create an alias for a command -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`eschtml`](../commands/eschtml.md): +* [escape.html: `eschtml`](../commands/eschtml.md): Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): Encode or decodes text for the URL -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/eschtml.md b/docs/commands/eschtml.md index d244a8cd3..7f087b31b 100644 --- a/docs/commands/eschtml.md +++ b/docs/commands/eschtml.md @@ -1,4 +1,4 @@ -# `eschtml` +# escape.html: `eschtml` > Encode or decodes text for HTML @@ -54,18 +54,18 @@ eschtml string to escape -> ## See Also -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): - Escapes an array so output is valid shell code -* [`escurl`](../commands/escurl.md): - Encode or decodes text for the URL * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return +* [escape.cli: `esccli`](../commands/esccli.md): + Escapes an array so output is valid shell code +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): + Encode or decodes text for the URL
diff --git a/docs/commands/escurl.md b/docs/commands/escurl.md index 14b26e708..8b1e5ff29 100644 --- a/docs/commands/escurl.md +++ b/docs/commands/escurl.md @@ -1,4 +1,4 @@ -# `escurl` +# escape.url: `escurl` > Encode or decodes text for the URL @@ -54,18 +54,18 @@ out '%21%3F%20%3C%3E%0A' -> !escurl ## See Also -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): - Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): - Encode or decodes text for HTML * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return +* [escape.cli: `esccli`](../commands/esccli.md): + Escapes an array so output is valid shell code +* [escape.html: `eschtml`](../commands/eschtml.md): + Encode or decodes text for HTML +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input
diff --git a/docs/commands/event.md b/docs/commands/event.md index 11009ee48..c7907afbf 100644 --- a/docs/commands/event.md +++ b/docs/commands/event.md @@ -109,11 +109,11 @@ onSecondsElapsed Iterate through a map or other collection of data * [`function`](../commands/function.md): Define a function block -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`private`](../commands/private.md): Define a private function block -* [`runtime`](../commands/runtime.md): +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/exec.md b/docs/commands/exec.md index dcd3223ed..f4e15e658 100644 --- a/docs/commands/exec.md +++ b/docs/commands/exec.md @@ -1,4 +1,4 @@ -# `exec` +# exec.file: `exec` > Runs an executable @@ -70,31 +70,32 @@ alias for `exec`. * `exec` * `command` +* `exec.file` ## See Also -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background -* [`builtins`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.builtins: `builtins`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/exitnum.md b/docs/commands/exitnum.md index 0cb741dd0..4e1ae16d2 100644 --- a/docs/commands/exitnum.md +++ b/docs/commands/exitnum.md @@ -1,4 +1,4 @@ -# `exitnum` +# proc.exitnum: `exitnum` > Output the exit number of the previous process @@ -19,12 +19,18 @@ exitnum -> 0 ``` +## Synonyms + +* `exitnum` +* `proc.exitnum` + + ## See Also -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/export.md b/docs/commands/export.md index a57ceab41..44c91ccc0 100644 --- a/docs/commands/export.md +++ b/docs/commands/export.md @@ -1,4 +1,4 @@ -# `export` +# var.env: `export` > Define an environmental variable and set it's value @@ -265,6 +265,8 @@ bar * `export` * `!export` * `unset` +* `var.env` +* `!var.env` ## See Also @@ -279,11 +281,11 @@ bar Returns the right operand if the left operand is empty / undefined (expression) * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [`set`](../commands/set.md): +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/expr.md b/docs/commands/expr.md index 0187be235..cf30129c7 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -338,9 +338,9 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { Returns the right operand if the left operand is falsy (expression) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/f.md b/docs/commands/f.md index 35271efb9..db51e5f40 100644 --- a/docs/commands/f.md +++ b/docs/commands/f.md @@ -1,4 +1,4 @@ -# `f` +# fs.files: `f` > Lists or filters file system objects (eg files) @@ -110,13 +110,19 @@ rx '\.(txt|md)' -> f +fw `+` flags are always matched first. Then the `-` flags are used to filter out any matches from the `+` flags. +## Synonyms + +* `f` +* `fs.files` + + ## See Also -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`rx`](../commands/rx.md): +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [fs.regex: `rx`](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`)
diff --git a/docs/commands/fexec.md b/docs/commands/fexec.md index 413e5ff26..547e776ae 100644 --- a/docs/commands/fexec.md +++ b/docs/commands/fexec.md @@ -1,4 +1,4 @@ -# `fexec` +# exec.*: `fexec` > Execute a command or function, bypassing the usual order of precedence. @@ -73,34 +73,37 @@ alias to `fexec builtin` * `fexec` * `builtin` +* `exec.builtin` +* `exec.function` +* `exec.private` ## See Also * [`alias`](../commands/alias.md): Create an alias for a command -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`bg`](../commands/bg.md): - Run processes in the background -* [`builtins`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`exec`](../commands/exec.md): - Runs an executable -* [`fg`](../commands/fg.md): - Sends a background process into the foreground * [`function`](../commands/function.md): Define a function block -* [`jobs`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`private`](../commands/private.md): Define a private function block -* [`source`](../commands/source.md): - Import Murex code from another file of code block +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): + Sends a background process into the foreground +* [proc.list: `jobs`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.builtins: `builtins`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/fg.md b/docs/commands/fg.md index 270a2ee8b..09ced0c18 100644 --- a/docs/commands/fg.md +++ b/docs/commands/fg.md @@ -1,4 +1,4 @@ -# `fg` +# proc.fg: `fg` > Sends a background process into the foreground @@ -19,19 +19,25 @@ fg fid This builtin is only supported on POSIX systems. There is no support planned for Windows (due to the kernel not supporting the right signals) nor Plan 9. +## Synonyms + +* `fg` +* `proc.fg` + + ## See Also -* [`bg`](../commands/bg.md): - Run processes in the background -* [`exec`](../commands/exec.md): +* [exec.file: `exec`](../commands/exec.md): Runs an executable -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/fid-kill.md b/docs/commands/fid-kill.md index 8f0e6f97f..226abd0b7 100644 --- a/docs/commands/fid-kill.md +++ b/docs/commands/fid-kill.md @@ -1,4 +1,4 @@ -# `fid-kill` +# proc.kill: `fid-kill` > Terminate a running Murex function @@ -24,27 +24,33 @@ which were launched within the current Murex shell). The FID (function ID) sent is not the same as a POSIX (eg Linux, macOS, BSD) PID (process ID). You can obtain a FID from `fid-list`. +## Synonyms + +* `fid-kill` +* `proc.kill` + + ## See Also -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background -* [`builtins`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-killall`](../commands/fid-killall.md): +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.builtins: `builtins`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/fid-killall.md b/docs/commands/fid-killall.md index 16bf53ecb..bed6c0e3e 100644 --- a/docs/commands/fid-killall.md +++ b/docs/commands/fid-killall.md @@ -1,4 +1,4 @@ -# `fid-killall` +# proc.kill.all: `fid-killall` > Terminate _all_ running Murex functions @@ -25,27 +25,33 @@ which were launched within the current Murex shell). The FID (function ID) sent is not the same as a POSIX (eg Linux, macOS, BSD) PID (process ID). You can obtain a FID from `fid-list`. +## Synonyms + +* `fid.killall` +* `proc.kill.all` + + ## See Also -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background -* [`builtins`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): Terminate a running Murex function -* [`fid-list`](../commands/fid-list.md): +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.builtins: `builtins`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/fid-list.md b/docs/commands/fid-list.md index 0893c090d..c430fc7cf 100644 --- a/docs/commands/fid-list.md +++ b/docs/commands/fid-list.md @@ -1,4 +1,4 @@ -# `fid-list` +# proc.list: `fid-list` > Lists all running functions within the current Murex session @@ -60,35 +60,37 @@ include: * `fid-list` * `jobs` +* `proc.list` +* `proc.jobs` ## See Also * [`*` (generic)](../types/generic.md): generic (primitive) -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background -* [`builtins`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): +* [`jsonl`](../types/jsonl.md): + JSON Lines +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [`jobs`](../commands/fid-list.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jsonl`](../types/jsonl.md): - JSON Lines -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.builtins: `builtins`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/for.md b/docs/commands/for.md index b4fcd16e0..43b687b5b 100644 --- a/docs/commands/for.md +++ b/docs/commands/for.md @@ -191,8 +191,6 @@ jsonl ## See Also -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`foreach`](../commands/foreach.md): @@ -205,10 +203,12 @@ jsonl A sophisticated yet simply way to build a JSON array * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`while`](../commands/while.md): Loop until condition false +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/commands/foreach.md b/docs/commands/foreach.md index 468eb5d3e..2b9279fd0 100644 --- a/docs/commands/foreach.md +++ b/docs/commands/foreach.md @@ -324,14 +324,10 @@ jsonl Read from a data type one array element at a time and return the elements contents and data type * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`debug`](../commands/debug.md): - Debugging information * [`for`](../commands/for.md): A more familiar iteration loop to existing developers * [`formap`](../commands/formap.md): @@ -346,14 +342,18 @@ jsonl JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`left`](../commands/left.md): - Left substring every item in a list -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`while`](../commands/while.md): Loop until condition false * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [list.left: `left`](../commands/left.md): + Left substring every item in a list +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [shell.debug: `debug`](../commands/debug.md): + Debugging information
diff --git a/docs/commands/formap.md b/docs/commands/formap.md index 5bfc246a5..e8231a001 100644 --- a/docs/commands/formap.md +++ b/docs/commands/formap.md @@ -114,12 +114,12 @@ The following meta values are defined: Iterate through an array * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`tabulate`](../commands/tabulate.md): Table transformation tools * [`while`](../commands/while.md): Loop until condition false +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/commands/format.md b/docs/commands/format.md index 24ddbc279..381a87485 100644 --- a/docs/commands/format.md +++ b/docs/commands/format.md @@ -30,7 +30,7 @@ Two: 2 Converts a structured file format into structured memory * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type
diff --git a/docs/commands/function.md b/docs/commands/function.md index 5a502bd77..4457fac33 100644 --- a/docs/commands/function.md +++ b/docs/commands/function.md @@ -252,28 +252,28 @@ You can override this order of precedence via the `fexec` and `exec` builtins. Command line flag parser for Murex shell scripting * [`break`](../commands/break.md): Terminate execution of a block within your processes scope -* [`exec`](../commands/exec.md): - Runs an executable -* [`export`](../commands/export.md): - Define an environmental variable and set it's value -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`method`](../commands/method.md): Define a methods supported data-types * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value -* [`source`](../commands/source.md): - Import Murex code from another file of code block -* [`version`](../commands/version.md): +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [shell.version: `version`](../commands/version.md): Get Murex version +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/commands/g.md b/docs/commands/g.md index 1504d49a3..c09b62893 100644 --- a/docs/commands/g.md +++ b/docs/commands/g.md @@ -1,4 +1,4 @@ -# `g` +# fs.glob: `g` > Glob pattern matching for file system objects (eg `*.txt`) @@ -132,18 +132,20 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. * `g` * `!g` +* `fs.glob` +* `!fs.glob` ## See Also -* [`f`](../commands/f.md): +* [fs.files: `f`](../commands/f.md): Lists or filters file system objects (eg files) -* [`match`](../commands/match.md): - Match an exact value in an array -* [`regexp`](../commands/regexp.md): - Regexp tools for arrays / lists of strings -* [`rx`](../commands/rx.md): +* [fs.regex: `rx`](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [list.regex: `regexp`](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [list.str: `match`](../commands/match.md): + Match an exact value in an array
diff --git a/docs/commands/get-type.md b/docs/commands/get-type.md index 670d298fe..fd37d564d 100644 --- a/docs/commands/get-type.md +++ b/docs/commands/get-type.md @@ -55,18 +55,18 @@ json Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`debug`](../commands/debug.md): - Debugging information * [`function`](../commands/function.md): Define a function block -* [`pipe`](../commands/pipe.md): +* [io.new.pipe: `pipe`](../commands/pipe.md): Manage Murex named pipes -* [`runtime`](../commands/runtime.md): +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type
diff --git a/docs/commands/get.md b/docs/commands/get.md index c80238c3b..f789f1aec 100644 --- a/docs/commands/get.md +++ b/docs/commands/get.md @@ -99,12 +99,12 @@ This enables sane, repeatable and readable defaults. Read the documents on Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/commands/getfile.md b/docs/commands/getfile.md index 6ccef2012..45b82b0d8 100644 --- a/docs/commands/getfile.md +++ b/docs/commands/getfile.md @@ -76,14 +76,14 @@ This enables sane, repeatable and readable defaults. Read the documents on ## See Also -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/commands/global.md b/docs/commands/global.md index 2518cdbbb..92a718f4e 100644 --- a/docs/commands/global.md +++ b/docs/commands/global.md @@ -1,4 +1,4 @@ -# `global` +# var.global: `global` > Define a global variable and set it's value @@ -249,6 +249,8 @@ bar * `global` * `!global` +* `var.global` +* `!var.global` ## See Also @@ -265,13 +267,13 @@ bar Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [`set`](../commands/set.md): +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/history.md b/docs/commands/history.md index bdecc7be9..8dcd92350 100644 --- a/docs/commands/history.md +++ b/docs/commands/history.md @@ -1,4 +1,4 @@ -# `history` +# shell.history: `history` > Outputs murex's command history @@ -39,11 +39,17 @@ history -> The history file is typically located on disk in a file called `~/.murex.history`. +## Synonyms + +* `history` +* `shell.history` + + ## See Also -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/if.md b/docs/commands/if.md index 426554055..38aba372b 100644 --- a/docs/commands/if.md +++ b/docs/commands/if.md @@ -133,8 +133,6 @@ code block as false. Otherwise, it will be considered true. Returns `true` or `false` depending on whether multiple conditions are met * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`debug`](../commands/debug.md): - Debugging information * [`false`](../commands/false.md): Returns a `false` value * [`or`](../commands/or.md): @@ -149,6 +147,8 @@ code block as false. Otherwise, it will be considered true. Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline +* [shell.debug: `debug`](../commands/debug.md): + Debugging information
diff --git a/docs/commands/is-null.md b/docs/commands/is-null.md index cb0f25116..5d3d7e224 100644 --- a/docs/commands/is-null.md +++ b/docs/commands/is-null.md @@ -57,11 +57,11 @@ if { is-null foobar } then { How scoping works within Murex * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`export`](../commands/export.md): +* [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value -* [`global`](../commands/global.md): +* [var.global: `global`](../commands/global.md): Define a global variable and set it's value -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/ja.md b/docs/commands/ja.md index 3dbfe6fb3..a759546fa 100644 --- a/docs/commands/ja.md +++ b/docs/commands/ja.md @@ -64,16 +64,16 @@ Please read the documentation on `a` for a more detailed breakdown on of Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`ta` (mkarray)](../commands/ta.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/jsplit.md b/docs/commands/jsplit.md index 2b8e0bd77..42f77d401 100644 --- a/docs/commands/jsplit.md +++ b/docs/commands/jsplit.md @@ -1,4 +1,4 @@ -# `jsplit` +# str.split: `jsplit` > Splits stdin into a JSON array based on a regex parameter @@ -38,35 +38,35 @@ unwanted "noise" is stripped from the output. ## Synonyms * `jsplit` -* `list.split` +* `str.split` ## See Also -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources
diff --git a/docs/commands/key-code.md b/docs/commands/key-code.md index d33c0f049..033f54ec0 100644 --- a/docs/commands/key-code.md +++ b/docs/commands/key-code.md @@ -63,7 +63,7 @@ event onKeyPress close=$key { Event driven programming for shell scripts * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type
diff --git a/docs/commands/left.md b/docs/commands/left.md index 4a508c09d..7d5d65222 100644 --- a/docs/commands/left.md +++ b/docs/commands/left.md @@ -1,4 +1,4 @@ -# `left` +# list.left: `left` > Left substring every item in a list @@ -56,24 +56,24 @@ runtime --unmarshallers ## See Also -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [`prefix`](../commands/prefix.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`right`](../commands/right.md): +* [list.right: `right`](../commands/right.md): Right substring every item in a list -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`suffix`](../commands/suffix.md): +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/let.md b/docs/commands/let.md index a91ad0069..6dce65d0d 100644 --- a/docs/commands/let.md +++ b/docs/commands/let.md @@ -407,15 +407,15 @@ bar Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`set`](../commands/set.md): +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/list.case.md b/docs/commands/list.case.md index 660633c6b..e98bbc80a 100644 --- a/docs/commands/list.case.md +++ b/docs/commands/list.case.md @@ -1,4 +1,4 @@ -# `list.case` +# list.case: `list.case` > Changes the character case of a string or all elements in an array diff --git a/docs/commands/lockfile.md b/docs/commands/lockfile.md index eab96954d..cbb89e254 100644 --- a/docs/commands/lockfile.md +++ b/docs/commands/lockfile.md @@ -1,4 +1,4 @@ -# `lockfile` +# fs.lockfile: `lockfile` > Create and manage lock files @@ -48,12 +48,18 @@ lockfile wait example out "lock file gone!" ``` +## Synonyms + +* `lockfile` +* `fs.lockfile` + + ## See Also -* [`bg`](../commands/bg.md): - Run processes in the background -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background
diff --git a/docs/commands/man-get-flags.md b/docs/commands/man-get-flags.md index 386344277..6d8350e1c 100644 --- a/docs/commands/man-get-flags.md +++ b/docs/commands/man-get-flags.md @@ -1,4 +1,4 @@ -# `man-get-flags` +# help.man.flags: `man-get-flags` > Parses man page files for command line flags @@ -52,13 +52,19 @@ have to parse command line parameters however they wish, there will always be a margin for error with how reliably any parser can autodetect parameters. one requirement is that flags are hyphen prefixed, eg `--flag`. +## Synonyms + +* `man-get-flags` +* `help.man.flags` + + ## See Also -* [`man-summary`](../commands/man-summary.md): - Outputs a man page summary of a command * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`summary` ](../commands/summary.md): +* [help.man.summary: `man-summary`](../commands/man-summary.md): + Outputs a man page summary of a command +* [shell.summary: `summary` ](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/man-summary.md b/docs/commands/man-summary.md index 40cb2ab1d..5a7dac311 100644 --- a/docs/commands/man-summary.md +++ b/docs/commands/man-summary.md @@ -1,4 +1,4 @@ -# `man-summary` +# help.man.summary: `man-summary` > Outputs a man page summary of a command @@ -38,15 +38,21 @@ ae - no man page exists 2 ``` +## Synonyms + +* `man-summary` +* `help.man.summary` + + ## See Also -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`man-get-flags` ](../commands/man-get-flags.md): - Parses man page files for command line flags * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`summary` ](../commands/summary.md): +* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): + Parses man page files for command line flags +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.summary: `summary` ](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/map.md b/docs/commands/map.md index a14d029b2..1288fa663 100644 --- a/docs/commands/map.md +++ b/docs/commands/map.md @@ -1,4 +1,4 @@ -# `map` +# struct.new.map: `map` > Creates a map from two data sources @@ -25,6 +25,12 @@ map { code-block } { code-block } -> } ``` +## Synonyms + +* `map` +* `struct.new.map` + + ## See Also * [`[ ..Range ]`](../parser/range.md): @@ -33,20 +39,20 @@ map { code-block } { code-block } -> Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/match.md b/docs/commands/match.md index 566e9970f..11c2701d5 100644 --- a/docs/commands/match.md +++ b/docs/commands/match.md @@ -1,4 +1,4 @@ -# `match` +# list.str: `match` > Match an exact value in an array @@ -70,40 +70,40 @@ same data-type. * `match` * `!match` -* `list.string` -* `!list.string` +* `list.str` +* `!list.str` ## See Also -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`prefix`](../commands/prefix.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`prepend`](../commands/prepend.md): +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`regexp`](../commands/regexp.md): +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [`suffix`](../commands/suffix.md): +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources
diff --git a/docs/commands/method.md b/docs/commands/method.md index a22a731b9..6c28bb347 100644 --- a/docs/commands/method.md +++ b/docs/commands/method.md @@ -72,13 +72,13 @@ var GroupMath = []string{ Pipes stdout from the left hand command to stdin of the right hand command * [`alias`](../commands/alias.md): Create an alias for a command -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`function`](../commands/function.md): Define a function block * [`private`](../commands/private.md): Define a private function block -* [`runtime`](../commands/runtime.md): +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/mjoin.md b/docs/commands/mjoin.md index 98a6b6536..3746e9789 100644 --- a/docs/commands/mjoin.md +++ b/docs/commands/mjoin.md @@ -1,4 +1,4 @@ -# `mjoin` +# list.join: `mjoin` > Joins a list or array into a single string @@ -45,7 +45,7 @@ Monday!Tuesday!Wednesday!Thursday!Friday Quickly generate arrays * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`jsplit` ](../commands/jsplit.md): +* [str.split: `jsplit` ](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter
diff --git a/docs/commands/msort.md b/docs/commands/msort.md index 697c11179..e87641305 100644 --- a/docs/commands/msort.md +++ b/docs/commands/msort.md @@ -1,4 +1,4 @@ -# `msort` +# list.sort: `msort` > Sorts an array - data type agnostic @@ -60,22 +60,22 @@ output of `msort` into another builtin: Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/mtac.md b/docs/commands/mtac.md index c55531a11..cb5318007 100644 --- a/docs/commands/mtac.md +++ b/docs/commands/mtac.md @@ -1,4 +1,4 @@ -# `mtac` +# list.reverse: `mtac` > Reverse the order of an array @@ -60,32 +60,32 @@ stdin is a long running process or non-standard stream (eg network pipe). ## See Also -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`prefix`](../commands/prefix.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`prepend`](../commands/prepend.md): +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`suffix`](../commands/suffix.md): +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources
diff --git a/docs/commands/murex-docs.md b/docs/commands/murex-docs.md index 76e970ee0..ab7120236 100644 --- a/docs/commands/murex-docs.md +++ b/docs/commands/murex-docs.md @@ -44,18 +44,18 @@ These man pages are compiled into the Murex executable. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr -* [`man-get-flags` ](../commands/man-get-flags.md): - Parses man page files for command line flags -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`tread`](../commands/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): + Parses man page files for command line flags +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/murex-package.md b/docs/commands/murex-package.md index 31a9833ae..703785585 100644 --- a/docs/commands/murex-package.md +++ b/docs/commands/murex-package.md @@ -1,4 +1,4 @@ -# `murex-package` +# shell.packages: `murex-package` > Murex's package manager @@ -111,6 +111,12 @@ If you wish to view what modules are loaded in a current session then use `murex-package list loaded` instead. This is also equivalent to using `runtime --modules`. +## Synonyms + +* `murex.package` +* `shell.packages` + + ## See Also * [Modules And Packages](../user-guide/modules.md): @@ -119,15 +125,15 @@ If you wish to view what modules are loaded in a current session then use A breakdown of the different files loaded on start up * [`alias`](../commands/alias.md): Create an alias for a command -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`function`](../commands/function.md): Define a function block * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins * [`private`](../commands/private.md): Define a private function block -* [`runtime`](../commands/runtime.md): +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/murex-parser.md b/docs/commands/murex-parser.md index 752c7fd21..560501947 100644 --- a/docs/commands/murex-parser.md +++ b/docs/commands/murex-parser.md @@ -20,11 +20,11 @@ Please note this command is still very much in beta and is likely to change in i ## See Also -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`runtime`](../commands/runtime.md): +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/murex-update-exe-list.md b/docs/commands/murex-update-exe-list.md index 0e12b58ff..a2ec1a116 100644 --- a/docs/commands/murex-update-exe-list.md +++ b/docs/commands/murex-update-exe-list.md @@ -1,4 +1,4 @@ -# `murex-update-exe-list` +# shell.rescan.path: `murex-update-exe-list` > Forces Murex to rescan $PATH looking for executables @@ -26,13 +26,19 @@ murex-update-exe-list Murex will automatically update the exe list each time tab completion is invoked for command name completion via the REPL shell. +## Synonyms + +* `murex-update-exe-list` +* `shell.rescan.path` + + ## See Also -* [`cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): Output the hosts CPU architecture -* [`cpucount`](../commands/cpucount.md): +* [sys.cpu.count: `cpucount`](../commands/cpucount.md): Output the number of CPU cores available on your host -* [`os`](../commands/os.md): +* [sys.os: `os`](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/namedpipe.md b/docs/commands/namedpipe.md index 11d2aeb32..f1e29de95 100644 --- a/docs/commands/namedpipe.md +++ b/docs/commands/namedpipe.md @@ -1,4 +1,4 @@ -# `` Read Named Pipe +# io.pipe: `` Read Named Pipe > Reads from a Murex named pipe @@ -113,21 +113,22 @@ that pipes created in modules should be prefixed with the name of its package. * `(murex named pipe)` * `<>` * `read-named-pipe` +* `io.pipe` ## See Also * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`bg`](../commands/bg.md): - Run processes in the background * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`pipe`](../commands/pipe.md): +* [io.new.pipe: `pipe`](../commands/pipe.md): Manage Murex named pipes -* [`runtime`](../commands/runtime.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/open-image.md b/docs/commands/open-image.md index 7df9db496..57cbf03c9 100644 --- a/docs/commands/open-image.md +++ b/docs/commands/open-image.md @@ -1,4 +1,4 @@ -# `open-image` +# fs.open.image: `open-image` > Renders bitmap image data on your terminal @@ -34,12 +34,18 @@ open-image file-path -> `open-image` will fail if stdout is not a TTY. +## Synonyms + +* `open-image` +* `fs.open.image` + + ## See Also -* [`open`](../commands/open.md): - Open a file with a preferred handler * [`qr`](../optional/qr.md): Creates a QR code from stdin +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler
diff --git a/docs/commands/open.md b/docs/commands/open.md index 7af23bb93..40c4da6d5 100644 --- a/docs/commands/open.md +++ b/docs/commands/open.md @@ -1,4 +1,4 @@ -# `open` +# fs.open: `open` > Open a file with a preferred handler @@ -212,28 +212,34 @@ In the case of macOS and some Linux systems, that might look like: exec open --flags filename ``` +## Synonyms + +* `open` +* `fs.open` + + ## See Also * [`*` (generic)](../types/generic.md): generic (primitive) -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`foreach`](../commands/foreach.md): Iterate through an array * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open`
diff --git a/docs/commands/openagent.md b/docs/commands/openagent.md index 514ae3d91..1c47850d7 100644 --- a/docs/commands/openagent.md +++ b/docs/commands/openagent.md @@ -1,4 +1,4 @@ -# `openagent` +# shell.open: `openagent` > Creates a handler function for `open` @@ -38,6 +38,8 @@ handler by checking `runtime --open-agents` and checking it's **FileRef**. * `openagent` * `!openagent` +* `shell.open` +* `!shell.open` ## See Also @@ -46,11 +48,11 @@ handler by checking `runtime --open-agents` and checking it's **FileRef**. How to track what code was loaded and from where * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/os.md b/docs/commands/os.md index ad8083d71..dbb17a591 100644 --- a/docs/commands/os.md +++ b/docs/commands/os.md @@ -1,4 +1,4 @@ -# `os` +# sys.os: `os` > Output the auto-detected OS name @@ -77,9 +77,9 @@ then please write it as `os posix plan9`. ## See Also -* [`cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): Output the hosts CPU architecture -* [`cpucount`](../commands/cpucount.md): +* [sys.cpu.count: `cpucount`](../commands/cpucount.md): Output the number of CPU cores available on your host
diff --git a/docs/commands/out.md b/docs/commands/out.md index 2ce3392e9..ac4886d98 100644 --- a/docs/commands/out.md +++ b/docs/commands/out.md @@ -1,4 +1,4 @@ -# `out` +# io.out: `out` > Print a string to the stdout with a trailing new line character @@ -42,6 +42,7 @@ Hello, World! ## Synonyms * `out` +* `io.out` * `echo` @@ -55,18 +56,18 @@ Hello, World! Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr -* [`pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [`read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`tread`](../commands/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.status: `pt`](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.input: `read`](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/commands/pipe.md b/docs/commands/pipe.md index 091226e40..d5d9a9a53 100644 --- a/docs/commands/pipe.md +++ b/docs/commands/pipe.md @@ -1,4 +1,4 @@ -# `pipe` +# io.new.pipe: `pipe` > Manage Murex named pipes @@ -120,28 +120,30 @@ that pipes created in modules should be prefixed with the name of its package. * `pipe` * `!pipe` +* `io.new.pipe` +* `!io.new.pipe` ## See Also * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`bg`](../commands/bg.md): - Run processes in the background -* [`match`](../commands/match.md): - Match an exact value in an array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/post.md b/docs/commands/post.md index d0a505424..d3ce28ef3 100644 --- a/docs/commands/post.md +++ b/docs/commands/post.md @@ -101,12 +101,12 @@ This enables sane, repeatable and readable defaults. Read the documents on Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/commands/prefix.md b/docs/commands/prefix.md index 4be77da14..66a830191 100644 --- a/docs/commands/prefix.md +++ b/docs/commands/prefix.md @@ -1,4 +1,4 @@ -# `prefix` +# list.prefix: `prefix` > Prefix a string to every item in a list @@ -40,24 +40,24 @@ runtime --unmarshallers ## See Also -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [`left`](../commands/left.md): +* [list.left: `left`](../commands/left.md): Left substring every item in a list -* [`right`](../commands/right.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.right: `right`](../commands/right.md): Right substring every item in a list -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`suffix`](../commands/suffix.md): +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/prepend.md b/docs/commands/prepend.md index 6ba1b377d..a202d31a0 100644 --- a/docs/commands/prepend.md +++ b/docs/commands/prepend.md @@ -1,4 +1,4 @@ -# `prepend` +# list.prepend: `prepend` > Add data to the start of an array @@ -52,26 +52,26 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`addheading` ](../commands/addheading.md): - Adds headings to a table -* [`append`](../commands/append.md): - Add data to the end of an array * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`match`](../commands/match.md): - Match an exact value in an array -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`regexp`](../commands/regexp.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [table.new.heading: `addheading` ](../commands/addheading.md): + Adds headings to a table
diff --git a/docs/commands/pretty.md b/docs/commands/pretty.md index ef52ee436..0a7a32a59 100644 --- a/docs/commands/pretty.md +++ b/docs/commands/pretty.md @@ -1,4 +1,4 @@ -# `pretty` +# struct.json.pretty: `pretty` > Prettifies JSON to make it human readable @@ -30,14 +30,20 @@ outputs that to stdout. } ``` +## Synonyms + +* `pretty` +* `struct.json.pretty` + + ## See Also * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/private.md b/docs/commands/private.md index 19c3a3a26..64d771b2a 100644 --- a/docs/commands/private.md +++ b/docs/commands/private.md @@ -96,26 +96,26 @@ You can override this order of precedence via the `fexec` and `exec` builtins. Create an alias for a command * [`break`](../commands/break.md): Terminate execution of a block within your processes scope -* [`exec`](../commands/exec.md): - Runs an executable -* [`export`](../commands/export.md): - Define an environmental variable and set it's value -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`function`](../commands/function.md): Define a function block -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`method`](../commands/method.md): Define a methods supported data-types -* [`set`](../commands/set.md): +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value -* [`source`](../commands/source.md): - Import Murex code from another file of code block
diff --git a/docs/commands/pt.md b/docs/commands/pt.md index 8dd28dc04..78c0fd680 100644 --- a/docs/commands/pt.md +++ b/docs/commands/pt.md @@ -1,4 +1,4 @@ -# `pt` +# fs.status: `pt` > Pipe telemetry. Writes data-types and bytes written @@ -22,6 +22,12 @@ curl -s https://example.com/bigfile.bin -> pt |> bigfile.bin (though Murex does also have it's own HTTP clients, `get`, `post` and `getfile`) +## Synonyms + +* `pt` +* `fs.status` + + ## See Also * [`>>` Append File](../parser/file-append.md): @@ -32,7 +38,7 @@ curl -s https://example.com/bigfile.bin -> pt |> bigfile.bin Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists
diff --git a/docs/commands/rand.md b/docs/commands/rand.md index 4113a8a87..f5ba71b56 100644 --- a/docs/commands/rand.md +++ b/docs/commands/rand.md @@ -71,7 +71,7 @@ cryptographically secure. Reformat one data-type into another data-type * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/read.md b/docs/commands/read.md index 2a716291d..f214ce886 100644 --- a/docs/commands/read.md +++ b/docs/commands/read.md @@ -1,4 +1,4 @@ -# `read` +# io.input: `read` > `read` a line of input from the user and store as a variable @@ -85,6 +85,12 @@ The data type the `read` line will be stored as is `str` (string). If you require this to be different then please use `tread` (typed read) or call `read` with the `--datatype` flag as per the **script usage**. +## Synonyms + +* `read` +* `io.input` + + ## See Also * [`%(Brace Quote)`](../parser/brace-quote.md): @@ -93,16 +99,16 @@ with the `--datatype` flag as per the **script usage**. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`tread`](../commands/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 8db4f1ed2..363ce5cd2 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -1,4 +1,4 @@ -# `regexp` +# list.regex: `regexp` > Regexp tools for arrays / lists of strings @@ -95,34 +95,34 @@ same data-type. ## See Also -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`match`](../commands/match.md): - Match an exact value in an array -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`prefix`](../commands/prefix.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`prepend`](../commands/prepend.md): +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`suffix`](../commands/suffix.md): +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources
diff --git a/docs/commands/return.md b/docs/commands/return.md index 1d6dee829..945a92940 100644 --- a/docs/commands/return.md +++ b/docs/commands/return.md @@ -62,14 +62,14 @@ was passed). Terminate process of a block within a caller function * [`exit`](../commands/exit.md): Exit murex -* [`exitnum`](../commands/exitnum.md): - Output the exit number of the previous process * [`function`](../commands/function.md): Define a function block -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [proc.exitnum: `exitnum`](../commands/exitnum.md): + Output the exit number of the previous process
diff --git a/docs/commands/right.md b/docs/commands/right.md index 47427bdff..980d6a67d 100644 --- a/docs/commands/right.md +++ b/docs/commands/right.md @@ -1,4 +1,4 @@ -# `right` +# list.right: `right` > Right substring every item in a list @@ -56,24 +56,24 @@ runtime --unmarshallers ## See Also -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [`prefix`](../commands/prefix.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`right`](../commands/right.md): +* [list.right: `right`](../commands/right.md): Right substring every item in a list -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`suffix`](../commands/suffix.md): +* [list.suffix: `suffix`](../commands/suffix.md): Prefix a string to every item in a list +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/round.md b/docs/commands/round.md index cbf4a9e2f..16dda7e1c 100644 --- a/docs/commands/round.md +++ b/docs/commands/round.md @@ -1,4 +1,4 @@ -# `round` +# num.round: `round` > Round a number by a user defined precision @@ -71,6 +71,12 @@ Rounding to the nearest multiple of `20`: * `-u` shorthand for `--up` +## Synonyms + +* `round` +* `num.round` + + ## See Also * [`expr`](../commands/expr.md): diff --git a/docs/commands/runmode.md b/docs/commands/runmode.md index 1707333f9..c17bd3b8b 100644 --- a/docs/commands/runmode.md +++ b/docs/commands/runmode.md @@ -87,22 +87,14 @@ if `runmode ... module` is set. Overview of what a "pipeline" is * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`function`](../commands/function.md): Define a function block -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block -* [`read`](../commands/read.md): - `read` a line of input from the user and store as a variable * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`tryerr`](../commands/tryerr.md): @@ -113,6 +105,14 @@ if `runmode ... module` is set. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number +* [io.input: `read`](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/commands/runtime.md b/docs/commands/runtime.md index 31ed2861b..1ebda5571 100644 --- a/docs/commands/runtime.md +++ b/docs/commands/runtime.md @@ -1,4 +1,4 @@ -# `runtime` +# shell.runtime: `runtime` > Returns runtime information on the internal state of Murex @@ -281,6 +281,7 @@ functions. * `runtime` * `builtins` +* `shell.runtime` ## See Also @@ -289,18 +290,8 @@ functions. Default integrations shipped with Murex * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`debug`](../commands/debug.md): - Debugging information * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`export`](../commands/export.md): - Define an environmental variable and set it's value -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): @@ -309,28 +300,38 @@ functions. Reformat one data-type into another data-type * [`function`](../commands/function.md): Define a function block -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`method`](../commands/method.md): Define a methods supported data-types -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value -* [`source`](../commands/source.md): - Import Murex code from another file of code block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/commands/rx.md b/docs/commands/rx.md index faf5d8446..a6e25d2c5 100644 --- a/docs/commands/rx.md +++ b/docs/commands/rx.md @@ -1,4 +1,4 @@ -# `rx` +# fs.regex: `rx` > Regexp pattern matching for file system objects (eg `.*\\.txt`) @@ -114,18 +114,20 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. * `rx` * `!rx` +* `fs.regex` +* `!fs.regex` ## See Also -* [`f`](../commands/f.md): +* [fs.files: `f`](../commands/f.md): Lists or filters file system objects (eg files) -* [`g`](../commands/g.md): +* [fs.glob: `g`](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [`match`](../commands/match.md): - Match an exact value in an array -* [`regexp`](../commands/regexp.md): +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings +* [list.str: `match`](../commands/match.md): + Match an exact value in an array
diff --git a/docs/commands/set.md b/docs/commands/set.md index 683f048e8..680da53aa 100644 --- a/docs/commands/set.md +++ b/docs/commands/set.md @@ -1,4 +1,4 @@ -# `set` +# var.set: `set` > Define a local variable and set it's value @@ -248,6 +248,8 @@ bar * `set` * `!set` +* `var.set` +* `!var.set` ## See Also @@ -264,16 +266,16 @@ bar Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`exec`](../commands/exec.md): - Runs an executable -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value
diff --git a/docs/commands/signal.md b/docs/commands/signal.md index fb305c0d1..23a99f6f7 100644 --- a/docs/commands/signal.md +++ b/docs/commands/signal.md @@ -166,14 +166,14 @@ Signals can be caught (often referred to as "trapped") in Murex with an event: Absolute path to running shell * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`bg`](../commands/bg.md): - Run processes in the background * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character * [onSignalReceived](../events/onsignalreceived.md): Trap OS signals +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background
diff --git a/docs/commands/source.md b/docs/commands/source.md index 3f60e01d0..06a6cc586 100644 --- a/docs/commands/source.md +++ b/docs/commands/source.md @@ -1,6 +1,6 @@ -# `source` +# exec.include: `source` -> Import Murex code from another file of code block +> Import Murex code from another file or code block ## Description @@ -56,29 +56,30 @@ Hello, world! * `source` * `.` +* `exec.include` ## See Also * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`function`](../commands/function.md): Define a function block * [`murex-parser` ](../commands/murex-parser.md): Runs the Murex parser against a block of code * [`private`](../commands/private.md): Define a private function block -* [`runtime`](../commands/runtime.md): +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`version`](../commands/version.md): +* [shell.version: `version`](../commands/version.md): Get Murex version
diff --git a/docs/commands/stdin.md b/docs/commands/stdin.md index 7ce4030f8..1f640bb66 100644 --- a/docs/commands/stdin.md +++ b/docs/commands/stdin.md @@ -133,17 +133,17 @@ that pipes created in modules should be prefixed with the name of its package. * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`function`](../commands/function.md): Define a function block -* [`match`](../commands/match.md): - Match an exact value in an array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pipe`](../commands/pipe.md): +* [io.new.pipe: `pipe`](../commands/pipe.md): Manage Murex named pipes -* [`runtime`](../commands/runtime.md): +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/struct-keys.md b/docs/commands/struct-keys.md index c56c89d03..55c4d0066 100644 --- a/docs/commands/struct-keys.md +++ b/docs/commands/struct-keys.md @@ -1,4 +1,4 @@ -# `struct-keys` +# struct.keys: `struct-keys` > Outputs all the keys in a structure as a file path @@ -156,6 +156,12 @@ Separator can also be multiple characters: * `-s` Alias for `--separator` +## Synonyms + +* `struct-keys` +* `struct.keys` + + ## See Also * [`[ Index ]`](../parser/item-index.md): @@ -164,7 +170,7 @@ Separator can also be multiple characters: Outputs an element from a nested structure * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/commands/suffix.md b/docs/commands/suffix.md index f49506822..5423e625a 100644 --- a/docs/commands/suffix.md +++ b/docs/commands/suffix.md @@ -1,4 +1,4 @@ -# `suffix` +# list.suffix: `suffix` > Prefix a string to every item in a list @@ -40,24 +40,24 @@ runtime --unmarshallers ## See Also -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [`left`](../commands/left.md): +* [list.left: `left`](../commands/left.md): Left substring every item in a list -* [`prefix`](../commands/prefix.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prefix: `prefix`](../commands/prefix.md): Prefix a string to every item in a list -* [`right`](../commands/right.md): +* [list.right: `right`](../commands/right.md): Right substring every item in a list -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/summary.md b/docs/commands/summary.md index 3b07fc7e4..a0cd343e0 100644 --- a/docs/commands/summary.md +++ b/docs/commands/summary.md @@ -1,4 +1,4 @@ -# `summary` +# shell.summary: `summary` > Defines a summary help text for a command @@ -45,25 +45,27 @@ Hello, world! * `summary` * `!summary` +* `shell.summary` +* `!shell.summary` ## See Also -* [`bexists`](../commands/bexists.md): +* [`murex-docs`](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.builtins.exist: `bexists`](../commands/bexists.md): Check which builtins exist -* [`builtins`](../commands/runtime.md): +* [shell.builtins: `builtins`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings -* [`exec`](../commands/exec.md): - Runs an executable -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/switch.md b/docs/commands/switch.md index ec5fc8ad9..3156cab81 100644 --- a/docs/commands/switch.md +++ b/docs/commands/switch.md @@ -219,8 +219,6 @@ switch { Evaluate a mathematical function and assign to variable (deprecated) * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`true`](../commands/true.md): Returns a `true` value * [`try`](../commands/try.md): @@ -229,6 +227,8 @@ switch { Checks for non-zero exits of each function in a pipeline * [`while`](../commands/while.md): Loop until condition false +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/commands/ta.md b/docs/commands/ta.md index da79f9f2c..21c331dae 100644 --- a/docs/commands/ta.md +++ b/docs/commands/ta.md @@ -1,4 +1,4 @@ -# `ta` (mkarray) +# list.new.type: `ta` > A sophisticated yet simple way to build an array of a user defined data-type @@ -52,6 +52,12 @@ if you are only creating arrays in JSON then you could use `ja` instead. Please read the documentation on `a` for a more detailed breakdown on of `ta`'s supported features. +## Synonyms + +* `ta` +* `list.new.type` + + ## See Also * [`%[]` Array Builder](../parser/create-array.md): @@ -62,14 +68,14 @@ Please read the documentation on `a` for a more detailed breakdown on of Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.reverse: `mtac`](../commands/mtac.md): Reverse the order of an array +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/commands/tabulate.md b/docs/commands/tabulate.md index 658d5512e..20e620207 100644 --- a/docs/commands/tabulate.md +++ b/docs/commands/tabulate.md @@ -59,12 +59,12 @@ rsync --help # print rsync help Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`formap`](../commands/formap.md): Iterate through a map or other collection of data * [`format`](../commands/format.md): Reformat one data-type into another data-type +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/commands/test.md b/docs/commands/test.md index 1cbd3a6dd..7133f98d5 100644 --- a/docs/commands/test.md +++ b/docs/commands/test.md @@ -114,9 +114,9 @@ flushes the table of pending reports. ## See Also -* [`` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): Reads from a Murex named pipe -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/time.md b/docs/commands/time.md index 7b6bebbcf..f21854b09 100644 --- a/docs/commands/time.md +++ b/docs/commands/time.md @@ -41,12 +41,12 @@ and stderr as usual. ## See Also -* [`exec`](../commands/exec.md): - Runs an executable * [`sleep`](../optional/sleep.md): Suspends the shell for a number of seconds -* [`source`](../commands/source.md): - Import Murex code from another file of code block +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block
diff --git a/docs/commands/tmp.md b/docs/commands/tmp.md index 4b1db0c90..312b3da3d 100644 --- a/docs/commands/tmp.md +++ b/docs/commands/tmp.md @@ -1,4 +1,4 @@ -# `tmp` +# fs.new.tmpfile: `tmp` > Create a temporary file and write to it @@ -96,16 +96,22 @@ you ever want to. which itself is located in the appropriate temp directory for the host OS (eg `$TMPDIR` on macOS). +## Synonyms + +* `tmp` +* `fs.new.tmpfile` + + ## See Also * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes
diff --git a/docs/commands/tout.md b/docs/commands/tout.md index 1f5f1d012..541e7ae7e 100644 --- a/docs/commands/tout.md +++ b/docs/commands/tout.md @@ -1,4 +1,4 @@ -# `tout` +# io.out.type: `tout` > Print a string to the stdout and set it's data-type @@ -29,6 +29,12 @@ tout data-type "string to write" -> Unlike `out`, `tout` does not append a carriage return / line feed. +## Synonyms + +* `tout` +* `io.out.type` + + ## See Also * [ANSI Constants](../user-guide/ansi.md): @@ -37,13 +43,13 @@ Unlike `out`, `tout` does not append a carriage return / line feed. Write a string to the stdout without new line (deprecated) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`out`](../commands/out.md): +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`pretty`](../commands/pretty.md): +* [struct.json.pretty: `pretty`](../commands/pretty.md): Prettifies JSON to make it human readable
diff --git a/docs/commands/tread.md b/docs/commands/tread.md index 4ae3dd4b4..31e85161c 100644 --- a/docs/commands/tread.md +++ b/docs/commands/tread.md @@ -46,18 +46,18 @@ variable. Initiates or terminates a string (variables expanded) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`read`](../commands/read.md): +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.input: `read`](../commands/read.md): `read` a line of input from the user and store as a variable -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable
diff --git a/docs/commands/try.md b/docs/commands/try.md index 976ed73b5..319f7bd50 100644 --- a/docs/commands/try.md +++ b/docs/commands/try.md @@ -47,8 +47,6 @@ command. Overview of the different schedulers (or 'run modes') in Murex * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`runmode`](../commands/runmode.md): @@ -63,6 +61,8 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session
diff --git a/docs/commands/tryerr.md b/docs/commands/tryerr.md index 997905820..e456cf9eb 100644 --- a/docs/commands/tryerr.md +++ b/docs/commands/tryerr.md @@ -48,8 +48,6 @@ command. Overview of the different schedulers (or 'run modes') in Murex * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`runmode`](../commands/runmode.md): @@ -64,6 +62,8 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session
diff --git a/docs/commands/trypipe.md b/docs/commands/trypipe.md index f7c4117d2..54fffe7f4 100644 --- a/docs/commands/trypipe.md +++ b/docs/commands/trypipe.md @@ -50,8 +50,6 @@ command. Overview of the different schedulers (or 'run modes') in Murex * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`runmode`](../commands/runmode.md): @@ -66,6 +64,8 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session
diff --git a/docs/commands/trypipeerr.md b/docs/commands/trypipeerr.md index 9c5ecad12..f5201c535 100644 --- a/docs/commands/trypipeerr.md +++ b/docs/commands/trypipeerr.md @@ -51,8 +51,6 @@ command. Overview of the different schedulers (or 'run modes') in Murex * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`runmode`](../commands/runmode.md): @@ -67,6 +65,8 @@ command. Checks for non-zero exits of each function in a pipeline * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session
diff --git a/docs/commands/type.md b/docs/commands/type.md index 1670122e9..087c5d01a 100644 --- a/docs/commands/type.md +++ b/docs/commands/type.md @@ -71,18 +71,18 @@ In `type`, it is represented by the term **executable**. * [`alias`](../commands/alias.md): Create an alias for a command -* [`exec`](../commands/exec.md): - Runs an executable * [`exit`](../commands/exit.md): Exit murex -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`function`](../commands/function.md): Define a function block -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`which`](../commands/which.md): Locate command origin +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/unsafe.md b/docs/commands/unsafe.md index 936dbca90..a659c8bb0 100644 --- a/docs/commands/unsafe.md +++ b/docs/commands/unsafe.md @@ -32,8 +32,6 @@ try { Overview of the different schedulers (or 'run modes') in Murex * [`catch`](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`runmode`](../commands/runmode.md): @@ -48,6 +46,8 @@ try { Checks for non-zero exits of each function in a pipeline * [`trypipeerr`](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session
diff --git a/docs/commands/version.md b/docs/commands/version.md index 16a85a263..6b3d6a310 100644 --- a/docs/commands/version.md +++ b/docs/commands/version.md @@ -1,4 +1,4 @@ -# `version` +# shell.version: `version` > Get Murex version @@ -42,24 +42,30 @@ murex: 0.51.1200 BETA * `--short` Returns only the major and minor version as a `num` data-type +## Synonyms + +* `version` +* `shell.version` + + ## See Also * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`function`](../commands/function.md): Define a function block * [`murex-parser` ](../commands/murex-parser.md): Runs the Murex parser against a block of code * [`private`](../commands/private.md): Define a private function block -* [`runtime`](../commands/runtime.md): +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`source`](../commands/source.md): - Import Murex code from another file of code block
diff --git a/docs/commands/which.md b/docs/commands/which.md index ded85936b..0959859ed 100644 --- a/docs/commands/which.md +++ b/docs/commands/which.md @@ -77,18 +77,18 @@ In `type`, it is represented by the term **executable**. * [`alias`](../commands/alias.md): Create an alias for a command -* [`exec`](../commands/exec.md): - Runs an executable * [`exit`](../commands/exit.md): Exit murex -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. * [`function`](../commands/function.md): Define a function block -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`type`](../commands/type.md): Command type (function, builtin, alias, etc) +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/while.md b/docs/commands/while.md index 589a2f811..cf3be8fa5 100644 --- a/docs/commands/while.md +++ b/docs/commands/while.md @@ -96,21 +96,21 @@ The following meta values are defined: ## See Also -* [`err`](../commands/err.md): - Print a line to the stderr * [`for`](../commands/for.md): A more familiar iteration loop to existing developers * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`out`](../commands/out.md): +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/events/oncommandcompletion.md b/docs/events/oncommandcompletion.md index ca90099fc..306c5bbc5 100644 --- a/docs/events/oncommandcompletion.md +++ b/docs/events/oncommandcompletion.md @@ -125,8 +125,6 @@ Stdout and stderr are both written to the terminal's stderr. Array of the command name and parameters within a given scope * [`alias`](../commands/alias.md): Create an alias for a command -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`function`](../commands/function.md): @@ -135,10 +133,12 @@ Stdout and stderr are both written to the terminal's stderr. Conditional statement to execute different blocks of code depending on the result of the condition * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [`regexp`](../commands/regexp.md): +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings * [read-named-pipe](../commands/namedpipe.md): Reads from a Murex named pipe +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/events/onfilesystemchange.md b/docs/events/onfilesystemchange.md index f032825eb..3f1080c2b 100644 --- a/docs/events/onfilesystemchange.md +++ b/docs/events/onfilesystemchange.md @@ -89,10 +89,10 @@ event to Linux, macOS and UNIX systems instead. ## See Also -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/events/onkeypress.md b/docs/events/onkeypress.md index 79bdbc5e9..923ca412a 100644 --- a/docs/events/onkeypress.md +++ b/docs/events/onkeypress.md @@ -255,8 +255,6 @@ from different interrupts). What's different about Murex's interactive shell? * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): @@ -265,6 +263,8 @@ from different interrupts). Full screen previews for files and command documentation * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/events/onpreview.md b/docs/events/onpreview.md index b528da00b..ccf765cc4 100644 --- a/docs/events/onpreview.md +++ b/docs/events/onpreview.md @@ -168,8 +168,6 @@ from different interrupts). Linux/UNIX `man` page integrations * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`function`](../commands/function.md): @@ -182,6 +180,8 @@ from different interrupts). Custom definable key bindings and macros * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/events/onprompt.md b/docs/events/onprompt.md index 7d3e548d6..1207c84bb 100644 --- a/docs/events/onprompt.md +++ b/docs/events/onprompt.md @@ -127,8 +127,6 @@ from different interrupts). What's different about Murex's interactive shell? * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): @@ -137,6 +135,8 @@ from different interrupts). Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/events/onsecondselapsed.md b/docs/events/onsecondselapsed.md index aafa77f1e..691dc0e62 100644 --- a/docs/events/onsecondselapsed.md +++ b/docs/events/onsecondselapsed.md @@ -58,10 +58,10 @@ Stdout and stderr are both written to the terminal. ## See Also -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/integrations/chatgpt.md b/docs/integrations/chatgpt.md index d5c1b4e43..4c097533f 100644 --- a/docs/integrations/chatgpt.md +++ b/docs/integrations/chatgpt.md @@ -131,8 +131,6 @@ under `/integrations`. A breakdown of the different files loaded on start up * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`murex-docs`](../commands/murex-docs.md): @@ -141,6 +139,8 @@ under `/integrations`. Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/cheatsh.md b/docs/integrations/cheatsh.md index e43cd6457..3d05e50c9 100644 --- a/docs/integrations/cheatsh.md +++ b/docs/integrations/cheatsh.md @@ -36,14 +36,14 @@ under `/integrations`. A breakdown of the different files loaded on start up * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/direnv.md b/docs/integrations/direnv.md index f18c08956..a3354a816 100644 --- a/docs/integrations/direnv.md +++ b/docs/integrations/direnv.md @@ -20,7 +20,7 @@ document. * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`export`](../commands/export.md): +* [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value ## Other Integrations diff --git a/docs/integrations/iterm2.md b/docs/integrations/iterm2.md index 705940d95..f0851183c 100644 --- a/docs/integrations/iterm2.md +++ b/docs/integrations/iterm2.md @@ -30,9 +30,9 @@ open https://murex.rocks/git-autocomplete.png Get more out of Kitty terminal emulator * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): +* [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/kitty.md b/docs/integrations/kitty.md index 31924b797..f985f42cf 100644 --- a/docs/integrations/kitty.md +++ b/docs/integrations/kitty.md @@ -24,12 +24,12 @@ to Kitty's ANSI escape sequences to render those images beautifully. * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/make.md b/docs/integrations/make.md index 4f869057f..a3f26e8db 100644 --- a/docs/integrations/make.md +++ b/docs/integrations/make.md @@ -28,10 +28,10 @@ under `/integrations`. * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/man-pages.md b/docs/integrations/man-pages.md index 02af7ce7c..2186b5998 100644 --- a/docs/integrations/man-pages.md +++ b/docs/integrations/man-pages.md @@ -46,8 +46,6 @@ That command will generally be pulled from its accompanying `man` page. How to enable ChatGPT hints * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`event`](../commands/event.md): Event driven programming for shell scripts * [`murex-docs`](../commands/murex-docs.md): @@ -56,6 +54,8 @@ That command will generally be pulled from its accompanying `man` page. Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/spellcheck.md b/docs/integrations/spellcheck.md index a60b62871..4f5c47706 100644 --- a/docs/integrations/spellcheck.md +++ b/docs/integrations/spellcheck.md @@ -163,20 +163,20 @@ and what the package names are for `aspell` and its corresponding dictionaries. What's different about Murex's interactive shell? * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`append`](../commands/append.md): - Add data to the end of an array -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value ## Other Integrations diff --git a/docs/integrations/terminology.md b/docs/integrations/terminology.md index 09cd59c63..ae6bf93e7 100644 --- a/docs/integrations/terminology.md +++ b/docs/integrations/terminology.md @@ -25,12 +25,12 @@ beautifully. * [Kitty Integrations](../integrations/kitty.md): Get more out of Kitty terminal emulator -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/yarn.md b/docs/integrations/yarn.md index 320100c1a..7a6ac4300 100644 --- a/docs/integrations/yarn.md +++ b/docs/integrations/yarn.md @@ -25,10 +25,10 @@ under `/integrations`. * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/mkarray/character.md b/docs/mkarray/character.md index 5f5df536c..7063d4ab6 100644 --- a/docs/mkarray/character.md +++ b/docs/mkarray/character.md @@ -64,16 +64,16 @@ a Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/mkarray/date.md b/docs/mkarray/date.md index 0ec53c95d..8bafe7e9f 100644 --- a/docs/mkarray/date.md +++ b/docs/mkarray/date.md @@ -199,20 +199,20 @@ Friday, 03 January Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/mkarray/decimal.md b/docs/mkarray/decimal.md index 4a75f57a9..1fe72ff2d 100644 --- a/docs/mkarray/decimal.md +++ b/docs/mkarray/decimal.md @@ -118,16 +118,16 @@ arrays such as JSON (`ja`). Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/mkarray/non-decimal.md b/docs/mkarray/non-decimal.md index 8b7187935..594bfb4e6 100644 --- a/docs/mkarray/non-decimal.md +++ b/docs/mkarray/non-decimal.md @@ -131,16 +131,16 @@ arrays such as JSON (`ja`). Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/mkarray/special.md b/docs/mkarray/special.md index 7e6d32324..55f0e9995 100644 --- a/docs/mkarray/special.md +++ b/docs/mkarray/special.md @@ -224,20 +224,20 @@ var rangeMoon = map[string]int{ Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`count`](../commands/count.md): - Count items in a map, list or array -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): - Reverse the order of an array -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/optional/README.md b/docs/optional/README.md index 50a128d20..5e1d62d78 100644 --- a/docs/optional/README.md +++ b/docs/optional/README.md @@ -46,7 +46,7 @@ murex-docs trypipe Compress or decompress a gzip file * [`qr`](../optional/qr.md): Creates a QR code from stdin -* [`select`](../optional/select.md): - Inlining SQL into shell pipelines * [`sleep`](../optional/sleep.md): - Suspends the shell for a number of seconds \ No newline at end of file + Suspends the shell for a number of seconds +* [table.select: `select`](../optional/select.md): + Inlining SQL into shell pipelines \ No newline at end of file diff --git a/docs/optional/base64.md b/docs/optional/base64.md index b85e97657..e7e4e0d39 100644 --- a/docs/optional/base64.md +++ b/docs/optional/base64.md @@ -57,16 +57,16 @@ it doesn't require the OS fork processes. * [`!bz2`](../optional/bz2.md): Decompress a bz2 file -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): +* [`gz`](../optional/gz.md): + Compress or decompress a gzip file +* [escape.cli: `esccli`](../commands/esccli.md): Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): +* [escape.html: `eschtml`](../commands/eschtml.md): Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): Encode or decodes text for the URL -* [`gz`](../optional/gz.md): - Compress or decompress a gzip file
diff --git a/docs/optional/bz2.md b/docs/optional/bz2.md index 7289fff03..bbbb25fb5 100644 --- a/docs/optional/bz2.md +++ b/docs/optional/bz2.md @@ -25,16 +25,16 @@ Currently there is no support for compressing a stream using bz2. * [`base64` ](../optional/base64.md): Encode or decode a base64 string -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): +* [`gz`](../optional/gz.md): + Compress or decompress a gzip file +* [escape.cli: `esccli`](../commands/esccli.md): Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): +* [escape.html: `eschtml`](../commands/eschtml.md): Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): Encode or decodes text for the URL -* [`gz`](../optional/gz.md): - Compress or decompress a gzip file
diff --git a/docs/optional/gz.md b/docs/optional/gz.md index 6c2638b99..3db6408e5 100644 --- a/docs/optional/gz.md +++ b/docs/optional/gz.md @@ -26,13 +26,13 @@ An optional builtin for compressing or decompressing a gzip stream from stdin. Decompress a bz2 file * [`base64` ](../optional/base64.md): Encode or decode a base64 string -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): +* [escape.cli: `esccli`](../commands/esccli.md): Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): +* [escape.html: `eschtml`](../commands/eschtml.md): Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/optional/qr.md b/docs/optional/qr.md index 51e2f2513..186cf176e 100644 --- a/docs/optional/qr.md +++ b/docs/optional/qr.md @@ -37,7 +37,7 @@ have to `cast` the output in some circumstances. * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`open-image`](../commands/open-image.md): +* [fs.open.image: `open-image`](../commands/open-image.md): Renders bitmap image data on your terminal
diff --git a/docs/optional/select.md b/docs/optional/select.md index 8657e2d32..79c9cbc2c 100644 --- a/docs/optional/select.md +++ b/docs/optional/select.md @@ -1,4 +1,4 @@ -# `select` +# table.select: `select` > Inlining SQL into shell pipelines @@ -128,18 +128,19 @@ If you do run into any issues then please raise them on [Github](https://github. ## Synonyms * `select` +* `table.select` ## See Also * [`*` (generic)](../types/generic.md): generic (primitive) -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`csv`](../types/csv.md): CSV files (and other character delimited tables) * [`jsonl`](../types/jsonl.md): JSON Lines +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings * [v2.1](../changelog/v2.1.md): This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details. diff --git a/docs/optional/sleep.md b/docs/optional/sleep.md index 55be76f9c..6238d0c50 100644 --- a/docs/optional/sleep.md +++ b/docs/optional/sleep.md @@ -32,12 +32,12 @@ or similar platforms then you will need to launch with the `exec` builtin: ## See Also -* [`exec`](../commands/exec.md): - Runs an executable -* [`source`](../commands/source.md): - Import Murex code from another file of code block * [`time`](../commands/time.md): Returns the execution run time of a command or block +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block
diff --git a/docs/parser/README.md b/docs/parser/README.md index ca7ff1a1a..f4bb6d567 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -363,8 +363,6 @@ files. Iterate through structured data * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block -* [`|>` Truncate File](../parser/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command * [`||` Or Logical Operator](../parser/logical-or.md): diff --git a/docs/parser/add-with.md b/docs/parser/add-with.md index 7d9d481c0..7479e0f74 100644 --- a/docs/parser/add-with.md +++ b/docs/parser/add-with.md @@ -55,8 +55,6 @@ value op value**, for example: Divides a variable by the right hand value (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -65,6 +63,8 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/addition.md b/docs/parser/addition.md index 4361baa35..8486b6a49 100644 --- a/docs/parser/addition.md +++ b/docs/parser/addition.md @@ -75,8 +75,6 @@ Error in `expr` (0,1): cannot Add with string types Divides one numeric value from another (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -85,6 +83,8 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/array.md b/docs/parser/array.md index 93dbb0fc8..96915413b 100644 --- a/docs/parser/array.md +++ b/docs/parser/array.md @@ -128,14 +128,14 @@ foo 1 2 3 4 5 bar Write a string to the stdout without new line (deprecated) * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/assign-or-merge.md b/docs/parser/assign-or-merge.md index fa37d4b5c..ce0801959 100644 --- a/docs/parser/assign-or-merge.md +++ b/docs/parser/assign-or-merge.md @@ -94,14 +94,14 @@ builtin. A table of all supported operators and tokens * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`foreach`](../commands/foreach.md): Iterate through an array -* [`g`](../commands/g.md): +* [fs.glob: `g`](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/parser/brace-quote-func.md b/docs/parser/brace-quote-func.md index bbd1d7211..0875ee1ab 100644 --- a/docs/parser/brace-quote-func.md +++ b/docs/parser/brace-quote-func.md @@ -54,16 +54,16 @@ characters if you don't want them nested. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`err`](../commands/err.md): - Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pt`](../commands/pt.md): +* [fs.status: `pt`](../commands/pt.md): Pipe telemetry. Writes data-types and bytes written -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [`|>` Truncate File](../parser/file-truncate.md): +* [fs.truncate: `>`](../command/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/brace-quote.md b/docs/parser/brace-quote.md index 07e3c54c9..31d993775 100644 --- a/docs/parser/brace-quote.md +++ b/docs/parser/brace-quote.md @@ -98,16 +98,16 @@ Hello (World!) Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/c-style-fun.md b/docs/parser/c-style-fun.md index 487a08569..6341d7790 100644 --- a/docs/parser/c-style-fun.md +++ b/docs/parser/c-style-fun.md @@ -103,14 +103,14 @@ It is 23 o' clock * [Language Tour](../Murex/tour.md): Getting started with Murex -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [`echo`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler +* [io.echo: `echo`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) * [sub-shell](../parser/sub-shell.md): diff --git a/docs/parser/create-array.md b/docs/parser/create-array.md index 1512c1b45..eaba9ba99 100644 --- a/docs/parser/create-array.md +++ b/docs/parser/create-array.md @@ -185,13 +185,13 @@ arrays. For more details on these please refer to the documents for each format Quickly generate objects (dictionaries / maps) * [`'Single Quote'`](../parser/single-quote.md): Initiates or terminates a string (variables not expanded) -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`ta` (mkarray)](../commands/ta.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type
diff --git a/docs/parser/curly-brace.md b/docs/parser/curly-brace.md index 0f8f00a49..4605c9715 100644 --- a/docs/parser/curly-brace.md +++ b/docs/parser/curly-brace.md @@ -82,18 +82,18 @@ constants are available. Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`err`](../commands/err.md): - Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/divide-by.md b/docs/parser/divide-by.md index c3ffab7fa..be3968ff4 100644 --- a/docs/parser/divide-by.md +++ b/docs/parser/divide-by.md @@ -55,8 +55,6 @@ value op value**, for example: Divides one numeric value from another (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -65,6 +63,8 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/division.md b/docs/parser/division.md index d14da0dd6..67d379045 100644 --- a/docs/parser/division.md +++ b/docs/parser/division.md @@ -70,8 +70,6 @@ Error in `expr` (0,1): cannot Add with string types Divides a variable by the right hand value (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -80,6 +78,8 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/double-quote.md b/docs/parser/double-quote.md index 48e5b0866..76f124ce2 100644 --- a/docs/parser/double-quote.md +++ b/docs/parser/double-quote.md @@ -43,16 +43,16 @@ bar Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/element.md b/docs/parser/element.md index 87ec3b2cb..0637df3d8 100644 --- a/docs/parser/element.md +++ b/docs/parser/element.md @@ -126,16 +126,16 @@ bool Outputs a ranged subset of data from stdin * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.reverse: `mtac`](../commands/mtac.md): Reverse the order of an array +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md index 3566130ee..82e609bd7 100644 --- a/docs/parser/elvis.md +++ b/docs/parser/elvis.md @@ -61,18 +61,18 @@ where it says: Returns the right operand if the left operand is empty / undefined (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): - Print a line to the stderr * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/equ.md b/docs/parser/equ.md index 0e8386152..8341a8799 100644 --- a/docs/parser/equ.md +++ b/docs/parser/equ.md @@ -198,19 +198,19 @@ Murex uses the [govaluate package](https://github.com/Knetic/govaluate). More in Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`global`](../commands/global.md): - Define a global variable and set it's value -* [`global`](../commands/global.md): - Define a global variable and set it's value * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`set`](../commands/set.md): +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/parser/expr-inlined.md b/docs/parser/expr-inlined.md index 15955cc61..9af96eb19 100644 --- a/docs/parser/expr-inlined.md +++ b/docs/parser/expr-inlined.md @@ -25,10 +25,10 @@ that parameter will be treated like a string. * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens -* [`echo`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators +* [io.echo: `echo`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/file-append.md b/docs/parser/file-append.md index 8e471365a..418499029 100644 --- a/docs/parser/file-append.md +++ b/docs/parser/file-append.md @@ -55,16 +55,16 @@ To truncate a file (ie overwrite its contents) use `|>` instead. Overview of what a "pipeline" is * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`|>` Truncate File](../parser/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [fs.truncate: `>`](../command/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe
diff --git a/docs/parser/item-index.md b/docs/parser/item-index.md index a14deabbe..e187c2922 100644 --- a/docs/parser/item-index.md +++ b/docs/parser/item-index.md @@ -151,16 +151,16 @@ Error in `[` ((builtin) 2,11): Key 'foobar' not found Outputs a ranged subset of data from stdin * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`config`](../commands/config.md): - Query or define Murex runtime settings -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`mtac`](../commands/mtac.md): +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.reverse: `mtac`](../commands/mtac.md): Reverse the order of an array +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/parser/lambda.md b/docs/parser/lambda.md index aa82d96e9..2df796754 100644 --- a/docs/parser/lambda.md +++ b/docs/parser/lambda.md @@ -185,18 +185,18 @@ The following meta values are defined: Quickly generate arrays * [`%{}` Object Builder](../parser/create-object.md): Quickly generate objects (dictionaries / maps) -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`regexp`](../commands/regexp.md): - Regexp tools for arrays / lists of strings * [`while`](../commands/while.md): Loop until condition false +* [list.regex: `regexp`](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/parser/logical-and.md b/docs/parser/logical-and.md index 779e4723e..5b5410e76 100644 --- a/docs/parser/logical-and.md +++ b/docs/parser/logical-and.md @@ -55,16 +55,16 @@ try { Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): - Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/logical-or.md b/docs/parser/logical-or.md index 66375e684..85777a669 100644 --- a/docs/parser/logical-or.md +++ b/docs/parser/logical-or.md @@ -60,14 +60,14 @@ There is no workaround for `trypipe`. Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): - Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/multiplication.md b/docs/parser/multiplication.md index 86d661708..6019c79d1 100644 --- a/docs/parser/multiplication.md +++ b/docs/parser/multiplication.md @@ -70,8 +70,6 @@ Error in `expr` (0,1): cannot Add with string types Divides one numeric value from another (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -80,6 +78,8 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/multiply-by.md b/docs/parser/multiply-by.md index fa29bb1bc..f8457c884 100644 --- a/docs/parser/multiply-by.md +++ b/docs/parser/multiply-by.md @@ -55,8 +55,6 @@ value op value**, for example: Divides a variable by the right hand value (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -65,6 +63,8 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md index cf28c1939..07694ce2e 100644 --- a/docs/parser/null-coalescing.md +++ b/docs/parser/null-coalescing.md @@ -66,20 +66,20 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): - Print a line to the stderr * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/pipe-arrow.md b/docs/parser/pipe-arrow.md index 95fc89213..c0a533f77 100644 --- a/docs/parser/pipe-arrow.md +++ b/docs/parser/pipe-arrow.md @@ -51,20 +51,20 @@ Hello, Earth! * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): +* [`|` POSIX Pipe](../parser/pipe-posix.md): + Pipes stdout from the left hand command to stdin of the right hand command +* [io.err: `err`](../commands/err.md): Print a line to the stderr -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`regexp`](../commands/regexp.md): +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [`|` POSIX Pipe](../parser/pipe-posix.md): - Pipes stdout from the left hand command to stdin of the right hand command
diff --git a/docs/parser/pipe-err.md b/docs/parser/pipe-err.md index 9a6889f40..e4c07501b 100644 --- a/docs/parser/pipe-err.md +++ b/docs/parser/pipe-err.md @@ -45,18 +45,18 @@ Hello, world!? regexp s/world/Earth/ Overview of what a "pipeline" is * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command -* [`err`](../commands/err.md): +* [`|` POSIX Pipe](../parser/pipe-posix.md): + Pipes stdout from the left hand command to stdin of the right hand command +* [io.err: `err`](../commands/err.md): Print a line to the stderr -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`regexp`](../commands/regexp.md): +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [`|` POSIX Pipe](../parser/pipe-posix.md): - Pipes stdout from the left hand command to stdin of the right hand command
diff --git a/docs/parser/pipe-generic.md b/docs/parser/pipe-generic.md index 164fe1794..8e4268f65 100644 --- a/docs/parser/pipe-generic.md +++ b/docs/parser/pipe-generic.md @@ -52,8 +52,6 @@ To demonstrate how the previous pipeline might look without a formatted pipe: Overview of what a "pipeline" is * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`format`](../commands/format.md): @@ -62,6 +60,8 @@ To demonstrate how the previous pipeline might look without a formatted pipe: A sophisticated yet simply way to build a JSON array * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe
diff --git a/docs/parser/pipe-posix.md b/docs/parser/pipe-posix.md index 3917f3af5..f505c473a 100644 --- a/docs/parser/pipe-posix.md +++ b/docs/parser/pipe-posix.md @@ -48,17 +48,17 @@ Hello, Earth! Overview of what a "pipeline" is * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`err`](../commands/err.md): +* [io.err: `err`](../commands/err.md): Print a line to the stderr -* [`out`](../commands/out.md): +* [io.out: `out`](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`regexp`](../commands/regexp.md): +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.regex: `regexp`](../commands/regexp.md): Regexp tools for arrays / lists of strings
diff --git a/docs/parser/range.md b/docs/parser/range.md index b89100cc5..d6301f5f7 100644 --- a/docs/parser/range.md +++ b/docs/parser/range.md @@ -100,20 +100,20 @@ December Outputs an element from an array, map or table * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [`append`](../commands/append.md): - Add data to the end of an array -* [`count`](../commands/count.md): - Count items in a map, list or array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [`prepend`](../commands/prepend.md): +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.prepend: `prepend`](../commands/prepend.md): Add data to the start of an array +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array
diff --git a/docs/parser/scalar.md b/docs/parser/scalar.md index 6fc9d05c4..7541f53f6 100644 --- a/docs/parser/scalar.md +++ b/docs/parser/scalar.md @@ -173,12 +173,12 @@ do not. A sophisticated yet simply way to build a JSON array * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/single-quote.md b/docs/parser/single-quote.md index 66da30124..f81a9b871 100644 --- a/docs/parser/single-quote.md +++ b/docs/parser/single-quote.md @@ -42,16 +42,16 @@ bar Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/parser/subtract-by.md b/docs/parser/subtract-by.md index f75d214dc..9904bb6ce 100644 --- a/docs/parser/subtract-by.md +++ b/docs/parser/subtract-by.md @@ -55,8 +55,6 @@ value op value**, for example: Subtracts one numeric value from another (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -65,6 +63,8 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/subtraction.md b/docs/parser/subtraction.md index a013e6ca2..2c469ef85 100644 --- a/docs/parser/subtraction.md +++ b/docs/parser/subtraction.md @@ -70,8 +70,6 @@ Error in `expr` (0,1): cannot Add with string types Divides one numeric value from another (expression) * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -80,6 +78,8 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/parser/tilde.md b/docs/parser/tilde.md index 9fcb1c3ac..c00d37fab 100644 --- a/docs/parser/tilde.md +++ b/docs/parser/tilde.md @@ -74,12 +74,12 @@ But it cannot be expanded inside single quotes. Expand values as an array * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/types/csv.md b/docs/types/csv.md index 87bd16bdf..edd484758 100644 --- a/docs/types/csv.md +++ b/docs/types/csv.md @@ -70,20 +70,20 @@ use `config`) Outputs an element from a nested structure * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`format`](../commands/format.md): Reformat one data-type into another data-type * [`int`](../types/int.md): Whole number (primitive) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`select`](../optional/select.md): - Inlining SQL into shell pipelines * [`str` (string)](../types/str.md): string (primitive) * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [table.select: `select`](../optional/select.md): + Inlining SQL into shell pipelines ### Read more about type hooks diff --git a/docs/types/generic.md b/docs/types/generic.md index 1470e1817..c9810000a 100644 --- a/docs/types/generic.md +++ b/docs/types/generic.md @@ -38,14 +38,14 @@ executables. Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`str` (string)](../types/str.md): string (primitive) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/hcl.md b/docs/types/hcl.md index 7008b73c1..461c5e7b2 100644 --- a/docs/types/hcl.md +++ b/docs/types/hcl.md @@ -95,18 +95,18 @@ See the HashiCorp's [documentation](https://github.com/hashicorp/hcl) for HCL sy JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/int.md b/docs/types/int.md index de706ab59..56d9789f2 100644 --- a/docs/types/int.md +++ b/docs/types/int.md @@ -36,14 +36,14 @@ AMD64 or other 64bit built of Murex would see the range from Reformat one data-type into another data-type * [`num` (number)](../types/num.md): Floating point number (primitive) -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`str` (string)](../types/str.md): string (primitive) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/json.md b/docs/types/json.md index 7fdaa541c..c9de3ffce 100644 --- a/docs/types/json.md +++ b/docs/types/json.md @@ -223,20 +223,20 @@ jsonl Concatenated JSON * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`toml`](../types/toml.md): Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonc.md b/docs/types/jsonc.md index b79453b8a..62c793547 100644 --- a/docs/types/jsonc.md +++ b/docs/types/jsonc.md @@ -148,20 +148,20 @@ parser is still in beta), it is shipped as an additional data-type. JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`toml`](../types/toml.md): Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonl.md b/docs/types/jsonl.md index 2e0e4aaf8..fcf49f2cb 100644 --- a/docs/types/jsonl.md +++ b/docs/types/jsonl.md @@ -159,20 +159,20 @@ cases for JSON lines. JavaScript Object Notation (JSON) * [`jsonc`](../types/jsonc.md): Concatenated JSON -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`toml`](../types/toml.md): Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/mxjson.md b/docs/types/mxjson.md index 35c48d483..7cec1d1c3 100644 --- a/docs/types/mxjson.md +++ b/docs/types/mxjson.md @@ -60,12 +60,8 @@ Any block quoted by this method will be converted to the following valid JSON: Quickly generate objects (dictionaries / maps) * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`format`](../commands/format.md): Reformat one data-type into another data-type * [`hcl`](../types/hcl.md): @@ -76,20 +72,24 @@ Any block quoted by this method will be converted to the following valid JSON: Concatenated JSON * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`toml`](../types/toml.md): Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/num.md b/docs/types/num.md index 240d5b445..d6b6a0416 100644 --- a/docs/types/num.md +++ b/docs/types/num.md @@ -27,14 +27,14 @@ numbers. Reformat one data-type into another data-type * [`int`](../types/int.md): Whole number (primitive) -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`str` (string)](../types/str.md): string (primitive) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/str.md b/docs/types/str.md index 42afcf111..3de234e5c 100644 --- a/docs/types/str.md +++ b/docs/types/str.md @@ -40,12 +40,12 @@ This type is modelled closely on generic but is more tailored for textual Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/toml.md b/docs/types/toml.md index 56c856469..98760b073 100644 --- a/docs/types/toml.md +++ b/docs/types/toml.md @@ -86,14 +86,14 @@ hosts = [ JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/yaml.md b/docs/types/yaml.md index 45297835d..ae72a03cb 100644 --- a/docs/types/yaml.md +++ b/docs/types/yaml.md @@ -51,12 +51,12 @@ external source packages for the shell to compile. JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`open`](../commands/open.md): +* [fs.open: `open`](../commands/open.md): Open a file with a preferred handler -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [index](../parser/item-index.md): Outputs an element from an array, map or table +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index c6d703984..dc869a32f 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -132,8 +132,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Iterate through structured data * [`{ Curly Brace }`](parser/curly-brace.md): Initiates or terminates a code block -* [`|>` Truncate File](parser/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists * [`|` POSIX Pipe](parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command * [`||` Or Logical Operator](parser/logical-or.md): @@ -147,32 +145,14 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. * [`!` (not)](../commands/not-func.md): Reads the stdin and exit number from previous process and not's it's condition -* [`2darray` ](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block -* [`a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [`addheading` ](../commands/addheading.md): - Adds headings to a table * [`alias`](../commands/alias.md): Create an alias for a command -* [`alter`](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [`and`](../commands/and.md): Returns `true` or `false` depending on whether multiple conditions are met -* [`append`](../commands/append.md): - Add data to the end of an array * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`bexists`](../commands/bexists.md): - Check which builtins exist -* [`bg`](../commands/bg.md): - Run processes in the background * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`cast`](../commands/cast.md): @@ -181,58 +161,18 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Handles the exception code raised by `try` or `trypipe` * [`cd`](../commands/cd.md): Change (working) directory -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`continue`](../commands/continue.md): Terminate process of a block within a caller function -* [`count`](../commands/count.md): - Count items in a map, list or array -* [`cpuarch`](../commands/cpuarch.md): - Output the hosts CPU architecture -* [`cpucount`](../commands/cpucount.md): - Output the number of CPU cores available on your host -* [`datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [`debug`](../commands/debug.md): - Debugging information * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) -* [`err`](../commands/err.md): - Print a line to the stderr -* [`escape`](../commands/escape.md): - Escape or unescape input -* [`esccli`](../commands/esccli.md): - Escapes an array so output is valid shell code -* [`eschtml`](../commands/eschtml.md): - Encode or decodes text for HTML -* [`escurl`](../commands/escurl.md): - Encode or decodes text for the URL * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`exec`](../commands/exec.md): - Runs an executable * [`exit`](../commands/exit.md): Exit murex -* [`exitnum`](../commands/exitnum.md): - Output the exit number of the previous process -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`f`](../commands/f.md): - Lists or filters file system objects (eg files) * [`false`](../commands/false.md): Returns a `false` value -* [`fexec` ](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): - Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): - Terminate a running Murex function -* [`fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [`fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [`for`](../commands/for.md): A more familiar iteration loop to existing developers * [`foreach`](../commands/foreach.md): @@ -243,132 +183,52 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Reformat one data-type into another data-type * [`function`](../commands/function.md): Define a function block -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`global`](../commands/global.md): - Define a global variable and set it's value -* [`history`](../commands/history.md): - Outputs murex's command history * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [`jsplit` ](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter * [`key-code`](../commands/key-code.md): Returns character sequences for any key pressed (ie sent from the terminal) -* [`left`](../commands/left.md): - Left substring every item in a list * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`list.case` ](../commands/list.case.md): - Changes the character case of a string or all elements in an array -* [`lockfile`](../commands/lockfile.md): - Create and manage lock files -* [`man-get-flags` ](../commands/man-get-flags.md): - Parses man page files for command line flags -* [`man-summary`](../commands/man-summary.md): - Outputs a man page summary of a command -* [`map`](../commands/map.md): - Creates a map from two data sources -* [`match`](../commands/match.md): - Match an exact value in an array * [`method`](../commands/method.md): Define a methods supported data-types -* [`mjoin` ](../commands/mjoin.md): - Joins a list or array into a single string -* [`msort`](../commands/msort.md): - Sorts an array - data type agnostic -* [`mtac`](../commands/mtac.md): - Reverse the order of an array * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-package`](../commands/murex-package.md): - Murex's package manager * [`murex-parser` ](../commands/murex-parser.md): Runs the Murex parser against a block of code -* [`murex-update-exe-list`](../commands/murex-update-exe-list.md): - Forces Murex to rescan $PATH looking for executables * [`null`](../commands/devnull.md): null function. Similar to /dev/null -* [`open-image`](../commands/open-image.md): - Renders bitmap image data on your terminal -* [`open`](../commands/open.md): - Open a file with a preferred handler -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`os`](../commands/os.md): - Output the auto-detected OS name -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`prefix`](../commands/prefix.md): - Prefix a string to every item in a list -* [`prepend`](../commands/prepend.md): - Add data to the start of an array -* [`pretty`](../commands/pretty.md): - Prettifies JSON to make it human readable * [`private`](../commands/private.md): Define a private function block -* [`pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written * [`rand`](../commands/rand.md): Random field generator -* [`read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [`regexp`](../commands/regexp.md): - Regexp tools for arrays / lists of strings * [`return`](../commands/return.md): Exits current function scope -* [`right`](../commands/right.md): - Right substring every item in a list -* [`round`](../commands/round.md): - Round a number by a user defined precision * [`runmode`](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [`rx`](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`signal`](../commands/signal.md): Sends a signal RPC -* [`source`](../commands/source.md): - Import Murex code from another file of code block -* [`struct-keys`](../commands/struct-keys.md): - Outputs all the keys in a structure as a file path -* [`suffix`](../commands/suffix.md): - Prefix a string to every item in a list -* [`summary` ](../commands/summary.md): - Defines a summary help text for a command * [`switch`](../commands/switch.md): Blocks of cascading conditionals -* [`ta` (mkarray)](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type * [`tabulate`](../commands/tabulate.md): Table transformation tools * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts * [`time`](../commands/time.md): Returns the execution run time of a command or block -* [`tmp`](../commands/tmp.md): - Create a temporary file and write to it -* [`tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type * [`tread`](../commands/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) * [`true`](../commands/true.md): @@ -385,12 +245,150 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Command type (function, builtin, alias, etc) * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [`version`](../commands/version.md): - Get Murex version * [`which`](../commands/which.md): Locate command origin * [`while`](../commands/while.md): Loop until condition false +* [escape.cli: `esccli`](../commands/esccli.md): + Escapes an array so output is valid shell code +* [escape.html: `eschtml`](../commands/eschtml.md): + Encode or decodes text for HTML +* [escape.quote: `escape`](../commands/escape.md): + Escape or unescape input +* [escape.url: `escurl`](../commands/escurl.md): + Encode or decodes text for the URL +* [exec.*: `fexec` ](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [fs.files: `f`](../commands/f.md): + Lists or filters file system objects (eg files) +* [fs.glob: `g`](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [fs.lockfile: `lockfile`](../commands/lockfile.md): + Create and manage lock files +* [fs.new.tmpfile: `tmp`](../commands/tmp.md): + Create a temporary file and write to it +* [fs.open.image: `open-image`](../commands/open-image.md): + Renders bitmap image data on your terminal +* [fs.open: `open`](../commands/open.md): + Open a file with a preferred handler +* [fs.regex: `rx`](../commands/rx.md): + Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [fs.status: `pt`](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): + Parses man page files for command line flags +* [help.man.summary: `man-summary`](../commands/man-summary.md): + Outputs a man page summary of a command +* [io.err: `err`](../commands/err.md): + Print a line to the stderr +* [io.input: `read`](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.new.pipe: `pipe`](../commands/pipe.md): + Manage Murex named pipes +* [io.out.type: `tout`](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe +* [list.append: `append`](../commands/append.md): + Add data to the end of an array +* [list.case: `list.case` ](../commands/list.case.md): + Changes the character case of a string or all elements in an array +* [list.join: `mjoin` ](../commands/mjoin.md): + Joins a list or array into a single string +* [list.left: `left`](../commands/left.md): + Left substring every item in a list +* [list.new.str: `a` (mkarray)](../commands/a.md): + A sophisticated yet simple way to build an array or list +* [list.new.type: `ta`](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [list.prefix: `prefix`](../commands/prefix.md): + Prefix a string to every item in a list +* [list.prepend: `prepend`](../commands/prepend.md): + Add data to the start of an array +* [list.regex: `regexp`](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [list.reverse: `mtac`](../commands/mtac.md): + Reverse the order of an array +* [list.right: `right`](../commands/right.md): + Right substring every item in a list +* [list.sort: `msort`](../commands/msort.md): + Sorts an array - data type agnostic +* [list.str: `match`](../commands/match.md): + Match an exact value in an array +* [list.suffix: `suffix`](../commands/suffix.md): + Prefix a string to every item in a list +* [num.round: `round`](../commands/round.md): + Round a number by a user defined precision +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.exitnum: `exitnum`](../commands/exitnum.md): + Output the exit number of the previous process +* [proc.fg: `fg`](../commands/fg.md): + Sends a background process into the foreground +* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.kill: `fid-kill`](../commands/fid-kill.md): + Terminate a running Murex function +* [proc.list: `fid-list`](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.builtins.exist: `bexists`](../commands/bexists.md): + Check which builtins exist +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.debug: `debug`](../commands/debug.md): + Debugging information +* [shell.history: `history`](../commands/history.md): + Outputs murex's command history +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` +* [shell.packages: `murex-package`](../commands/murex-package.md): + Murex's package manager +* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): + Forces Murex to rescan $PATH looking for executables +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [shell.summary: `summary` ](../commands/summary.md): + Defines a summary help text for a command +* [shell.version: `version`](../commands/version.md): + Get Murex version +* [str.datetime: `datetime`](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [str.split: `jsplit` ](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [struct.alter: `alter`](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [struct.count: `count`](../commands/count.md): + Count items in a map, list or array +* [struct.json.pretty: `pretty`](../commands/pretty.md): + Prettifies JSON to make it human readable +* [struct.keys: `struct-keys`](../commands/struct-keys.md): + Outputs all the keys in a structure as a file path +* [struct.new.2darray: `2darray` ](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [struct.new.map: `map`](../commands/map.md): + Creates a map from two data sources +* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): + Output the hosts CPU architecture +* [sys.cpu.count: `cpucount`](../commands/cpucount.md): + Output the number of CPU cores available on your host +* [sys.os: `os`](../commands/os.md): + Output the auto-detected OS name +* [table.new.heading: `addheading` ](../commands/addheading.md): + Adds headings to a table +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value +* [var.global: `global`](../commands/global.md): + Define a global variable and set it's value +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value ### Optional Builtins @@ -406,10 +404,10 @@ are only included by default on Windows. Compress or decompress a gzip file * [`qr`](../optional/qr.md): Creates a QR code from stdin -* [`select`](../optional/select.md): - Inlining SQL into shell pipelines * [`sleep`](../optional/sleep.md): Suspends the shell for a number of seconds +* [table.select: `select`](../optional/select.md): + Inlining SQL into shell pipelines ## Data Types diff --git a/docs/user-guide/ansi.md b/docs/user-guide/ansi.md index f68ae516a..29d971cea 100644 --- a/docs/user-guide/ansi.md +++ b/docs/user-guide/ansi.md @@ -228,12 +228,12 @@ it persistent. Initiates or terminates a string (variables expanded) * [`(brace quote)`](../parser/brace-quote-func.md): Write a string to the stdout without new line (deprecated) -* [`err`](../commands/err.md): +* [io.err: `err`](../commands/err.md): Print a line to the stderr -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [`tout`](../commands/tout.md): +* [io.out.type: `tout`](../commands/tout.md): Print a string to the stdout and set it's data-type +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/user-guide/bang-prefix.md b/docs/user-guide/bang-prefix.md index 1fe50176c..bc62d9dc1 100644 --- a/docs/user-guide/bang-prefix.md +++ b/docs/user-guide/bang-prefix.md @@ -29,11 +29,11 @@ bang prefix and what the behavior of that prefix is. Reads the stdin and exit number from previous process and not's it's condition * [`and`](../commands/and.md): Returns `true` or `false` depending on whether multiple conditions are met -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`set`](../commands/set.md): +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/user-guide/fileref.md b/docs/user-guide/fileref.md index c0de95efb..ac380150b 100644 --- a/docs/user-guide/fileref.md +++ b/docs/user-guide/fileref.md @@ -58,12 +58,12 @@ empty Filename string. An introduction to Murex modules and packages * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`murex-package`](../commands/murex-package.md): +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [shell.packages: `murex-package`](../commands/murex-package.md): Murex's package manager -* [`runtime`](../commands/runtime.md): +* [shell.runtime: `runtime`](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [`source`](../commands/source.md): - Import Murex code from another file of code block
diff --git a/docs/user-guide/hint-text.md b/docs/user-guide/hint-text.md index 862227fdc..28f9a0bd2 100644 --- a/docs/user-guide/hint-text.md +++ b/docs/user-guide/hint-text.md @@ -87,7 +87,7 @@ prompt: * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? -* [`config`](../commands/config.md): +* [shell.config: `config`](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/user-guide/interactive-shell.md b/docs/user-guide/interactive-shell.md index ac80aa3a6..6c8b8c729 100644 --- a/docs/user-guide/interactive-shell.md +++ b/docs/user-guide/interactive-shell.md @@ -223,20 +223,20 @@ give you as much useful detail as it can. A list of all the terminal hotkeys and their uses * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`method`](../commands/method.md): Define a methods supported data-types * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [`runtime`](../commands/runtime.md): - Returns runtime information on the internal state of Murex * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.runtime: `runtime`](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/user-guide/job-control.md b/docs/user-guide/job-control.md index 01b8e9af9..c9777331c 100644 --- a/docs/user-guide/job-control.md +++ b/docs/user-guide/job-control.md @@ -140,19 +140,19 @@ Task 1 * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`bg`](../commands/bg.md): - Run processes in the background -* [`exec`](../commands/exec.md): - Runs an executable -* [`fexec` ](../commands/fexec.md): +* [exec.*: `fexec` ](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [`fg`](../commands/fg.md): +* [exec.file: `exec`](../commands/exec.md): + Runs an executable +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background +* [proc.fg: `fg`](../commands/fg.md): Sends a background process into the foreground -* [`fid-kill`](../commands/fid-kill.md): +* [proc.kill: `fid-kill`](../commands/fid-kill.md): Terminate a running Murex function -* [`fid-list`](../commands/fid-list.md): +* [proc.list: `fid-list`](../commands/fid-list.md): Lists all running functions within the current Murex session -* [`jobs`](../commands/fid-list.md): +* [proc.list: `jobs`](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/user-guide/modules.md b/docs/user-guide/modules.md index 648e1bdd3..7ed7b7fe0 100644 --- a/docs/user-guide/modules.md +++ b/docs/user-guide/modules.md @@ -116,14 +116,14 @@ empty Filename string. * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where -* [`murex-package`](../commands/murex-package.md): - Murex's package manager * [`private`](../commands/private.md): Define a private function block -* [`source`](../commands/source.md): - Import Murex code from another file of code block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [shell.packages: `murex-package`](../commands/murex-package.md): + Murex's package manager
diff --git a/docs/user-guide/namedpipes.md b/docs/user-guide/namedpipes.md index 5d2bcaf63..a0c806a4f 100644 --- a/docs/user-guide/namedpipes.md +++ b/docs/user-guide/namedpipes.md @@ -49,12 +49,12 @@ command parameter1 parameter2 parameter3 ## See Also -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [``](../commands/stdin.md): Read the stdin belonging to the parent code block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts +* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): + Reads from a Murex named pipe
diff --git a/docs/user-guide/pipeline.md b/docs/user-guide/pipeline.md index 722d5fef4..ed2ce02e5 100644 --- a/docs/user-guide/pipeline.md +++ b/docs/user-guide/pipeline.md @@ -79,10 +79,10 @@ document but you can read more on them in links the links below. Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`bg`](../commands/bg.md): - Run processes in the background * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [proc.bg: `bg`](../commands/bg.md): + Run processes in the background
diff --git a/docs/user-guide/profile.md b/docs/user-guide/profile.md index 353d24aad..a61de6796 100644 --- a/docs/user-guide/profile.md +++ b/docs/user-guide/profile.md @@ -79,10 +79,10 @@ how you define that value. * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [`export`](../commands/export.md): - Define an environmental variable and set it's value -* [`murex-package`](../commands/murex-package.md): +* [shell.packages: `murex-package`](../commands/murex-package.md): Murex's package manager +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/docs/user-guide/reserved-vars.md b/docs/user-guide/reserved-vars.md index e0fdf109c..7f54764b6 100644 --- a/docs/user-guide/reserved-vars.md +++ b/docs/user-guide/reserved-vars.md @@ -30,11 +30,11 @@ Error in `set` (0,1): cannot set a reserved variable: SELF Overview of what a "pipeline" is * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`export`](../commands/export.md): +* [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value -* [`global`](../commands/global.md): +* [var.global: `global`](../commands/global.md): Define a global variable and set it's value -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/user-guide/rosetta-stone.md b/docs/user-guide/rosetta-stone.md index 002a4bb2d..f9e426103 100644 --- a/docs/user-guide/rosetta-stone.md +++ b/docs/user-guide/rosetta-stone.md @@ -165,10 +165,10 @@ if you want to learn more about shell scripting in Murex. Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [`|>` Truncate File](../parser/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails +* [fs.truncate: `>`](../command/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists * [index](../parser/item-index.md): Outputs an element from an array, map or table diff --git a/docs/user-guide/scoping.md b/docs/user-guide/scoping.md index 1994f145a..ae93e13a0 100644 --- a/docs/user-guide/scoping.md +++ b/docs/user-guide/scoping.md @@ -53,10 +53,6 @@ scope. Subshells also do not create a new scope either. * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts * [`foreach`](../commands/foreach.md): @@ -67,16 +63,20 @@ scope. Subshells also do not create a new scope either. Conditional statement to execute different blocks of code depending on the result of the condition * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`openagent`](../commands/openagent.md): - Creates a handler function for `open` * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value -* [`source`](../commands/source.md): - Import Murex code from another file of code block * [`switch`](../commands/switch.md): Blocks of cascading conditionals +* [exec.include: `source`](../commands/source.md): + Import Murex code from another file or code block +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings +* [shell.open: `openagent`](../commands/openagent.md): + Creates a handler function for `open` +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index 14126bd07..55b1dbe86 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -54,10 +54,10 @@ changing this option will not cause accidental side-effects in other functions. Getting started with Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`config`](../commands/config.md): - Query or define Murex runtime settings * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators +* [shell.config: `config`](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/variables/argv.md b/docs/variables/argv.md index 55ebdd349..dfae5e0d9 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -79,20 +79,20 @@ deprecated and may be removed from future releases. Expand values as an array * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`function`](../commands/function.md): Define a function block * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/columns.md b/docs/variables/columns.md index 15805aab7..644fe1f33 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -47,12 +47,12 @@ This is a reserved variable so it cannot be changed. What's different about Murex's interactive shell? * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`str` (string)](../types/str.md): string (primitive) * [`string` (stringing)](../types/str.md): string (primitive) +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index d3fd4c9e4..cc28ad7a8 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -42,12 +42,12 @@ This is a reserved variable so it cannot be changed. * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`str` (string)](../types/str.md): string (primitive) * [`string` (stringing)](../types/str.md): string (primitive) +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index e813a5e60..ab0007158 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -47,7 +47,7 @@ This is a reserved variable so it cannot be changed. Path of current shell * [`path`](../types/path.md): Structured object for working with file and directory paths -* [`set`](../commands/set.md): +* [var.set: `set`](../commands/set.md): Define a local variable and set it's value
diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index 2113b895b..198a69b5e 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -64,18 +64,18 @@ then variables `$1` through to `$19` (inclusive) will all be set. Array of the command name and parameters within a given scope * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`function`](../commands/function.md): Define a function block -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/params.md b/docs/variables/params.md index d835cfcf9..87adb18c3 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -67,20 +67,20 @@ This is a reserved variable so it cannot be changed. Expand values as an array * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line * [`function`](../commands/function.md): Define a function block * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`out`](../commands/out.md): - Print a string to the stdout with a trailing new line character * [`private`](../commands/private.md): Define a private function block -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [io.out: `out`](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/pwd.md b/docs/variables/pwd.md index 04f20cefb..e4273cf9c 100644 --- a/docs/variables/pwd.md +++ b/docs/variables/pwd.md @@ -43,10 +43,10 @@ It is updated via `cd` however you can overwrite its value manually via `export` History of each change to the sessions working directory * [`cd`](../commands/cd.md): Change (working) directory -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`path`](../types/path.md): Structured object for working with file and directory paths +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index a54272d7b..87cc1908f 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -70,10 +70,10 @@ It is updated via `cd` however you can overwrite its value manually via `set`. JavaScript Object Notation (JSON) * [`path`](../types/path.md): Structured object for working with file and directory paths -* [`set`](../commands/set.md): - Define a local variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [var.set: `set`](../commands/set.md): + Define a local variable and set it's value
diff --git a/docs/variables/shell.md b/docs/variables/shell.md index 1e3bb1ec7..eac886a42 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -45,10 +45,10 @@ precision. * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell -* [`export`](../commands/export.md): - Define an environmental variable and set it's value * [`string` (stringing)](../types/str.md): string (primitive) +* [var.env: `export`](../commands/export.md): + Define an environmental variable and set it's value
diff --git a/integrations/_namespaces_any.mx b/integrations/_namespaces_any.mx index 7965ebdd2..cfe75d935 100644 --- a/integrations/_namespaces_any.mx +++ b/integrations/_namespaces_any.mx @@ -1,71 +1,106 @@ -alias list.sort = msort -alias list.reverse = mtac -alias list.prepend = prepend -alias list.append = append -alias list.prefix = prefix -alias list.suffix = suffix -alias list.left = left -alias list.right = right -alias list.regex = regexp -alias !list.regex = !regexp -alias list.match = match -alias !list.match = !match -alias list.join = mjoin -alias list.new.str = a -alias list.new.type = ta +alias list.sort = msort +alias list.reverse = mtac +alias list.prepend = prepend +alias list.append = append +alias list.prefix = prefix +alias list.suffix = suffix +alias list.left = left +alias list.right = right +alias list.regex = regexp +alias !list.regex = !regexp +alias list.str = match +alias !list.str = !match +alias list.join = mjoin +alias list.new.str = a +alias list.new.type = ta + +alias str.split = jsplit +alias str.datetime = datetime + +alias num.round = round alias struct.count = count +alias struct.alter = alter +alias struct.keys = struct-keys alias struct.new.map = map alias struct.new.2darray = 2darray -alias escape.quote = escape -alias !escape.quote = !escape -alias escape.html = eschtml -alias !escape.html = !eschtml -alias escape.url = escurl -alias !escape.url = !escurl -alias escape.cli = esccli +alias table.select = select +alias table.new.heading = addheading + +alias var.set = set +alias !var.set = !set +alias var.global = global +alias !var.global = !global +alias var.env = export +alias !var.env = !export + +alias escape.quote = escape +alias !escape.quote = !escape +alias escape.html = eschtml +alias !escape.html = !eschtml +alias escape.url = escurl +alias !escape.url = !escurl +alias escape.cli = esccli -alias io.out = out -alias io.err = err -alias io.pipe = read-named-pipe -alias io.stat = pt +alias io.out = out +alias io.err = err +alias io.pipe = read-named-pipe +alias io.status = pt +alias io.new.pipe = pipe +alias !io.new.pipe = !pipe -alias fs.glob = g -alias !fs.glob = !g -alias fs.regex = rx -alias !fs.regex = !rx -alias fs.file = f -alias fs.lockfile = lockfile -alias fs.new.temp.file = tmp +alias fs.glob = g +alias !fs.glob = !g +alias fs.regex = rx +alias !fs.regex = !rx +alias fs.files = f +alias fs.lockfile = lockfile +alias fs.new.tmpfile = tmp +alias fs.truncate = ">" +alias fs.append = ">>" +alias fs.open = open +alias fs.open.image= open-image alias sys.os = os alias sys.cpu.arch = cpuarch alias sys.cpu.count = cpucount -alias shell.alias = alias -alias !shell.alias = !alias -alias shell.function = function -alias !shell.function = !function -alias shell.private = private -alias shell.pipe = pipe -alias !shell.pipe = !pipe -alias shell.event = event -alias !shell.event = !event +alias shell.alias = alias +alias !shell.alias = !alias +alias shell.function = function +alias !shell.function = !function +alias shell.private = private +alias shell.pipe = pipe +alias !shell.pipe = !pipe +alias shell.event = event +alias !shell.event = !event +alias shell.autocomplete= autocomplete +alias shell.packages = murex-package +alias shell.rescan.path = murex-update-exe-list +alias shell.runtime = runtime +alias shell.config = config +alias shell.builtins.exist = bexists +alias shell.history = history +alias shell.summary = summary +alias !shell.summary = !summary +alias shell.open = openagent -alias shell.exec.builtin = fexec builtin -alias shell.exec.function = fexec function -alias shell.exec.private = fexec private +alias help = murex-docs +alias help.man.summary = man-summary +alias help.man.flags = man-get-flags -alias murex.packages = murex-package -alias murex.rescan.path = murex-update-exe-list -alias murex.runtime = runtime -alias murex.config = config +alias exec.file = exec +alias exec.include = source +alias exec.builtin = fexec builtin +alias exec.function = fexec function +alias exec.private = fexec private -alias proc.fg = fg -alias proc.bg = bg -alias proc.jobs = fid-list --jobs -alias proc.list = fid-list -alias proc.kill = fid-kill -alias proc.kill.all = fid-killall -alias proc.send.signal = signal \ No newline at end of file +alias proc.exitnum = exitnum +alias proc.fg = fg +alias proc.bg = bg +alias proc.jobs = fid-list --jobs +alias proc.list = fid-list +alias proc.kill = fid-kill +alias proc.kill.all = fid-killall +alias proc.send.signal = signal \ No newline at end of file diff --git a/version.svg b/version.svg index e3c2d65e7..18ace1a5c 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.3100Version6.3.3100 +Version: 6.3.3200Version6.3.3200 From f4cfa5711b903e1ba97192ffd0929d2dd36fed9f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 29 Aug 2024 22:34:04 +0100 Subject: [PATCH 065/142] #860 updated doc titles --- builtins/core/arraytools/2darray_doc.yaml | 2 +- builtins/core/arraytools/addheading_doc.yaml | 2 +- builtins/core/arraytools/map_doc.yaml | 2 +- .../core/autocomplete/autocomplete_doc.yaml | 2 +- builtins/core/config/config_doc.yaml | 2 +- builtins/core/datatools/alter_doc.yaml | 2 +- builtins/core/datatools/count_doc.yaml | 2 +- builtins/core/datatools/structkeys_doc.yaml | 2 +- builtins/core/escape/escape_doc.yaml | 8 +- builtins/core/io/echo_doc.yaml | 6 +- builtins/core/io/f_doc.yaml | 2 +- builtins/core/io/file_doc.yaml | 6 +- builtins/core/io/g_doc.yaml | 2 +- builtins/core/io/lockfile_doc.yaml | 2 +- builtins/core/io/read_doc.yaml | 4 +- builtins/core/io/rx_doc.yaml | 2 +- builtins/core/io/tmp_doc.yaml | 2 +- builtins/core/lists/append_doc.yaml | 4 +- builtins/core/lists/case_doc.yaml | 2 +- builtins/core/lists/jsplit_doc.yaml | 2 +- builtins/core/lists/mjoin_doc.yaml | 2 +- builtins/core/lists/msort_doc.yaml | 2 +- builtins/core/lists/mtac_doc.yaml | 2 +- builtins/core/lists/push_pop_doc.yaml | 8 +- builtins/core/lists/regexp_doc.yaml | 4 +- builtins/core/management/debug_doc.yaml | 2 +- builtins/core/management/fexec_doc.yaml | 2 +- builtins/core/management/functions_doc.yaml | 8 +- builtins/core/management/history_doc.yaml | 2 +- builtins/core/management/shell_doc.yaml | 6 +- builtins/core/management/source_doc.yaml | 2 +- builtins/core/management/version_doc.yaml | 2 +- builtins/core/mkarray/array_doc.yaml | 10 +- builtins/core/modules/murex-package_doc.yaml | 4 +- builtins/core/open/open_doc.yaml | 2 +- builtins/core/openimage/open-image_doc.yaml | 2 +- builtins/core/pipe/namedpipe_doc.yaml | 5 +- builtins/core/pipe/pipe_doc.yaml | 2 +- builtins/core/pretty/pretty_doc.yaml | 2 +- builtins/core/processes/bgfg_doc.yaml | 4 +- builtins/core/processes/fid-list_doc.yaml | 2 +- builtins/core/processes/kill_doc.yaml | 6 +- builtins/core/runtime/runtime_doc.yaml | 2 +- builtins/core/structs/function_doc.yaml | 22 ++- builtins/core/system/system_doc.yaml | 6 +- builtins/docs/summaries.go | 160 +++++++++-------- docs/blog/reading_lists.md | 6 +- docs/changelog/v2.0.md | 10 +- docs/changelog/v2.1.md | 8 +- docs/changelog/v2.10.md | 8 +- docs/changelog/v2.11.md | 10 +- docs/changelog/v2.2.md | 2 +- docs/changelog/v2.3.md | 6 +- docs/changelog/v2.4.md | 12 +- docs/changelog/v2.5.md | 12 +- docs/changelog/v2.6.md | 4 +- docs/changelog/v2.7.md | 8 +- docs/changelog/v2.8.md | 6 +- docs/changelog/v2.9.md | 14 +- docs/changelog/v3.0.md | 12 +- docs/changelog/v4.0.md | 6 +- docs/changelog/v4.2.md | 14 +- docs/changelog/v4.3.md | 4 +- docs/changelog/v4.4.md | 14 +- docs/changelog/v5.0.md | 10 +- docs/changelog/v5.1.md | 2 +- docs/changelog/v5.2.md | 8 +- docs/changelog/v5.3.md | 6 +- docs/changelog/v6.0.md | 6 +- docs/changelog/v6.1.md | 8 +- docs/changelog/v6.2.md | 2 +- docs/commands/2darray.md | 20 +-- docs/commands/README.md | 164 +++++++++--------- docs/commands/a.md | 14 +- docs/commands/addheading.md | 20 +-- docs/commands/alias.md | 22 +-- docs/commands/alter.md | 10 +- docs/commands/append.md | 20 +-- docs/commands/autocomplete.md | 22 +-- docs/commands/bexists.md | 6 +- docs/commands/bg.md | 16 +- docs/commands/break.md | 10 +- docs/commands/cast.md | 6 +- docs/commands/cd.md | 2 +- docs/commands/config.md | 16 +- docs/commands/continue.md | 10 +- docs/commands/count.md | 22 +-- docs/commands/cpuarch.md | 6 +- docs/commands/cpucount.md | 6 +- docs/commands/datetime.md | 4 +- docs/commands/debug.md | 4 +- docs/commands/err.md | 22 +-- docs/commands/escape.md | 8 +- docs/commands/esccli.md | 14 +- docs/commands/eschtml.md | 8 +- docs/commands/escurl.md | 8 +- docs/commands/event.md | 10 +- docs/commands/exec.md | 26 +-- docs/commands/exitnum.md | 4 +- docs/commands/expr.md | 4 +- docs/commands/f.md | 6 +- docs/commands/fexec.md | 30 ++-- docs/commands/fg.md | 16 +- docs/commands/fid-kill.md | 24 +-- docs/commands/fid-killall.md | 26 +-- docs/commands/fid-list.md | 26 +-- docs/{parser => commands}/file-truncate.md | 21 +-- docs/commands/for.md | 4 +- docs/commands/foreach.md | 10 +- docs/commands/format.md | 2 +- docs/commands/function.md | 24 +-- docs/commands/g.md | 10 +- docs/commands/get-type.md | 12 +- docs/commands/get.md | 2 +- docs/commands/getfile.md | 4 +- docs/commands/history.md | 6 +- docs/commands/if.md | 2 +- docs/commands/ja.md | 8 +- docs/commands/jsplit.md | 20 +-- docs/commands/key-code.md | 2 +- docs/commands/left.md | 16 +- docs/commands/list.case.md | 2 +- docs/commands/lockfile.md | 6 +- docs/commands/man-get-flags.md | 6 +- docs/commands/man-summary.md | 8 +- docs/commands/map.md | 16 +- docs/commands/match.md | 28 +-- docs/commands/method.md | 20 ++- docs/commands/mjoin.md | 4 +- docs/commands/msort.md | 18 +- docs/commands/mtac.md | 26 +-- docs/commands/murex-docs.md | 14 +- docs/commands/murex-package.md | 20 +-- docs/commands/murex-update-exe-list.md | 8 +- docs/commands/namedpipe.md | 16 +- docs/commands/open-image.md | 4 +- docs/commands/open.md | 8 +- docs/commands/openagent.md | 6 +- docs/commands/os.md | 6 +- docs/commands/out.md | 18 +- docs/commands/pipe.md | 18 +- docs/commands/post.md | 2 +- docs/commands/prefix.md | 16 +- docs/commands/prepend.md | 20 +-- docs/commands/pretty.md | 8 +- docs/commands/private.md | 26 +-- docs/commands/pt.md | 4 +- docs/commands/read.md | 14 +- docs/commands/regexp.md | 28 +-- docs/commands/return.md | 12 +- docs/commands/right.md | 16 +- docs/commands/runmode.md | 18 +- docs/commands/runtime.md | 30 ++-- docs/commands/rx.md | 10 +- docs/commands/signal.md | 4 +- docs/commands/source.md | 22 +-- docs/commands/stdin.md | 17 +- docs/commands/struct-keys.md | 2 +- docs/commands/suffix.md | 16 +- docs/commands/summary.md | 16 +- docs/commands/ta.md | 8 +- docs/commands/tabulate.md | 2 +- docs/commands/test.md | 4 +- docs/commands/time.md | 2 +- docs/commands/tmp.md | 8 +- docs/commands/tout.md | 8 +- docs/commands/try.md | 2 +- docs/commands/tryerr.md | 2 +- docs/commands/trypipe.md | 2 +- docs/commands/trypipeerr.md | 2 +- docs/commands/type.md | 12 +- docs/commands/unsafe.md | 2 +- docs/commands/version.md | 20 +-- docs/commands/which.md | 12 +- docs/commands/while.md | 4 +- docs/events/oncommandcompletion.md | 16 +- docs/events/onfilesystemchange.md | 2 +- docs/events/onkeypress.md | 2 +- docs/events/onpreview.md | 6 +- docs/events/onprompt.md | 2 +- docs/events/onsecondselapsed.md | 2 +- docs/integrations/chatgpt.md | 2 +- docs/integrations/cheatsh.md | 2 +- docs/integrations/iterm2.md | 2 +- docs/integrations/kitty.md | 2 +- docs/integrations/make.md | 2 +- docs/integrations/man-pages.md | 2 +- docs/integrations/spellcheck.md | 8 +- docs/integrations/terminology.md | 2 +- docs/integrations/yarn.md | 2 +- docs/mkarray/character.md | 6 +- docs/mkarray/date.md | 8 +- docs/mkarray/decimal.md | 6 +- docs/mkarray/non-decimal.md | 6 +- docs/mkarray/special.md | 8 +- docs/optional/base64.md | 8 +- docs/optional/bz2.md | 8 +- docs/optional/gz.md | 8 +- docs/optional/qr.md | 2 +- docs/optional/select.md | 2 +- docs/optional/sleep.md | 2 +- docs/parser/add-with.md | 2 +- docs/parser/addition.md | 2 +- docs/parser/array.md | 2 +- docs/parser/assign-or-merge.md | 4 +- docs/parser/brace-quote-func.md | 14 +- docs/parser/brace-quote.md | 2 +- docs/parser/c-style-fun.md | 4 +- docs/parser/create-array.md | 4 +- docs/parser/curly-brace.md | 8 +- docs/parser/divide-by.md | 2 +- docs/parser/division.md | 2 +- docs/parser/double-quote.md | 2 +- docs/parser/element.md | 10 +- docs/parser/elvis.md | 4 +- docs/parser/expr-inlined.md | 2 +- docs/parser/file-append.md | 8 +- docs/parser/item-index.md | 10 +- docs/parser/lambda.md | 4 +- docs/parser/logical-and.md | 4 +- docs/parser/logical-or.md | 4 +- docs/parser/multiplication.md | 2 +- docs/parser/multiply-by.md | 2 +- docs/parser/null-coalescing.md | 4 +- docs/parser/pipe-arrow.md | 8 +- docs/parser/pipe-err.md | 8 +- docs/parser/pipe-generic.md | 2 +- docs/parser/pipe-posix.md | 8 +- docs/parser/range.md | 14 +- docs/parser/scalar.md | 2 +- docs/parser/single-quote.md | 2 +- docs/parser/subtract-by.md | 2 +- docs/parser/subtraction.md | 2 +- docs/parser/tilde.md | 2 +- docs/types/csv.md | 2 +- docs/types/generic.md | 4 +- docs/types/hcl.md | 6 +- docs/types/int.md | 4 +- docs/types/json.md | 6 +- docs/types/jsonc.md | 6 +- docs/types/jsonl.md | 6 +- docs/types/mxjson.md | 10 +- docs/types/num.md | 4 +- docs/types/str.md | 4 +- docs/types/toml.md | 4 +- docs/types/yaml.md | 4 +- docs/user-guide/README.md | 164 +++++++++--------- docs/user-guide/ansi.md | 8 +- docs/user-guide/bang-prefix.md | 2 +- docs/user-guide/fileref.md | 6 +- docs/user-guide/hint-text.md | 2 +- docs/user-guide/interactive-shell.md | 10 +- docs/user-guide/job-control.md | 14 +- docs/user-guide/modules.md | 8 +- docs/user-guide/namedpipes.md | 6 +- docs/user-guide/pipeline.md | 2 +- docs/user-guide/profile.md | 2 +- docs/user-guide/rosetta-stone.md | 2 +- docs/user-guide/scoping.md | 14 +- docs/user-guide/strict-types.md | 2 +- docs/variables/argv.md | 12 +- docs/variables/numeric.md | 12 +- docs/variables/params.md | 12 +- docs/variables/self.md | 4 +- integrations/_namespaces_any.mx | 8 +- 265 files changed, 1299 insertions(+), 1246 deletions(-) rename docs/{parser => commands}/file-truncate.md (84%) diff --git a/builtins/core/arraytools/2darray_doc.yaml b/builtins/core/arraytools/2darray_doc.yaml index 7a36652aa..3da1c2b56 100644 --- a/builtins/core/arraytools/2darray_doc.yaml +++ b/builtins/core/arraytools/2darray_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: 2darray Title: >- - struct.new.2darray: `2darray` + struct.new.2darray CategoryID: commands Summary: >- Create a 2D JSON array from multiple input sources diff --git a/builtins/core/arraytools/addheading_doc.yaml b/builtins/core/arraytools/addheading_doc.yaml index 0948d083f..4241f9873 100644 --- a/builtins/core/arraytools/addheading_doc.yaml +++ b/builtins/core/arraytools/addheading_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: addheading Title: >- - table.new.heading: `addheading` + table.add.heading CategoryID: commands Summary: >- Adds headings to a table diff --git a/builtins/core/arraytools/map_doc.yaml b/builtins/core/arraytools/map_doc.yaml index 079ca618a..d0cccfa82 100644 --- a/builtins/core/arraytools/map_doc.yaml +++ b/builtins/core/arraytools/map_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: map Title: >- - struct.new.map: `map` + struct.new.map (`map`) CategoryID: commands Summary: >- Creates a map from two data sources diff --git a/builtins/core/autocomplete/autocomplete_doc.yaml b/builtins/core/autocomplete/autocomplete_doc.yaml index dd1c5bae0..075e99241 100644 --- a/builtins/core/autocomplete/autocomplete_doc.yaml +++ b/builtins/core/autocomplete/autocomplete_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: "autocomplete" Title: >+ - shell.autocomplete: `autocomplete` + shell.autocomplete CategoryID: commands Summary: >- Set definitions for tab-completion in the command line diff --git a/builtins/core/config/config_doc.yaml b/builtins/core/config/config_doc.yaml index 09ba00816..62c3c2539 100644 --- a/builtins/core/config/config_doc.yaml +++ b/builtins/core/config/config_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: config Title: >+ - shell.config: `config` + shell.config CategoryID: commands Summary: >- Query or define Murex runtime settings diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index a37608145..04a57b4d5 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: alter Title: >+ - struct.alter: `alter` + struct.alter CategoryID: commands Summary: >- Change a value within a structured data-type and pass that change along the diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index ee7aa7767..9ef5875ac 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: count Title: >+ - struct.count: `count` + struct.count CategoryID: commands Summary: >- Count items in a map, list or array diff --git a/builtins/core/datatools/structkeys_doc.yaml b/builtins/core/datatools/structkeys_doc.yaml index 77d347b0c..7deead165 100644 --- a/builtins/core/datatools/structkeys_doc.yaml +++ b/builtins/core/datatools/structkeys_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: struct-keys Title: >+ - struct.keys: `struct-keys` + struct.keys CategoryID: commands Summary: >- Outputs all the keys in a structure as a file path diff --git a/builtins/core/escape/escape_doc.yaml b/builtins/core/escape/escape_doc.yaml index 568b8b19c..3df3b0664 100644 --- a/builtins/core/escape/escape_doc.yaml +++ b/builtins/core/escape/escape_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: escape Title: >+ - escape.quote: `escape` + escape.quote CategoryID: commands Summary: >- Escape or unescape input @@ -51,7 +51,7 @@ - DocumentID: eschtml Title: >+ - escape.html: `eschtml` + escape.html CategoryID: commands Summary: >- Encode or decodes text for HTML @@ -110,7 +110,7 @@ - DocumentID: escurl Title: >+ - escape.url: `escurl` + escape.url CategoryID: commands Summary: >- Encode or decodes text for the URL @@ -169,7 +169,7 @@ - DocumentID: esccli Title: >+ - escape.cli: `esccli` + escape.cli CategoryID: commands Summary: >- Escapes an array so output is valid shell code diff --git a/builtins/core/io/echo_doc.yaml b/builtins/core/io/echo_doc.yaml index ad393070d..3a63ce6ad 100644 --- a/builtins/core/io/echo_doc.yaml +++ b/builtins/core/io/echo_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: out Title: >+ - io.out: `out` + io.out CategoryID: commands Summary: >- Print a string to the stdout with a trailing new line character @@ -53,7 +53,7 @@ - DocumentID: tout Title: >+ - io.out.type: `tout` + io.out.type (`tout`) CategoryID: commands Summary: >- Print a string to the stdout and set it's data-type @@ -144,7 +144,7 @@ - DocumentID: err Title: >+ - io.err: `err` + io.err CategoryID: commands Summary: >- Print a line to the stderr diff --git a/builtins/core/io/f_doc.yaml b/builtins/core/io/f_doc.yaml index 42d50fbca..515bd1fff 100644 --- a/builtins/core/io/f_doc.yaml +++ b/builtins/core/io/f_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: f Title: >+ - fs.files: `f` + fs.files (`f`) CategoryID: commands Summary: >- Lists or filters file system objects (eg files) diff --git a/builtins/core/io/file_doc.yaml b/builtins/core/io/file_doc.yaml index 9c89a0a08..3cdae670c 100644 --- a/builtins/core/io/file_doc.yaml +++ b/builtins/core/io/file_doc.yaml @@ -1,7 +1,7 @@ - DocumentID: file-truncate Title: >+ - fs.truncate: `>` - CategoryID: command + fs.truncate (`>`) + CategoryID: commands Summary: >- Writes stdin to disk - overwriting contents if file already exists Description: |- @@ -37,7 +37,7 @@ - DocumentID: pt Title: >+ - fs.status: `pt` + io.status (`pt`) CategoryID: commands Summary: >- Pipe telemetry. Writes data-types and bytes written diff --git a/builtins/core/io/g_doc.yaml b/builtins/core/io/g_doc.yaml index ea6574933..2077000ca 100644 --- a/builtins/core/io/g_doc.yaml +++ b/builtins/core/io/g_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: g Title: >+ - fs.glob: `g` + fs.glob (`g`) CategoryID: commands Summary: >- Glob pattern matching for file system objects (eg `*.txt`) diff --git a/builtins/core/io/lockfile_doc.yaml b/builtins/core/io/lockfile_doc.yaml index 5aa7c91db..12869d711 100644 --- a/builtins/core/io/lockfile_doc.yaml +++ b/builtins/core/io/lockfile_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: lockfile Title: >+ - fs.lockfile: `lockfile` + fs.lockfile CategoryID: commands Summary: >- Create and manage lock files diff --git a/builtins/core/io/read_doc.yaml b/builtins/core/io/read_doc.yaml index 3a6353cbc..790111989 100644 --- a/builtins/core/io/read_doc.yaml +++ b/builtins/core/io/read_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: read Title: >+ - io.input: `read` + io.read CategoryID: commands Summary: >- `read` a line of input from the user and store as a variable @@ -90,7 +90,7 @@ - DocumentID: tread Title: >+ `tread` - CategoryID: commands + CategoryID: deprecated Summary: >- `read` a line of input from the user and store as a user defined *typed* variable (deprecated) Description: |- diff --git a/builtins/core/io/rx_doc.yaml b/builtins/core/io/rx_doc.yaml index 7e7ebe947..9425518dd 100644 --- a/builtins/core/io/rx_doc.yaml +++ b/builtins/core/io/rx_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: rx Title: >+ - fs.regex: `rx` + fs.regex (`rx`) CategoryID: commands Summary: >- Regexp pattern matching for file system objects (eg `.*\\.txt`) diff --git a/builtins/core/io/tmp_doc.yaml b/builtins/core/io/tmp_doc.yaml index 74b3afa42..ef00b81e9 100644 --- a/builtins/core/io/tmp_doc.yaml +++ b/builtins/core/io/tmp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: tmp Title: >+ - fs.new.tmpfile: `tmp` + fs.tmpfile (`tmp`) CategoryID: commands Summary: >- Create a temporary file and write to it diff --git a/builtins/core/lists/append_doc.yaml b/builtins/core/lists/append_doc.yaml index d14543ff2..61fd7e1b2 100644 --- a/builtins/core/lists/append_doc.yaml +++ b/builtins/core/lists/append_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: prepend Title: >- - list.prepend: `prepend` + list.prepend CategoryID: commands Summary: >- Add data to the start of an array @@ -55,7 +55,7 @@ - DocumentID: append Title: >+ - list.append: `append` + list.append CategoryID: commands Summary: >- Add data to the end of an array diff --git a/builtins/core/lists/case_doc.yaml b/builtins/core/lists/case_doc.yaml index 74d52d2c9..eb771d75f 100644 --- a/builtins/core/lists/case_doc.yaml +++ b/builtins/core/lists/case_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: list.case Title: >- - list.case: `list.case` + list.case CategoryID: commands Summary: >- Changes the character case of a string or all elements in an array diff --git a/builtins/core/lists/jsplit_doc.yaml b/builtins/core/lists/jsplit_doc.yaml index b806bfd52..5b1f663dd 100644 --- a/builtins/core/lists/jsplit_doc.yaml +++ b/builtins/core/lists/jsplit_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: jsplit Title: >- - str.split: `jsplit` + str.split CategoryID: commands Summary: >- Splits stdin into a JSON array based on a regex parameter diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml index 98bdaec09..f923cb3d1 100644 --- a/builtins/core/lists/mjoin_doc.yaml +++ b/builtins/core/lists/mjoin_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mjoin Title: >- - list.join: `mjoin` + list.join CategoryID: commands Summary: >- Joins a list or array into a single string diff --git a/builtins/core/lists/msort_doc.yaml b/builtins/core/lists/msort_doc.yaml index d2e956936..e67577970 100644 --- a/builtins/core/lists/msort_doc.yaml +++ b/builtins/core/lists/msort_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: msort Title: >- - list.sort: `msort` + list.sort CategoryID: commands Summary: >- Sorts an array - data type agnostic diff --git a/builtins/core/lists/mtac_doc.yaml b/builtins/core/lists/mtac_doc.yaml index ec15d82c2..a5c9480d0 100644 --- a/builtins/core/lists/mtac_doc.yaml +++ b/builtins/core/lists/mtac_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mtac Title: >+ - list.reverse: `mtac` + list.reverse (`mtac`) CategoryID: commands Summary: >- Reverse the order of an array diff --git a/builtins/core/lists/push_pop_doc.yaml b/builtins/core/lists/push_pop_doc.yaml index 8a247ffad..24a90928c 100644 --- a/builtins/core/lists/push_pop_doc.yaml +++ b/builtins/core/lists/push_pop_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: left Title: >+ - list.left: `left` + list.left CategoryID: commands Summary: >- Left substring every item in a list @@ -61,7 +61,7 @@ - DocumentID: right Title: >+ - list.right: `right` + list.right CategoryID: commands Summary: >- Right substring every item in a list @@ -122,7 +122,7 @@ - DocumentID: prefix Title: >+ - list.prefix: `prefix` + list.prefix CategoryID: commands Summary: >- Prefix a string to every item in a list @@ -167,7 +167,7 @@ - DocumentID: suffix Title: >+ - list.suffix: `suffix` + list.suffix CategoryID: commands Summary: >- Prefix a string to every item in a list diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index 5b023b147..53770ea8f 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: match Title: >+ - list.str: `match` + list.str (`match`) CategoryID: commands Summary: >- Match an exact value in an array @@ -86,7 +86,7 @@ - DocumentID: regexp Title: >+ - list.regex: `regexp` + list.regex CategoryID: commands Summary: >- Regexp tools for arrays / lists of strings diff --git a/builtins/core/management/debug_doc.yaml b/builtins/core/management/debug_doc.yaml index 27662eae6..ab8cbf478 100644 --- a/builtins/core/management/debug_doc.yaml +++ b/builtins/core/management/debug_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: debug Title: >+ - shell.debug: `debug` + shell.debug CategoryID: commands Summary: >- Debugging information diff --git a/builtins/core/management/fexec_doc.yaml b/builtins/core/management/fexec_doc.yaml index c1e18b60c..00cc49c2d 100644 --- a/builtins/core/management/fexec_doc.yaml +++ b/builtins/core/management/fexec_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fexec Title: >+ - exec.*: `fexec` + exec.* (`fexec`) CategoryID: commands Summary: >- Execute a command or function, bypassing the usual order of precedence. diff --git a/builtins/core/management/functions_doc.yaml b/builtins/core/management/functions_doc.yaml index 19aa5d45b..4c96d062a 100644 --- a/builtins/core/management/functions_doc.yaml +++ b/builtins/core/management/functions_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: exitnum Title: >+ - proc.exitnum: `exitnum` + proc.exitnum CategoryID: commands Summary: >- Output the exit number of the previous process @@ -28,7 +28,7 @@ - DocumentID: murex-update-exe-list Title: >+ - shell.rescan.path: `murex-update-exe-list` + shell.rescan.path CategoryID: commands Summary: >- Forces Murex to rescan $PATH looking for executables @@ -61,7 +61,7 @@ - DocumentID: man-summary Title: >+ - help.man.summary: `man-summary` + help.man.summary CategoryID: commands Summary: >- Outputs a man page summary of a command @@ -188,7 +188,7 @@ - DocumentID: bexists Title: >+ - shell.builtins.exist: `bexists` + shell.builtins.exist CategoryID: commands Summary: >- Check which builtins exist diff --git a/builtins/core/management/history_doc.yaml b/builtins/core/management/history_doc.yaml index 6b52212df..6062e7652 100644 --- a/builtins/core/management/history_doc.yaml +++ b/builtins/core/management/history_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: history Title: >+ - shell.history: `history` + shell.history CategoryID: commands Summary: >- Outputs murex's command history diff --git a/builtins/core/management/shell_doc.yaml b/builtins/core/management/shell_doc.yaml index 73b26470c..3391e9302 100644 --- a/builtins/core/management/shell_doc.yaml +++ b/builtins/core/management/shell_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: summary Title: >+ - shell.summary: `summary` + shell.summary CategoryID: commands Summary: >- Defines a summary help text for a command @@ -60,7 +60,7 @@ - DocumentID: murex-parser Title: >+ `murex-parser` - CategoryID: commands + CategoryID: deprecated Summary: >- Runs the Murex parser against a block of code Description: |- @@ -119,7 +119,7 @@ - DocumentID: man-get-flags Title: >+ - help.man.flags: `man-get-flags` + help.man.flags CategoryID: commands Summary: >- Parses man page files for command line flags diff --git a/builtins/core/management/source_doc.yaml b/builtins/core/management/source_doc.yaml index 2c4878523..aab9d4f04 100644 --- a/builtins/core/management/source_doc.yaml +++ b/builtins/core/management/source_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: source Title: >+ - exec.include: `source` + exec.include (`source`) CategoryID: commands Summary: >- Import Murex code from another file or code block diff --git a/builtins/core/management/version_doc.yaml b/builtins/core/management/version_doc.yaml index 252fc087e..af3921bd9 100644 --- a/builtins/core/management/version_doc.yaml +++ b/builtins/core/management/version_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: version Title: >+ - shell.version: `version` + shell.version CategoryID: commands Summary: >- Get Murex version diff --git a/builtins/core/mkarray/array_doc.yaml b/builtins/core/mkarray/array_doc.yaml index 0dd0b003d..c67beb4fc 100644 --- a/builtins/core/mkarray/array_doc.yaml +++ b/builtins/core/mkarray/array_doc.yaml @@ -1,12 +1,12 @@ - DocumentID: a Title: >+ - list.new.str: `a` (mkarray) + list.new.str (`a`) CategoryID: commands Summary: >- - A sophisticated yet simple way to build an array or list + A sophisticated yet simple way to build an array or list (mkarray) Description: |- - Pronounced "make array", like `mkdir` (etc), Murex has a pretty sophisticated - builtin for generating arrays. Think like bash's `{1..9}` syntax: + _mkarray_, pronounced "make array" like `mkdir` (etc), is Murex's sophisticated + syntax for generating arrays. Think like bash's `{1..9}` syntax: ``` a [1..9] @@ -14,6 +14,8 @@ Except Murex also supports other sets of ranges like dates, days of the week, and alternative number bases. + + This builtin streams arrays as a list of strings (`str`). Usage: |- {{ include "gen/includes/mkarray-range-usage.inc.md" }} Examples: |- diff --git a/builtins/core/modules/murex-package_doc.yaml b/builtins/core/modules/murex-package_doc.yaml index 63435fa39..51d335153 100644 --- a/builtins/core/modules/murex-package_doc.yaml +++ b/builtins/core/modules/murex-package_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: murex-package Title: >+ - shell.packages: `murex-package` + shell.packages (`murex-package`) CategoryID: commands Summary: >- Murex's package manager @@ -90,7 +90,7 @@ `murex-package list loaded` instead. This is also equivalent to using `runtime --modules`. Synonyms: - - murex.package + - murex-package - shell.packages Related: - runtime diff --git a/builtins/core/open/open_doc.yaml b/builtins/core/open/open_doc.yaml index 39fc26a54..37dcc9da1 100644 --- a/builtins/core/open/open_doc.yaml +++ b/builtins/core/open/open_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open Title: >+ - fs.open: `open` + fs.open CategoryID: commands Summary: >- Open a file with a preferred handler diff --git a/builtins/core/openimage/open-image_doc.yaml b/builtins/core/openimage/open-image_doc.yaml index 32294855a..459d69e2c 100644 --- a/builtins/core/openimage/open-image_doc.yaml +++ b/builtins/core/openimage/open-image_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open-image Title: >- - fs.open.image: `open-image` + fs.open.image CategoryID: commands Summary: >- Renders bitmap image data on your terminal diff --git a/builtins/core/pipe/namedpipe_doc.yaml b/builtins/core/pipe/namedpipe_doc.yaml index 1333ecc7a..d627ce644 100644 --- a/builtins/core/pipe/namedpipe_doc.yaml +++ b/builtins/core/pipe/namedpipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: namedpipe Title: >+ - io.pipe: `` Read Named Pipe + io.pipe (``) CategoryID: commands Summary: >- Reads from a Murex named pipe @@ -52,7 +52,7 @@ - DocumentID: stdin Title: >+ - `` + io.in (``) CategoryID: commands Summary: >- Read the stdin belonging to the parent code block @@ -105,6 +105,7 @@ {{ include "gen/includes/named-pipes.inc.md" }} Synonyms: - "" + - io.in Related: - pipe - namedpipe diff --git a/builtins/core/pipe/pipe_doc.yaml b/builtins/core/pipe/pipe_doc.yaml index 5173e4f81..2bfce3fd4 100644 --- a/builtins/core/pipe/pipe_doc.yaml +++ b/builtins/core/pipe/pipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pipe Title: >+ - io.new.pipe: `pipe` + io.new.pipe CategoryID: commands Summary: >- Manage Murex named pipes diff --git a/builtins/core/pretty/pretty_doc.yaml b/builtins/core/pretty/pretty_doc.yaml index a9ab8f5b6..62be3e82b 100644 --- a/builtins/core/pretty/pretty_doc.yaml +++ b/builtins/core/pretty/pretty_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pretty Title: >+ - struct.json.pretty: `pretty` + struct.json.pretty CategoryID: commands Summary: >- Prettifies JSON to make it human readable diff --git a/builtins/core/processes/bgfg_doc.yaml b/builtins/core/processes/bgfg_doc.yaml index cbbc35827..9ce1ec17c 100644 --- a/builtins/core/processes/bgfg_doc.yaml +++ b/builtins/core/processes/bgfg_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: bg Title: >+ - proc.bg: `bg` + proc.bg CategoryID: commands Summary: >- Run processes in the background @@ -44,7 +44,7 @@ - DocumentID: fg Title: >+ - proc.fg: `fg` + proc.fg CategoryID: commands Summary: >- Sends a background process into the foreground diff --git a/builtins/core/processes/fid-list_doc.yaml b/builtins/core/processes/fid-list_doc.yaml index dc621e9d1..d41ba1643 100644 --- a/builtins/core/processes/fid-list_doc.yaml +++ b/builtins/core/processes/fid-list_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-list Title: >+ - proc.list: `fid-list` + proc.list CategoryID: commands Summary: >- Lists all running functions within the current Murex session diff --git a/builtins/core/processes/kill_doc.yaml b/builtins/core/processes/kill_doc.yaml index 4750562b2..b7912242c 100644 --- a/builtins/core/processes/kill_doc.yaml +++ b/builtins/core/processes/kill_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-kill Title: >+ - proc.kill: `fid-kill` + proc.kill CategoryID: commands Summary: >- Terminate a running Murex function @@ -34,7 +34,7 @@ - DocumentID: fid-killall Title: >+ - proc.kill.all: `fid-killall` + proc.kill.all CategoryID: commands Summary: >- Terminate _all_ running Murex functions @@ -51,7 +51,7 @@ {{ include "gen/includes/fid-kill.inc.md" }} Synonyms: - - fid.killall + - fid-killall - proc.kill.all Related: - fid-list diff --git a/builtins/core/runtime/runtime_doc.yaml b/builtins/core/runtime/runtime_doc.yaml index 634d0cc07..8a22f7162 100644 --- a/builtins/core/runtime/runtime_doc.yaml +++ b/builtins/core/runtime/runtime_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: runtime Title: >+ - shell.runtime: `runtime` + shell.runtime CategoryID: commands Summary: >- Returns runtime information on the internal state of Murex diff --git a/builtins/core/structs/function_doc.yaml b/builtins/core/structs/function_doc.yaml index f3b0eb331..4273fad30 100644 --- a/builtins/core/structs/function_doc.yaml +++ b/builtins/core/structs/function_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: alias Title: >+ - `alias` + shell.alias CategoryID: commands Summary: >- Create an alias for a command @@ -85,6 +85,8 @@ Synonyms: - alias - "!alias" + - shell.alias + - "!shell.alias" Related: - function - private @@ -98,9 +100,11 @@ - fexec - method + + - DocumentID: function Title: >+ - `function` + shell.function CategoryID: commands Summary: >- Define a function block @@ -306,6 +310,8 @@ Synonyms: - function - "!function" + - shell.function + - "!shell.function" Related: - args - alias @@ -323,9 +329,11 @@ - version - break + + - DocumentID: private Title: >+ - `private` + shell.private CategoryID: commands Summary: >- Define a private function block @@ -383,6 +391,8 @@ {{ include "gen/includes/order-of-precedence.inc.md" }} Synonyms: + - private + - shell.private Related: - function - alias @@ -397,9 +407,11 @@ - method - break + + - DocumentID: method Title: >+ - `method` + shell.method CategoryID: commands Summary: >- Define a methods supported data-types @@ -428,6 +440,8 @@ {{ include "lang/types/groups.go" }} ``` Synonyms: + - method + - shell.method Related: - function - alias diff --git a/builtins/core/system/system_doc.yaml b/builtins/core/system/system_doc.yaml index ada0d39fb..141e6181a 100644 --- a/builtins/core/system/system_doc.yaml +++ b/builtins/core/system/system_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: os Title: >+ - sys.os: `os` + sys.os CategoryID: commands Summary: >- Output the auto-detected OS name @@ -78,7 +78,7 @@ - DocumentID: cpuarch Title: >+ - sys.cpu.arch: `cpuarch` + sys.cpu.arch CategoryID: commands Summary: >- Output the hosts CPU architecture @@ -106,7 +106,7 @@ - DocumentID: cpucount Title: >+ - sys.cpu.count: `cpucount` + sys.cpu.count CategoryID: commands Summary: >- Output the number of CPU cores available on your host diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index c035fad28..3cc173ef6 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -7,8 +7,6 @@ func init() { Summary = map[string]string{ "not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "stdin": "Read the stdin belonging to the parent code block", - "alias": "Create an alias for a command", "and": "Returns `true` or `false` depending on whether multiple conditions are met", "args": "Command line flag parser for Murex shell scripting", "break": "Terminate execution of a block within your processes scope", @@ -25,7 +23,6 @@ func init() { "foreach": "Iterate through an array", "formap": "Iterate through a map or other collection of data", "format": "Reformat one data-type into another data-type", - "function": "Define a function block", "get-type": "Returns the data-type of a variable or pipe", "get": "Makes a standard HTTP request and returns the result as a JSON object", "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", @@ -34,13 +31,10 @@ func init() { "ja": "A sophisticated yet simply way to build a JSON array", "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "method": "Define a methods supported data-types", "murex-docs": "Displays the man pages for Murex builtins", - "murex-parser": "Runs the Murex parser against a block of code", "devnull": "null function. Similar to /dev/null", "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", "post": "HTTP POST request with a JSON-parsable return", - "private": "Define a private function block", "rand": "Random field generator", "return": "Exits current function scope", "runmode": "Alter the scheduler's behaviour at higher scoping level", @@ -49,7 +43,6 @@ func init() { "tabulate": "Table transformation tools", "test": "Murex's test framework - define tests, run tests and debug shell scripts", "time": "Returns the execution run time of a command or block", - "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", "true": "Returns a `true` value", "try": "Handles non-zero exits inside a block of code", "tryerr": "Handles errors inside a block of code", @@ -69,24 +62,26 @@ func init() { "f": "Lists or filters file system objects (eg files)", "g": "Glob pattern matching for file system objects (eg `*.txt`)", "lockfile": "Create and manage lock files", - "tmp": "Create a temporary file and write to it", - "open-image": "Renders bitmap image data on your terminal", "open": "Open a file with a preferred handler", + "open-image": "Renders bitmap image data on your terminal", "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "pt": "Pipe telemetry. Writes data-types and bytes written", + "tmp": "Create a temporary file and write to it", + "file-truncate": "Writes stdin to disk - overwriting contents if file already exists", "man-get-flags": "Parses man page files for command line flags", "man-summary": "Outputs a man page summary of a command", "err": "Print a line to the stderr", - "read": "`read` a line of input from the user and store as a variable", + "stdin": "Read the stdin belonging to the parent code block", "pipe": "Manage Murex named pipes", - "tout": "Print a string to the stdout and set it's data-type", "out": "Print a string to the stdout with a trailing new line character", + "tout": "Print a string to the stdout and set it's data-type", "namedpipe": "Reads from a Murex named pipe", + "read": "`read` a line of input from the user and store as a variable", + "pt": "Pipe telemetry. Writes data-types and bytes written", "append": "Add data to the end of an array", "list.case": "Changes the character case of a string or all elements in an array", "mjoin": "Joins a list or array into a single string", "left": "Left substring every item in a list", - "a": "A sophisticated yet simple way to build an array or list", + "a": "A sophisticated yet simple way to build an array or list (mkarray)", "ta": "A sophisticated yet simple way to build an array of a user defined data-type", "prefix": "Prefix a string to every item in a list", "prepend": "Add data to the start of an array", @@ -100,16 +95,20 @@ func init() { "bg": "Run processes in the background", "exitnum": "Output the exit number of the previous process", "fg": "Sends a background process into the foreground", - "fid-killall": "Terminate _all_ running Murex functions", "fid-kill": "Terminate a running Murex function", + "fid-killall": "Terminate _all_ running Murex functions", "fid-list": "Lists all running functions within the current Murex session", + "alias": "Create an alias for a command", "autocomplete": "Set definitions for tab-completion in the command line", "bexists": "Check which builtins exist", "config": "Query or define Murex runtime settings", "debug": "Debugging information", + "function": "Define a function block", "history": "Outputs murex's command history", + "method": "Define a methods supported data-types", "openagent": "Creates a handler function for `open`", "murex-package": "Murex's package manager", + "private": "Define a private function block", "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "runtime": "Returns runtime information on the internal state of Murex", "summary": "Defines a summary help text for a command", @@ -138,8 +137,6 @@ func init() { "select": "Inlining SQL into shell pipelines", "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "commands/stdin": "Read the stdin belonging to the parent code block", - "commands/alias": "Create an alias for a command", "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", "commands/args": "Command line flag parser for Murex shell scripting", "commands/break": "Terminate execution of a block within your processes scope", @@ -156,7 +153,6 @@ func init() { "commands/foreach": "Iterate through an array", "commands/formap": "Iterate through a map or other collection of data", "commands/format": "Reformat one data-type into another data-type", - "commands/function": "Define a function block", "commands/get-type": "Returns the data-type of a variable or pipe", "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", @@ -165,13 +161,10 @@ func init() { "commands/ja": "A sophisticated yet simply way to build a JSON array", "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/method": "Define a methods supported data-types", "commands/murex-docs": "Displays the man pages for Murex builtins", - "commands/murex-parser": "Runs the Murex parser against a block of code", "commands/devnull": "null function. Similar to /dev/null", "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", "commands/post": "HTTP POST request with a JSON-parsable return", - "commands/private": "Define a private function block", "commands/rand": "Random field generator", "commands/return": "Exits current function scope", "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", @@ -180,7 +173,6 @@ func init() { "commands/tabulate": "Table transformation tools", "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", "commands/time": "Returns the execution run time of a command or block", - "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", "commands/true": "Returns a `true` value", "commands/try": "Handles non-zero exits inside a block of code", "commands/tryerr": "Handles errors inside a block of code", @@ -200,24 +192,26 @@ func init() { "commands/f": "Lists or filters file system objects (eg files)", "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", "commands/lockfile": "Create and manage lock files", - "commands/tmp": "Create a temporary file and write to it", - "commands/open-image": "Renders bitmap image data on your terminal", "commands/open": "Open a file with a preferred handler", + "commands/open-image": "Renders bitmap image data on your terminal", "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "commands/pt": "Pipe telemetry. Writes data-types and bytes written", + "commands/tmp": "Create a temporary file and write to it", + "commands/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", "commands/man-get-flags": "Parses man page files for command line flags", "commands/man-summary": "Outputs a man page summary of a command", "commands/err": "Print a line to the stderr", - "commands/read": "`read` a line of input from the user and store as a variable", + "commands/stdin": "Read the stdin belonging to the parent code block", "commands/pipe": "Manage Murex named pipes", - "commands/tout": "Print a string to the stdout and set it's data-type", "commands/out": "Print a string to the stdout with a trailing new line character", + "commands/tout": "Print a string to the stdout and set it's data-type", "commands/namedpipe": "Reads from a Murex named pipe", + "commands/read": "`read` a line of input from the user and store as a variable", + "commands/pt": "Pipe telemetry. Writes data-types and bytes written", "commands/append": "Add data to the end of an array", "commands/list.case": "Changes the character case of a string or all elements in an array", "commands/mjoin": "Joins a list or array into a single string", "commands/left": "Left substring every item in a list", - "commands/a": "A sophisticated yet simple way to build an array or list", + "commands/a": "A sophisticated yet simple way to build an array or list (mkarray)", "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", "commands/prefix": "Prefix a string to every item in a list", "commands/prepend": "Add data to the start of an array", @@ -231,16 +225,20 @@ func init() { "commands/bg": "Run processes in the background", "commands/exitnum": "Output the exit number of the previous process", "commands/fg": "Sends a background process into the foreground", - "commands/fid-killall": "Terminate _all_ running Murex functions", "commands/fid-kill": "Terminate a running Murex function", + "commands/fid-killall": "Terminate _all_ running Murex functions", "commands/fid-list": "Lists all running functions within the current Murex session", + "commands/alias": "Create an alias for a command", "commands/autocomplete": "Set definitions for tab-completion in the command line", "commands/bexists": "Check which builtins exist", "commands/config": "Query or define Murex runtime settings", "commands/debug": "Debugging information", + "commands/function": "Define a function block", "commands/history": "Outputs murex's command history", + "commands/method": "Define a methods supported data-types", "commands/openagent": "Creates a handler function for `open`", "commands/murex-package": "Murex's package manager", + "commands/private": "Define a private function block", "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "commands/runtime": "Returns runtime information on the internal state of Murex", "commands/summary": "Defines a summary help text for a command", @@ -418,9 +416,6 @@ func init() { "!": "not-func", "not": "not-func", - "": "stdin", - "alias": "alias", - "!alias": "alias", "and": "and", "!and": "and", "args": "args", @@ -440,8 +435,6 @@ func init() { "foreach": "foreach", "formap": "formap", "format": "format", - "function": "function", - "!function": "function", "get-type": "get-type", "get": "get", "getfile": "getfile", @@ -451,15 +444,12 @@ func init() { "ja": "ja", "key-code": "key-code", "let": "let", - "method": "method", "murex-docs": "murex-docs", "help": "murex-docs", - "murex-parser": "murex-parser", "null": "devnull", "or": "or", "!or": "or", "post": "post", - "private": "private", "rand": "rand", "return": "return", "runmode": "runmode", @@ -469,7 +459,6 @@ func init() { "test": "test", "!test": "test", "time": "time", - "tread": "tread", "true": "true", "try": "try", "tryerr": "tryerr", @@ -513,39 +502,45 @@ func init() { "!fs.glob": "g", "lockfile": "lockfile", "fs.lockfile": "lockfile", - "tmp": "tmp", - "fs.new.tmpfile": "tmp", - "open-image": "open-image", - "fs.open.image": "open-image", "open": "open", "fs.open": "open", + "open-image": "open-image", + "fs.open.image": "open-image", "rx": "rx", "!rx": "rx", "fs.regex": "rx", "!fs.regex": "rx", - "pt": "pt", - "fs.status": "pt", + "tmp": "tmp", + "fs.new.tmpfile": "tmp", + ">": "file-truncate", + "fs.truncate": "file-truncate", + "|>": "file-truncate", + "fwrite": "file-truncate", "man-get-flags": "man-get-flags", "help.man.flags": "man-get-flags", "man-summary": "man-summary", "help.man.summary": "man-summary", "err": "err", "io.err": "err", - "read": "read", - "io.input": "read", + "": "stdin", + "io.in": "stdin", "pipe": "pipe", "!pipe": "pipe", "io.new.pipe": "pipe", "!io.new.pipe": "pipe", - "tout": "tout", - "io.out.type": "tout", "out": "out", "io.out": "out", "echo": "out", + "tout": "tout", + "io.out.type": "tout", "(murex named pipe)": "namedpipe", "<>": "namedpipe", "read-named-pipe": "namedpipe", "io.pipe": "namedpipe", + "read": "read", + "io.input": "read", + "pt": "pt", + "fs.status": "pt", "append": "append", "list.append": "append", "list.case": "list.case", @@ -586,14 +581,18 @@ func init() { "proc.exitnum": "exitnum", "fg": "fg", "proc.fg": "fg", - "fid.killall": "fid-killall", - "proc.kill.all": "fid-killall", "fid-kill": "fid-kill", "proc.kill": "fid-kill", + "fid-killall": "fid-killall", + "proc.kill.all": "fid-killall", "fid-list": "fid-list", "jobs": "fid-list", "proc.list": "fid-list", "proc.jobs": "fid-list", + "alias": "alias", + "!alias": "alias", + "shell.alias": "alias", + "!shell.alias": "alias", "autocomplete": "autocomplete", "shell.autocomplete": "autocomplete", "bexists": "bexists", @@ -603,14 +602,22 @@ func init() { "!shell.config": "config", "debug": "debug", "shell.debug": "debug", + "function": "function", + "!function": "function", + "shell.function": "function", + "!shell.function": "function", "history": "history", "shell.history": "history", + "method": "method", + "shell.method": "method", "openagent": "openagent", "!openagent": "openagent", "shell.open": "openagent", "!shell.open": "openagent", - "murex.package": "murex-package", + "murex-package": "murex-package", "shell.packages": "murex-package", + "private": "private", + "shell.private": "private", "murex-update-exe-list": "murex-update-exe-list", "shell.rescan.path": "murex-update-exe-list", "runtime": "runtime", @@ -715,9 +722,6 @@ func init() { "commands/!": "commands/not-func", "commands/not": "commands/not-func", - "commands/": "commands/stdin", - "commands/alias": "commands/alias", - "commands/!alias": "commands/alias", "commands/and": "commands/and", "commands/!and": "commands/and", "commands/args": "commands/args", @@ -737,8 +741,6 @@ func init() { "commands/foreach": "commands/foreach", "commands/formap": "commands/formap", "commands/format": "commands/format", - "commands/function": "commands/function", - "commands/!function": "commands/function", "commands/get-type": "commands/get-type", "commands/get": "commands/get", "commands/getfile": "commands/getfile", @@ -748,15 +750,12 @@ func init() { "commands/ja": "commands/ja", "commands/key-code": "commands/key-code", "commands/let": "commands/let", - "commands/method": "commands/method", "commands/murex-docs": "commands/murex-docs", "commands/help": "commands/murex-docs", - "commands/murex-parser": "commands/murex-parser", "commands/null": "commands/devnull", "commands/or": "commands/or", "commands/!or": "commands/or", "commands/post": "commands/post", - "commands/private": "commands/private", "commands/rand": "commands/rand", "commands/return": "commands/return", "commands/runmode": "commands/runmode", @@ -766,7 +765,6 @@ func init() { "commands/test": "commands/test", "commands/!test": "commands/test", "commands/time": "commands/time", - "commands/tread": "commands/tread", "commands/true": "commands/true", "commands/try": "commands/try", "commands/tryerr": "commands/tryerr", @@ -810,39 +808,45 @@ func init() { "commands/!fs.glob": "commands/g", "commands/lockfile": "commands/lockfile", "commands/fs.lockfile": "commands/lockfile", - "commands/tmp": "commands/tmp", - "commands/fs.new.tmpfile": "commands/tmp", - "commands/open-image": "commands/open-image", - "commands/fs.open.image": "commands/open-image", "commands/open": "commands/open", "commands/fs.open": "commands/open", + "commands/open-image": "commands/open-image", + "commands/fs.open.image": "commands/open-image", "commands/rx": "commands/rx", "commands/!rx": "commands/rx", "commands/fs.regex": "commands/rx", "commands/!fs.regex": "commands/rx", - "commands/pt": "commands/pt", - "commands/fs.status": "commands/pt", + "commands/tmp": "commands/tmp", + "commands/fs.new.tmpfile": "commands/tmp", + "commands/>": "commands/file-truncate", + "commands/fs.truncate": "commands/file-truncate", + "commands/|>": "commands/file-truncate", + "commands/fwrite": "commands/file-truncate", "commands/man-get-flags": "commands/man-get-flags", "commands/help.man.flags": "commands/man-get-flags", "commands/man-summary": "commands/man-summary", "commands/help.man.summary": "commands/man-summary", "commands/err": "commands/err", "commands/io.err": "commands/err", - "commands/read": "commands/read", - "commands/io.input": "commands/read", + "commands/": "commands/stdin", + "commands/io.in": "commands/stdin", "commands/pipe": "commands/pipe", "commands/!pipe": "commands/pipe", "commands/io.new.pipe": "commands/pipe", "commands/!io.new.pipe": "commands/pipe", - "commands/tout": "commands/tout", - "commands/io.out.type": "commands/tout", "commands/out": "commands/out", "commands/io.out": "commands/out", "commands/echo": "commands/out", + "commands/tout": "commands/tout", + "commands/io.out.type": "commands/tout", "commands/(murex named pipe)": "commands/namedpipe", "commands/<>": "commands/namedpipe", "commands/read-named-pipe": "commands/namedpipe", "commands/io.pipe": "commands/namedpipe", + "commands/read": "commands/read", + "commands/io.input": "commands/read", + "commands/pt": "commands/pt", + "commands/fs.status": "commands/pt", "commands/append": "commands/append", "commands/list.append": "commands/append", "commands/list.case": "commands/list.case", @@ -883,14 +887,18 @@ func init() { "commands/proc.exitnum": "commands/exitnum", "commands/fg": "commands/fg", "commands/proc.fg": "commands/fg", - "commands/fid.killall": "commands/fid-killall", - "commands/proc.kill.all": "commands/fid-killall", "commands/fid-kill": "commands/fid-kill", "commands/proc.kill": "commands/fid-kill", + "commands/fid-killall": "commands/fid-killall", + "commands/proc.kill.all": "commands/fid-killall", "commands/fid-list": "commands/fid-list", "commands/jobs": "commands/fid-list", "commands/proc.list": "commands/fid-list", "commands/proc.jobs": "commands/fid-list", + "commands/alias": "commands/alias", + "commands/!alias": "commands/alias", + "commands/shell.alias": "commands/alias", + "commands/!shell.alias": "commands/alias", "commands/autocomplete": "commands/autocomplete", "commands/shell.autocomplete": "commands/autocomplete", "commands/bexists": "commands/bexists", @@ -900,14 +908,22 @@ func init() { "commands/!shell.config": "commands/config", "commands/debug": "commands/debug", "commands/shell.debug": "commands/debug", + "commands/function": "commands/function", + "commands/!function": "commands/function", + "commands/shell.function": "commands/function", + "commands/!shell.function": "commands/function", "commands/history": "commands/history", "commands/shell.history": "commands/history", + "commands/method": "commands/method", + "commands/shell.method": "commands/method", "commands/openagent": "commands/openagent", "commands/!openagent": "commands/openagent", "commands/shell.open": "commands/openagent", "commands/!shell.open": "commands/openagent", - "commands/murex.package": "commands/murex-package", + "commands/murex-package": "commands/murex-package", "commands/shell.packages": "commands/murex-package", + "commands/private": "commands/private", + "commands/shell.private": "commands/private", "commands/murex-update-exe-list": "commands/murex-update-exe-list", "commands/shell.rescan.path": "commands/murex-update-exe-list", "commands/runtime": "commands/runtime", diff --git a/docs/blog/reading_lists.md b/docs/blog/reading_lists.md index 948c69e2b..95e766e0c 100644 --- a/docs/blog/reading_lists.md +++ b/docs/blog/reading_lists.md @@ -151,10 +151,10 @@ Published: 22.04.2023 at 11:43 Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray)
diff --git a/docs/changelog/v2.0.md b/docs/changelog/v2.0.md index a69fcda6d..757a4da04 100644 --- a/docs/changelog/v2.0.md +++ b/docs/changelog/v2.0.md @@ -37,13 +37,13 @@ Published: 17.04.2021 at 12:49 An introduction to Murex modules and packages * [Spellcheck](../integrations/spellcheck.md): How to enable inline spellchecking -* [fs.open.image: `open-image`](../commands/open-image.md): - Renders bitmap image data on your terminal -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [shell.config: `config`](../commands/config.md): +* [fs.open.image](../commands/open-image.md): + Renders bitmap image data on your terminal +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager
diff --git a/docs/changelog/v2.1.md b/docs/changelog/v2.1.md index 9d8d55fd3..45ddd63bd 100644 --- a/docs/changelog/v2.1.md +++ b/docs/changelog/v2.1.md @@ -87,12 +87,12 @@ Published: 30.04.2021 at 10:00 Iterate through an array * [`jsonl`](../types/jsonl.md): JSON Lines -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.list: `jobs`](../commands/fid-list.md): - Lists all running functions within the current Murex session * [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines diff --git a/docs/changelog/v2.10.md b/docs/changelog/v2.10.md index 3801f374a..d0c9dc344 100644 --- a/docs/changelog/v2.10.md +++ b/docs/changelog/v2.10.md @@ -70,13 +70,13 @@ Published: 01.08.2022 at 20:10 Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [fs.files: `f`](../commands/f.md): +* [fs.files (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.regex: `rx`](../commands/rx.md): +* [fs.regex (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v2.11.md b/docs/changelog/v2.11.md index e27eec479..a75725658 100644 --- a/docs/changelog/v2.11.md +++ b/docs/changelog/v2.11.md @@ -54,17 +54,17 @@ Published: 12.09.2022 at 08:10 * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`alias`](../commands/alias.md): - Create an alias for a command * [`cd`](../commands/cd.md): Change (working) directory * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [struct.keys: `struct-keys`](../commands/struct-keys.md): +* [struct.keys](../commands/struct-keys.md): Outputs all the keys in a structure as a file path * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/changelog/v2.2.md b/docs/changelog/v2.2.md index 06ebec99c..115ddaa40 100644 --- a/docs/changelog/v2.2.md +++ b/docs/changelog/v2.2.md @@ -64,7 +64,7 @@ Published: 21.06.2021 at 21:51 * [`*` (generic)](../types/generic.md): generic (primitive) -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground
diff --git a/docs/changelog/v2.3.md b/docs/changelog/v2.3.md index d3befbe7f..a9dc28186 100644 --- a/docs/changelog/v2.3.md +++ b/docs/changelog/v2.3.md @@ -82,11 +82,11 @@ Published: 26.09.2021 at 11:33 * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`method`](../commands/method.md): - Define a methods supported data-types * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.method](../commands/method.md): + Define a methods supported data-types +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/changelog/v2.4.md b/docs/changelog/v2.4.md index 3d276ddd4..296a26a2b 100644 --- a/docs/changelog/v2.4.md +++ b/docs/changelog/v2.4.md @@ -106,19 +106,19 @@ Published: 09.12.2021 at 08:00 A breakdown of the different files loaded on start up * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/docs/changelog/v2.5.md b/docs/changelog/v2.5.md index 4609d60c9..ec31483b9 100644 --- a/docs/changelog/v2.5.md +++ b/docs/changelog/v2.5.md @@ -60,17 +60,17 @@ Published: 12.02.2022 at 16:16 Overview of what a "pipeline" is * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array * [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines diff --git a/docs/changelog/v2.6.md b/docs/changelog/v2.6.md index 99b00b389..41745ad97 100644 --- a/docs/changelog/v2.6.md +++ b/docs/changelog/v2.6.md @@ -50,9 +50,9 @@ Published: 26.02.2022 at 18:33 * [`while`](../commands/while.md): Loop until condition false -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index 937da98a4..5a8a587df 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -84,14 +84,14 @@ Published: 15.05.2022 at 22:49 Continues next operation if previous operation passes * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.input: `read`](../commands/read.md): +* [io.read](../commands/read.md): `read` a line of input from the user and store as a variable -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` diff --git a/docs/changelog/v2.8.md b/docs/changelog/v2.8.md index 70b75ae21..67dc8d26e 100644 --- a/docs/changelog/v2.8.md +++ b/docs/changelog/v2.8.md @@ -40,14 +40,14 @@ Published: 23.05.2022 at 22:23 Special variables reserved by Murex * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [`function`](../commands/function.md): - Define a function block * [`jsonc`](../types/jsonc.md): Concatenated JSON * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): + Define a function block
diff --git a/docs/changelog/v2.9.md b/docs/changelog/v2.9.md index 0ae79f56d..0eaffe1aa 100644 --- a/docs/changelog/v2.9.md +++ b/docs/changelog/v2.9.md @@ -68,24 +68,24 @@ Published: 15.07.2022 at 20:35 Writes stdin to disk - appending contents if file already exists * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`function`](../commands/function.md): - Define a function block * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`private`](../commands/private.md): - Define a private function block * [`runmode`](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/changelog/v3.0.md b/docs/changelog/v3.0.md index 52fe87d9b..8ba5f848a 100644 --- a/docs/changelog/v3.0.md +++ b/docs/changelog/v3.0.md @@ -116,15 +116,15 @@ Published: 31.12.2022 at 08:10 Displays the man pages for Murex builtins * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/changelog/v4.0.md b/docs/changelog/v4.0.md index e42c5b7af..36508467d 100644 --- a/docs/changelog/v4.0.md +++ b/docs/changelog/v4.0.md @@ -82,15 +82,15 @@ Published: 26.03.2023 at 17:50 Quickly generate arrays * [`%{}` Object Builder](../parser/create-object.md): Quickly generate objects (dictionaries / maps) -* [`function`](../commands/function.md): - Define a function block * [`path`](../types/path.md): Structured object for working with file and directory paths * [`paths`](../types/paths.md): Structured array for working with `$PATH` style data * [`string` (stringing)](../types/str.md): string (primitive) -* [struct.count: `count`](../commands/count.md): +* [shell.function](../commands/function.md): + Define a function block +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/changelog/v4.2.md b/docs/changelog/v4.2.md index ceea51bd8..5db4fbd56 100644 --- a/docs/changelog/v4.2.md +++ b/docs/changelog/v4.2.md @@ -72,24 +72,24 @@ Published: 19.06.2023 at 23:15 What's different about Murex's interactive shell? * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`alias`](../commands/alias.md): - Create an alias for a command * [`foreach`](../commands/foreach.md): Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`method`](../commands/method.md): - Define a methods supported data-types * [`while`](../commands/while.md): Loop until condition false -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [shell.config: `config`](../commands/config.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.method](../commands/method.md): + Define a methods supported data-types
diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index 01dcd0939..01f0ff76f 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -32,9 +32,9 @@ Published: 02.07.2023 at 09:55 Event driven programming for shell scripts * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/changelog/v4.4.md b/docs/changelog/v4.4.md index a585767e6..19ed2a5ec 100644 --- a/docs/changelog/v4.4.md +++ b/docs/changelog/v4.4.md @@ -142,28 +142,28 @@ Published: 27.07.2023 at 23:12 Event driven programming for shell scripts * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`function`](../commands/function.md): - Define a function block * [`int`](../types/int.md): Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion -* [`private`](../commands/private.md): - Define a private function block * [`return`](../commands/return.md): Exits current function scope * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): +* [help.man.flags](../commands/man-get-flags.md): Parses man page files for command line flags * [num.round: `round`](../commands/round.md): Round a number by a user defined precision -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/changelog/v5.0.md b/docs/changelog/v5.0.md index 3d788d2ee..0ddbfa6b6 100644 --- a/docs/changelog/v5.0.md +++ b/docs/changelog/v5.0.md @@ -97,8 +97,6 @@ Published: 07.09.2023 at 00:12 Array of the command name and parameters passed to the current shell * [`SELF` (json)](../variables/self.md): Meta information about the running scope. -* [`alias`](../commands/alias.md): - Create an alias for a command * [`csv`](../types/csv.md): CSV files (and other character delimited tables) * [`event`](../commands/event.md): @@ -113,11 +111,13 @@ Published: 07.09.2023 at 00:12 Sends a signal RPC * [`which`](../commands/which.md): Locate command origin -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager
diff --git a/docs/changelog/v5.1.md b/docs/changelog/v5.1.md index 5ffeb3f30..b0a5aa00d 100644 --- a/docs/changelog/v5.1.md +++ b/docs/changelog/v5.1.md @@ -48,7 +48,7 @@ Published: 09.10.2023 at 22:13 ## See Also -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information
diff --git a/docs/changelog/v5.2.md b/docs/changelog/v5.2.md index 57d4d8662..045e27f07 100644 --- a/docs/changelog/v5.2.md +++ b/docs/changelog/v5.2.md @@ -88,13 +88,13 @@ Published: 18.11.2023 at 20:59 A list of all the terminal hotkeys and their uses * [`[{ Lambda }]`](../parser/lambda.md): Iterate through structured data -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/changelog/v5.3.md b/docs/changelog/v5.3.md index 567251793..4e605ded5 100644 --- a/docs/changelog/v5.3.md +++ b/docs/changelog/v5.3.md @@ -93,11 +93,11 @@ Published: 02.01.2024 at 15:45 Guide to contributing to Murex * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/changelog/v6.0.md b/docs/changelog/v6.0.md index f67487df9..dc0037f80 100644 --- a/docs/changelog/v6.0.md +++ b/docs/changelog/v6.0.md @@ -48,11 +48,11 @@ Published: 17.02.2024 at 20:47 Guide to contributing to Murex * [`is-null`](../commands/is-null.md): Checks if a variable is null or undefined -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index dfb7b5120..31b070796 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -166,15 +166,15 @@ Published: 17.06.2024 at 22:54 Events triggered by changes in state of the interactive shell * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [help.man.summary: `man-summary`](../commands/man-summary.md): +* [help.man.summary](../commands/man-summary.md): Outputs a man page summary of a command -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 8706d5779..310f3f161 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -94,7 +94,7 @@ Published: 19.07.2024 at 08:54 Expressions: mathematical, string comparisons, logical operators * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/commands/2darray.md b/docs/commands/2darray.md index c5c6999e0..cf064ea22 100644 --- a/docs/commands/2darray.md +++ b/docs/commands/2darray.md @@ -1,4 +1,4 @@ -# struct.new.2darray: `2darray` +# struct.new.2darray > Create a 2D JSON array from multiple input sources @@ -107,21 +107,21 @@ A sophisticated yet simply way to build a JSON array * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/README.md b/docs/commands/README.md index 57d15c222..66efac38d 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -38,10 +38,6 @@ murex-docs trypipe * [`!` (not)](../commands/not-func.md): Reads the stdin and exit number from previous process and not's it's condition -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [`alias`](../commands/alias.md): - Create an alias for a command * [`and`](../commands/and.md): Returns `true` or `false` depending on whether multiple conditions are met * [`args` ](../commands/args.md): @@ -74,8 +70,6 @@ murex-docs trypipe Iterate through a map or other collection of data * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`function`](../commands/function.md): - Define a function block * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe * [`get`](../commands/get.md): @@ -92,20 +86,14 @@ murex-docs trypipe Returns character sequences for any key pressed (ie sent from the terminal) * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-parser` ](../commands/murex-parser.md): - Runs the Murex parser against a block of code * [`null`](../commands/devnull.md): null function. Similar to /dev/null * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`private`](../commands/private.md): - Define a private function block * [`rand`](../commands/rand.md): Random field generator * [`return`](../commands/return.md): @@ -122,8 +110,6 @@ murex-docs trypipe Murex's test framework - define tests, run tests and debug shell scripts * [`time`](../commands/time.md): Returns the execution run time of a command or block -* [`tread`](../commands/tread.md): - `read` a line of input from the user and store as a user defined *typed* variable (deprecated) * [`true`](../commands/true.md): Returns a `true` value * [`try`](../commands/try.md): @@ -142,139 +128,151 @@ murex-docs trypipe Locate command origin * [`while`](../commands/while.md): Loop until condition false -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.files: `f`](../commands/f.md): +* [fs.files (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.lockfile: `lockfile`](../commands/lockfile.md): +* [fs.lockfile](../commands/lockfile.md): Create and manage lock files -* [fs.new.tmpfile: `tmp`](../commands/tmp.md): - Create a temporary file and write to it -* [fs.open.image: `open-image`](../commands/open-image.md): - Renders bitmap image data on your terminal -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [fs.regex: `rx`](../commands/rx.md): +* [fs.open.image](../commands/open-image.md): + Renders bitmap image data on your terminal +* [fs.regex (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [fs.status: `pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): +* [fs.tmpfile (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [fs.truncate (`>`)](../commands/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [help.man.flags](../commands/man-get-flags.md): Parses man page files for command line flags -* [help.man.summary: `man-summary`](../commands/man-summary.md): +* [help.man.summary](../commands/man-summary.md): Outputs a man page summary of a command -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.input: `read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.append: `append`](../commands/append.md): +* [io.read](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [list.append](../commands/append.md): Add data to the end of an array -* [list.case: `list.case` ](../commands/list.case.md): +* [list.case](../commands/list.case.md): Changes the character case of a string or all elements in an array -* [list.join: `mjoin` ](../commands/mjoin.md): +* [list.join](../commands/mjoin.md): Joins a list or array into a single string -* [list.left: `left`](../commands/left.md): +* [list.left](../commands/left.md): Left substring every item in a list -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.right: `right`](../commands/right.md): +* [list.right](../commands/right.md): Right substring every item in a list -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list * [num.round: `round`](../commands/round.md): Round a number by a user defined precision -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.exitnum: `exitnum`](../commands/exitnum.md): +* [proc.exitnum](../commands/exitnum.md): Output the exit number of the previous process -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.builtins.exist: `bexists`](../commands/bexists.md): +* [shell.builtins.exist](../commands/bexists.md): Check which builtins exist -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information -* [shell.history: `history`](../commands/history.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.history](../commands/history.md): Outputs murex's command history +* [shell.method](../commands/method.md): + Define a methods supported data-types * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.private](../commands/private.md): + Define a private function block +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.summary: `summary` ](../commands/summary.md): +* [shell.summary](../commands/summary.md): Defines a summary help text for a command -* [shell.version: `version`](../commands/version.md): +* [shell.version](../commands/version.md): Get Murex version * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable -* [struct.keys: `struct-keys`](../commands/struct-keys.md): +* [struct.keys](../commands/struct-keys.md): Outputs all the keys in a structure as a file path -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources -* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count: `cpucount`](../commands/cpucount.md): +* [sys.cpu.count](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os: `os`](../commands/os.md): +* [sys.os](../commands/os.md): Output the auto-detected OS name -* [table.new.heading: `addheading` ](../commands/addheading.md): +* [table.add.heading](../commands/addheading.md): Adds headings to a table * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/commands/a.md b/docs/commands/a.md index 91096510b..afed1a32f 100644 --- a/docs/commands/a.md +++ b/docs/commands/a.md @@ -1,11 +1,11 @@ -# list.new.str: `a` (mkarray) +# list.new.str (`a`) -> A sophisticated yet simple way to build an array or list +> A sophisticated yet simple way to build an array or list (mkarray) ## Description -Pronounced "make array", like `mkdir` (etc), Murex has a pretty sophisticated -builtin for generating arrays. Think like bash's `{1..9}` syntax: +_mkarray_, pronounced "make array" like `mkdir` (etc), is Murex's sophisticated +syntax for generating arrays. Think like bash's `{1..9}` syntax: ``` a [1..9] @@ -14,6 +14,8 @@ a [1..9] Except Murex also supports other sets of ranges like dates, days of the week, and alternative number bases. +This builtin streams arrays as a list of strings (`str`). + ## Usage ``` @@ -182,9 +184,9 @@ arrays. For more details on these please refer to the documents for each format string (primitive) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/addheading.md b/docs/commands/addheading.md index 2d61f74ac..fab8f5d2a 100644 --- a/docs/commands/addheading.md +++ b/docs/commands/addheading.md @@ -1,4 +1,4 @@ -# table.new.heading: `addheading` +# table.add.heading > Adds headings to a table @@ -38,21 +38,21 @@ prepend to tables. Alters the data-type of the previous function without altering its output * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/alias.md b/docs/commands/alias.md index a1f7feb4f..98e0ebfdb 100644 --- a/docs/commands/alias.md +++ b/docs/commands/alias.md @@ -1,4 +1,4 @@ -# `alias` +# shell.alias > Create an alias for a command @@ -119,26 +119,28 @@ You can override this order of precedence via the `fexec` and `exec` builtins. * `alias` * `!alias` +* `shell.alias` +* `!shell.alias` ## See Also -* [`function`](../commands/function.md): - Define a function block * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types -* [`private`](../commands/private.md): - Define a private function block -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) +* [shell.function](../commands/function.md): + Define a function block +* [shell.method](../commands/method.md): + Define a methods supported data-types +* [shell.private](../commands/private.md): + Define a private function block * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value * [var.global: `global`](../commands/global.md): diff --git a/docs/commands/alter.md b/docs/commands/alter.md index d3e94ab69..2fb54b7f7 100644 --- a/docs/commands/alter.md +++ b/docs/commands/alter.md @@ -1,4 +1,4 @@ -# struct.alter: `alter` +# struct.alter > Change a value within a structured data-type and pass that change along the pipeline without altering the original source input @@ -196,13 +196,13 @@ Marshallers are enabled at compile time from the `builtins/data-types` directory Alters the data-type of the previous function without altering its output * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/append.md b/docs/commands/append.md index 52e21cc80..9a349cda3 100644 --- a/docs/commands/append.md +++ b/docs/commands/append.md @@ -1,4 +1,4 @@ -# list.append: `append` +# list.append > Add data to the end of an array @@ -55,21 +55,21 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco Alters the data-type of the previous function without altering its output * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [table.new.heading: `addheading` ](../commands/addheading.md): +* [table.add.heading](../commands/addheading.md): Adds headings to a table
diff --git a/docs/commands/autocomplete.md b/docs/commands/autocomplete.md index 60c564c7d..9f4e63587 100644 --- a/docs/commands/autocomplete.md +++ b/docs/commands/autocomplete.md @@ -1,4 +1,4 @@ -# shell.autocomplete: `autocomplete` +# shell.autocomplete > Set definitions for tab-completion in the command line @@ -612,25 +612,25 @@ flags. ## See Also -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table -* [`alias`](../commands/alias.md): - Create an alias for a command -* [`function`](../commands/function.md): - Define a function block * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe -* [`private`](../commands/private.md): - Define a private function block * [`switch`](../commands/switch.md): Blocks of cascading conditionals +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.config: `config`](../commands/config.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.summary: `summary` ](../commands/summary.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block +* [shell.summary](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/bexists.md b/docs/commands/bexists.md index c90350c5e..eeb5c4bfe 100644 --- a/docs/commands/bexists.md +++ b/docs/commands/bexists.md @@ -1,4 +1,4 @@ -# shell.builtins.exist: `bexists` +# shell.builtins.exist > Check which builtins exist @@ -47,9 +47,9 @@ that reason alone it has been spared from the axe. * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/bg.md b/docs/commands/bg.md index b3c396cf4..46792ea62 100644 --- a/docs/commands/bg.md +++ b/docs/commands/bg.md @@ -1,4 +1,4 @@ -# proc.bg: `bg` +# proc.bg > Run processes in the background @@ -43,15 +43,15 @@ cross platform while `bg int` currently does not work on Windows nor Plan 9. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.fg: `fg`](../commands/fg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/break.md b/docs/commands/break.md index c4a24f80c..4a8d1abeb 100644 --- a/docs/commands/break.md +++ b/docs/commands/break.md @@ -106,16 +106,16 @@ Error in `break` (7,17): no block found named `bar` within the scope of `foo` Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`function`](../commands/function.md): - Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`private`](../commands/private.md): - Define a private function block * [`return`](../commands/return.md): Exits current function scope -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/commands/cast.md b/docs/commands/cast.md index d174b8cd9..623583589 100644 --- a/docs/commands/cast.md +++ b/docs/commands/cast.md @@ -70,10 +70,10 @@ instead. Quickly generate objects (dictionaries / maps) * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/commands/cd.md b/docs/commands/cd.md index 29f086851..0c69a9815 100644 --- a/docs/commands/cd.md +++ b/docs/commands/cd.md @@ -81,7 +81,7 @@ config set shell auto-cd true * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block
diff --git a/docs/commands/config.md b/docs/commands/config.md index e8f33235b..6aee2434d 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -1,4 +1,4 @@ -# shell.config: `config` +# shell.config > Query or define Murex runtime settings @@ -245,23 +245,23 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Outputs an element from a nested structure * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block * [`get`](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/commands/continue.md b/docs/commands/continue.md index b5a09f58c..7ad6e55cc 100644 --- a/docs/commands/continue.md +++ b/docs/commands/continue.md @@ -84,16 +84,16 @@ Error in `continue` (7,17): no block found named `bar` within the scope of `foo` Iterate through an array * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`function`](../commands/function.md): - Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`private`](../commands/private.md): - Define a private function block * [`return`](../commands/return.md): Exits current function scope -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/commands/count.md b/docs/commands/count.md index 3049e18a2..2b7dfdad7 100644 --- a/docs/commands/count.md +++ b/docs/commands/count.md @@ -1,4 +1,4 @@ -# struct.count: `count` +# struct.count > Count items in a map, list or array @@ -150,25 +150,25 @@ unique count should be one less than the total count: Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [io.out.type: `tout`](../commands/tout.md): +* [io.out.type (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/cpuarch.md b/docs/commands/cpuarch.md index 7ea49a8e7..b9c484ae7 100644 --- a/docs/commands/cpuarch.md +++ b/docs/commands/cpuarch.md @@ -1,4 +1,4 @@ -# sys.cpu.arch: `cpuarch` +# sys.cpu.arch > Output the hosts CPU architecture @@ -27,9 +27,9 @@ amd64 ## See Also -* [sys.cpu.count: `cpucount`](../commands/cpucount.md): +* [sys.cpu.count](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os: `os`](../commands/os.md): +* [sys.os](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/cpucount.md b/docs/commands/cpucount.md index 1c6a80865..13f1d7cae 100644 --- a/docs/commands/cpucount.md +++ b/docs/commands/cpucount.md @@ -1,4 +1,4 @@ -# sys.cpu.count: `cpucount` +# sys.cpu.count > Output the number of CPU cores available on your host @@ -27,9 +27,9 @@ cpucount -> ## See Also -* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.os: `os`](../commands/os.md): +* [sys.os](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/datetime.md b/docs/commands/datetime.md index c0d5bda92..baf57d41e 100644 --- a/docs/commands/datetime.md +++ b/docs/commands/datetime.md @@ -91,8 +91,8 @@ required. * [`[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray)
diff --git a/docs/commands/debug.md b/docs/commands/debug.md index e717c70e5..d3a2c3b20 100644 --- a/docs/commands/debug.md +++ b/docs/commands/debug.md @@ -1,4 +1,4 @@ -# shell.debug: `debug` +# shell.debug > Debugging information @@ -196,7 +196,7 @@ debug panic * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/err.md b/docs/commands/err.md index db4084432..afecc5f24 100644 --- a/docs/commands/err.md +++ b/docs/commands/err.md @@ -1,4 +1,4 @@ -# io.err: `err` +# io.err > Print a line to the stderr @@ -65,21 +65,21 @@ a new Murex named pipe. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [fs.status: `pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [proc.bg: `bg`](../commands/bg.md): +* [io.status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [proc.bg](../commands/bg.md): Run processes in the background -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable
diff --git a/docs/commands/escape.md b/docs/commands/escape.md index b13d37dca..f5db4bb8c 100644 --- a/docs/commands/escape.md +++ b/docs/commands/escape.md @@ -1,4 +1,4 @@ -# escape.quote: `escape` +# escape.quote > Escape or unescape input @@ -49,11 +49,11 @@ escape string to escape -> ## See Also -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/commands/esccli.md b/docs/commands/esccli.md index 5c2b49910..867ca70d0 100644 --- a/docs/commands/esccli.md +++ b/docs/commands/esccli.md @@ -1,4 +1,4 @@ -# escape.cli: `esccli` +# escape.cli > Escapes an array so output is valid shell code @@ -51,16 +51,16 @@ out foo\$b\@r * [`[ Index ]`](../parser/item-index.md): Outputs an element from an array, map or table -* [`alias`](../commands/alias.md): - Create an alias for a command -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [shell.alias](../commands/alias.md): + Create an alias for a command
diff --git a/docs/commands/eschtml.md b/docs/commands/eschtml.md index 7f087b31b..fdf7f31de 100644 --- a/docs/commands/eschtml.md +++ b/docs/commands/eschtml.md @@ -1,4 +1,4 @@ -# escape.html: `eschtml` +# escape.html > Encode or decodes text for HTML @@ -60,11 +60,11 @@ eschtml string to escape -> Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/commands/escurl.md b/docs/commands/escurl.md index 8b1e5ff29..3d138d540 100644 --- a/docs/commands/escurl.md +++ b/docs/commands/escurl.md @@ -1,4 +1,4 @@ -# escape.url: `escurl` +# escape.url > Encode or decodes text for the URL @@ -60,11 +60,11 @@ out '%21%3F%20%3C%3E%0A' -> !escurl Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input
diff --git a/docs/commands/event.md b/docs/commands/event.md index c7907afbf..e6fde8f73 100644 --- a/docs/commands/event.md +++ b/docs/commands/event.md @@ -107,13 +107,13 @@ onSecondsElapsed * [`formap`](../commands/formap.md): Iterate through a map or other collection of data -* [`function`](../commands/function.md): +* [fs.open](../commands/open.md): + Open a file with a preferred handler +* [shell.function](../commands/function.md): Define a function block -* [`private`](../commands/private.md): +* [shell.private](../commands/private.md): Define a private function block -* [fs.open: `open`](../commands/open.md): - Open a file with a preferred handler -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/exec.md b/docs/commands/exec.md index f4e15e658..db5e5c4aa 100644 --- a/docs/commands/exec.md +++ b/docs/commands/exec.md @@ -75,25 +75,25 @@ alias for `exec`. ## See Also -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.builtins.exist: `bexists`](../commands/bexists.md): - Check which builtins exist -* [shell.builtins: `builtins`](../commands/runtime.md): +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist](../commands/bexists.md): + Check which builtins exist +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/commands/exitnum.md b/docs/commands/exitnum.md index 4e1ae16d2..feec42118 100644 --- a/docs/commands/exitnum.md +++ b/docs/commands/exitnum.md @@ -1,4 +1,4 @@ -# proc.exitnum: `exitnum` +# proc.exitnum > Output the exit number of the previous process @@ -29,7 +29,7 @@ exitnum -> * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/expr.md b/docs/commands/expr.md index cf30129c7..c8c31db4b 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -338,9 +338,9 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { Returns the right operand if the left operand is falsy (expression) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/f.md b/docs/commands/f.md index db51e5f40..8e5255029 100644 --- a/docs/commands/f.md +++ b/docs/commands/f.md @@ -1,4 +1,4 @@ -# fs.files: `f` +# fs.files (`f`) > Lists or filters file system objects (eg files) @@ -120,9 +120,9 @@ any matches from the `+` flags. * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.regex: `rx`](../commands/rx.md): +* [fs.regex (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`)
diff --git a/docs/commands/fexec.md b/docs/commands/fexec.md index 547e776ae..62e567c23 100644 --- a/docs/commands/fexec.md +++ b/docs/commands/fexec.md @@ -1,4 +1,4 @@ -# exec.*: `fexec` +# exec.* (`fexec`) > Execute a command or function, bypassing the usual order of precedence. @@ -80,30 +80,30 @@ alias to `fexec builtin` ## See Also -* [`alias`](../commands/alias.md): - Create an alias for a command * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block -* [`private`](../commands/private.md): - Define a private function block * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.list: `jobs`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.builtins: `builtins`](../commands/runtime.md): +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/commands/fg.md b/docs/commands/fg.md index 09ced0c18..01931d88b 100644 --- a/docs/commands/fg.md +++ b/docs/commands/fg.md @@ -1,4 +1,4 @@ -# proc.fg: `fg` +# proc.fg > Sends a background process into the foreground @@ -29,15 +29,15 @@ for Windows (due to the kernel not supporting the right signals) nor Plan 9. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/fid-kill.md b/docs/commands/fid-kill.md index 226abd0b7..38097aff7 100644 --- a/docs/commands/fid-kill.md +++ b/docs/commands/fid-kill.md @@ -1,4 +1,4 @@ -# proc.kill: `fid-kill` +# proc.kill > Terminate a running Murex function @@ -32,25 +32,25 @@ PID (process ID). You can obtain a FID from `fid-list`. ## See Also -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): +* [proc.kill.all](../commands/fid-killall.md): Terminate _all_ running Murex functions -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.builtins.exist: `bexists`](../commands/bexists.md): - Check which builtins exist -* [shell.builtins: `builtins`](../commands/runtime.md): +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist](../commands/bexists.md): + Check which builtins exist +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/fid-killall.md b/docs/commands/fid-killall.md index bed6c0e3e..73d8d3a59 100644 --- a/docs/commands/fid-killall.md +++ b/docs/commands/fid-killall.md @@ -1,4 +1,4 @@ -# proc.kill.all: `fid-killall` +# proc.kill.all > Terminate _all_ running Murex functions @@ -27,31 +27,31 @@ PID (process ID). You can obtain a FID from `fid-list`. ## Synonyms -* `fid.killall` +* `fid-killall` * `proc.kill.all` ## See Also -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.builtins.exist: `bexists`](../commands/bexists.md): - Check which builtins exist -* [shell.builtins: `builtins`](../commands/runtime.md): +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist](../commands/bexists.md): + Check which builtins exist +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/fid-list.md b/docs/commands/fid-list.md index c430fc7cf..593d2e31b 100644 --- a/docs/commands/fid-list.md +++ b/docs/commands/fid-list.md @@ -1,4 +1,4 @@ -# proc.list: `fid-list` +# proc.list > Lists all running functions within the current Murex session @@ -72,25 +72,25 @@ include: CSV files (and other character delimited tables) * [`jsonl`](../types/jsonl.md): JSON Lines -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `jobs`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.builtins.exist: `bexists`](../commands/bexists.md): - Check which builtins exist -* [shell.builtins: `builtins`](../commands/runtime.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.builtins.exist](../commands/bexists.md): + Check which builtins exist +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables
diff --git a/docs/parser/file-truncate.md b/docs/commands/file-truncate.md similarity index 84% rename from docs/parser/file-truncate.md rename to docs/commands/file-truncate.md index 9c75920f1..7b4dc13cb 100644 --- a/docs/parser/file-truncate.md +++ b/docs/commands/file-truncate.md @@ -1,4 +1,4 @@ -# `|>` Truncate File +# fs.truncate (`>`) > Writes stdin to disk - overwriting contents if file already exists @@ -23,8 +23,9 @@ g * |> files.txt ## Synonyms -* `|>` * `>` +* `fs.truncate` +* `|>` * `fwrite` @@ -32,20 +33,20 @@ g * |> files.txt * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`` Read Named Pipe](../commands/namedpipe.md): - Reads from a Murex named pipe * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`g`](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [`pipe`](../commands/pipe.md): - Manage Murex named pipes -* [`tmp`](../commands/tmp.md): - Create a temporary file and write to it * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command +* [fs.glob (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [fs.tmpfile (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [io.new.pipe](../commands/pipe.md): + Manage Murex named pipes +* [io.pipe (``)](../commands/namedpipe.md): + Reads from a Murex named pipe
diff --git a/docs/commands/for.md b/docs/commands/for.md index 43b687b5b..59ddd5135 100644 --- a/docs/commands/for.md +++ b/docs/commands/for.md @@ -205,8 +205,8 @@ jsonl Evaluate a mathematical function and assign to variable (deprecated) * [`while`](../commands/while.md): Loop until condition false -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/commands/foreach.md b/docs/commands/foreach.md index 2b9279fd0..b898de682 100644 --- a/docs/commands/foreach.md +++ b/docs/commands/foreach.md @@ -346,13 +346,13 @@ jsonl Loop until condition false * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [list.left: `left`](../commands/left.md): +* [list.left](../commands/left.md): Left substring every item in a list -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [shell.debug: `debug`](../commands/debug.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [shell.debug](../commands/debug.md): Debugging information
diff --git a/docs/commands/format.md b/docs/commands/format.md index 381a87485..ac5c82aac 100644 --- a/docs/commands/format.md +++ b/docs/commands/format.md @@ -30,7 +30,7 @@ Two: 2 Converts a structured file format into structured memory * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [io.out.type: `tout`](../commands/tout.md): +* [io.out.type (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type
diff --git a/docs/commands/function.md b/docs/commands/function.md index 4457fac33..72f0db626 100644 --- a/docs/commands/function.md +++ b/docs/commands/function.md @@ -1,4 +1,4 @@ -# `function` +# shell.function > Define a function block @@ -240,33 +240,35 @@ You can override this order of precedence via the `fexec` and `exec` builtins. * `function` * `!function` +* `shell.function` +* `!shell.function` ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`alias`](../commands/alias.md): - Create an alias for a command * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting * [`break`](../commands/break.md): Terminate execution of a block within your processes scope * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types -* [`private`](../commands/private.md): - Define a private function block -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [shell.version: `version`](../commands/version.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.method](../commands/method.md): + Define a methods supported data-types +* [shell.private](../commands/private.md): + Define a private function block +* [shell.version](../commands/version.md): Get Murex version * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/commands/g.md b/docs/commands/g.md index c09b62893..4b9632552 100644 --- a/docs/commands/g.md +++ b/docs/commands/g.md @@ -1,4 +1,4 @@ -# fs.glob: `g` +# fs.glob (`g`) > Glob pattern matching for file system objects (eg `*.txt`) @@ -138,13 +138,13 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. ## See Also -* [fs.files: `f`](../commands/f.md): +* [fs.files (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.regex: `rx`](../commands/rx.md): +* [fs.regex (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array
diff --git a/docs/commands/get-type.md b/docs/commands/get-type.md index fd37d564d..0ce8b5e38 100644 --- a/docs/commands/get-type.md +++ b/docs/commands/get-type.md @@ -55,15 +55,15 @@ json Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`function`](../commands/function.md): - Define a function block -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out.type: `tout`](../commands/tout.md): +* [io.out.type (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/commands/get.md b/docs/commands/get.md index f789f1aec..7fd11c3f6 100644 --- a/docs/commands/get.md +++ b/docs/commands/get.md @@ -103,7 +103,7 @@ This enables sane, repeatable and readable defaults. Read the documents on Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/getfile.md b/docs/commands/getfile.md index 45b82b0d8..94626a7f5 100644 --- a/docs/commands/getfile.md +++ b/docs/commands/getfile.md @@ -80,9 +80,9 @@ This enables sane, repeatable and readable defaults. Read the documents on Makes a standard HTTP request and returns the result as a JSON object * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/history.md b/docs/commands/history.md index 8dcd92350..300a1ffbb 100644 --- a/docs/commands/history.md +++ b/docs/commands/history.md @@ -1,4 +1,4 @@ -# shell.history: `history` +# shell.history > Outputs murex's command history @@ -47,9 +47,9 @@ The history file is typically located on disk in a file called `~/.murex.history ## See Also -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/if.md b/docs/commands/if.md index 38aba372b..da170f73d 100644 --- a/docs/commands/if.md +++ b/docs/commands/if.md @@ -147,7 +147,7 @@ code block as false. Otherwise, it will be considered true. Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information
diff --git a/docs/commands/ja.md b/docs/commands/ja.md index a759546fa..55a16ba9d 100644 --- a/docs/commands/ja.md +++ b/docs/commands/ja.md @@ -66,13 +66,13 @@ Please read the documentation on `a` for a more detailed breakdown on of Outputs an element from a nested structure * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/jsplit.md b/docs/commands/jsplit.md index 42f77d401..2b39d667c 100644 --- a/docs/commands/jsplit.md +++ b/docs/commands/jsplit.md @@ -1,4 +1,4 @@ -# str.split: `jsplit` +# str.split > Splits stdin into a JSON array based on a regex parameter @@ -51,21 +51,21 @@ unwanted "noise" is stripped from the output. Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/key-code.md b/docs/commands/key-code.md index 033f54ec0..07ced729b 100644 --- a/docs/commands/key-code.md +++ b/docs/commands/key-code.md @@ -63,7 +63,7 @@ event onKeyPress close=$key { Event driven programming for shell scripts * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros -* [io.out.type: `tout`](../commands/tout.md): +* [io.out.type (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type
diff --git a/docs/commands/left.md b/docs/commands/left.md index 7d5d65222..aad353e80 100644 --- a/docs/commands/left.md +++ b/docs/commands/left.md @@ -1,4 +1,4 @@ -# list.left: `left` +# list.left > Left substring every item in a list @@ -62,17 +62,17 @@ runtime --unmarshallers Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.right: `right`](../commands/right.md): +* [list.right](../commands/right.md): Right substring every item in a list -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/list.case.md b/docs/commands/list.case.md index e98bbc80a..347073cf4 100644 --- a/docs/commands/list.case.md +++ b/docs/commands/list.case.md @@ -1,4 +1,4 @@ -# list.case: `list.case` +# list.case > Changes the character case of a string or all elements in an array diff --git a/docs/commands/lockfile.md b/docs/commands/lockfile.md index cbb89e254..95a192a56 100644 --- a/docs/commands/lockfile.md +++ b/docs/commands/lockfile.md @@ -1,4 +1,4 @@ -# fs.lockfile: `lockfile` +# fs.lockfile > Create and manage lock files @@ -56,9 +56,9 @@ out "lock file gone!" ## See Also -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background
diff --git a/docs/commands/man-get-flags.md b/docs/commands/man-get-flags.md index 6d8350e1c..2bb7bc8f1 100644 --- a/docs/commands/man-get-flags.md +++ b/docs/commands/man-get-flags.md @@ -1,4 +1,4 @@ -# help.man.flags: `man-get-flags` +# help.man.flags > Parses man page files for command line flags @@ -62,9 +62,9 @@ requirement is that flags are hyphen prefixed, eg `--flag`. * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [help.man.summary: `man-summary`](../commands/man-summary.md): +* [help.man.summary](../commands/man-summary.md): Outputs a man page summary of a command -* [shell.summary: `summary` ](../commands/summary.md): +* [shell.summary](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/man-summary.md b/docs/commands/man-summary.md index 5a7dac311..70207f80b 100644 --- a/docs/commands/man-summary.md +++ b/docs/commands/man-summary.md @@ -1,4 +1,4 @@ -# help.man.summary: `man-summary` +# help.man.summary > Outputs a man page summary of a command @@ -48,11 +48,11 @@ ae - no man page exists * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): +* [help.man.flags](../commands/man-get-flags.md): Parses man page files for command line flags -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.summary: `summary` ](../commands/summary.md): +* [shell.summary](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/map.md b/docs/commands/map.md index 1288fa663..fd66ad493 100644 --- a/docs/commands/map.md +++ b/docs/commands/map.md @@ -1,4 +1,4 @@ -# struct.new.map: `map` +# struct.new.map (`map`) > Creates a map from two data sources @@ -41,17 +41,17 @@ map { code-block } { code-block } -> Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/match.md b/docs/commands/match.md index 11c2701d5..825cf819b 100644 --- a/docs/commands/match.md +++ b/docs/commands/match.md @@ -1,4 +1,4 @@ -# list.str: `match` +# list.str (`match`) > Match an exact value in an array @@ -78,31 +78,31 @@ same data-type. * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/method.md b/docs/commands/method.md index 6c28bb347..e26fabe09 100644 --- a/docs/commands/method.md +++ b/docs/commands/method.md @@ -1,4 +1,4 @@ -# `method` +# shell.method > Define a methods supported data-types @@ -64,21 +64,27 @@ var GroupMath = []string{ } ``` +## Synonyms + +* `method` +* `shell.method` + + ## See Also * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`alias`](../commands/alias.md): +* [shell.alias](../commands/alias.md): Create an alias for a command -* [`function`](../commands/function.md): +* [shell.autocomplete](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): Define a function block -* [`private`](../commands/private.md): +* [shell.private](../commands/private.md): Define a private function block -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/mjoin.md b/docs/commands/mjoin.md index 3746e9789..e49164c77 100644 --- a/docs/commands/mjoin.md +++ b/docs/commands/mjoin.md @@ -1,4 +1,4 @@ -# list.join: `mjoin` +# list.join > Joins a list or array into a single string @@ -45,7 +45,7 @@ Monday!Tuesday!Wednesday!Thursday!Friday Quickly generate arrays * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter
diff --git a/docs/commands/msort.md b/docs/commands/msort.md index e87641305..bf0f99b37 100644 --- a/docs/commands/msort.md +++ b/docs/commands/msort.md @@ -1,4 +1,4 @@ -# list.sort: `msort` +# list.sort > Sorts an array - data type agnostic @@ -62,19 +62,19 @@ output of `msort` into another builtin: Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/mtac.md b/docs/commands/mtac.md index cb5318007..dc4424d28 100644 --- a/docs/commands/mtac.md +++ b/docs/commands/mtac.md @@ -1,4 +1,4 @@ -# list.reverse: `mtac` +# list.reverse (`mtac`) > Reverse the order of an array @@ -62,29 +62,29 @@ stdin is a long running process or non-standard stream (eg network pipe). * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/murex-docs.md b/docs/commands/murex-docs.md index ab7120236..06dd7226b 100644 --- a/docs/commands/murex-docs.md +++ b/docs/commands/murex-docs.md @@ -44,18 +44,18 @@ These man pages are compiled into the Murex executable. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../commands/tread.md): +* [`tread`](../deprecated/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): +* [help.man.flags](../commands/man-get-flags.md): Parses man page files for command line flags -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/commands/murex-package.md b/docs/commands/murex-package.md index 703785585..860b144e0 100644 --- a/docs/commands/murex-package.md +++ b/docs/commands/murex-package.md @@ -1,4 +1,4 @@ -# shell.packages: `murex-package` +# shell.packages (`murex-package`) > Murex's package manager @@ -113,7 +113,7 @@ If you wish to view what modules are loaded in a current session then use ## Synonyms -* `murex.package` +* `murex-package` * `shell.packages` @@ -123,17 +123,17 @@ If you wish to view what modules are loaded in a current session then use An introduction to Murex modules and packages * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`alias`](../commands/alias.md): - Create an alias for a command -* [`function`](../commands/function.md): - Define a function block * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`private`](../commands/private.md): - Define a private function block -* [shell.config: `config`](../commands/config.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/murex-update-exe-list.md b/docs/commands/murex-update-exe-list.md index a2ec1a116..7e73ec356 100644 --- a/docs/commands/murex-update-exe-list.md +++ b/docs/commands/murex-update-exe-list.md @@ -1,4 +1,4 @@ -# shell.rescan.path: `murex-update-exe-list` +# shell.rescan.path > Forces Murex to rescan $PATH looking for executables @@ -34,11 +34,11 @@ invoked for command name completion via the REPL shell. ## See Also -* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count: `cpucount`](../commands/cpucount.md): +* [sys.cpu.count](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os: `os`](../commands/os.md): +* [sys.os](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/namedpipe.md b/docs/commands/namedpipe.md index f1e29de95..ab63a7627 100644 --- a/docs/commands/namedpipe.md +++ b/docs/commands/namedpipe.md @@ -1,4 +1,4 @@ -# io.pipe: `` Read Named Pipe +# io.pipe (``) > Reads from a Murex named pipe @@ -118,17 +118,17 @@ that pipes created in modules should be prefixed with the name of its package. ## See Also -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [proc.bg: `bg`](../commands/bg.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [proc.bg](../commands/bg.md): Run processes in the background -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/open-image.md b/docs/commands/open-image.md index 57cbf03c9..b4789a436 100644 --- a/docs/commands/open-image.md +++ b/docs/commands/open-image.md @@ -1,4 +1,4 @@ -# fs.open.image: `open-image` +# fs.open.image > Renders bitmap image data on your terminal @@ -44,7 +44,7 @@ open-image file-path -> * [`qr`](../optional/qr.md): Creates a QR code from stdin -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler
diff --git a/docs/commands/open.md b/docs/commands/open.md index 40c4da6d5..4788acef1 100644 --- a/docs/commands/open.md +++ b/docs/commands/open.md @@ -1,4 +1,4 @@ -# fs.open: `open` +# fs.open > Open a file with a preferred handler @@ -230,13 +230,13 @@ exec open --flags filename Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` diff --git a/docs/commands/openagent.md b/docs/commands/openagent.md index 1c47850d7..7c2345694 100644 --- a/docs/commands/openagent.md +++ b/docs/commands/openagent.md @@ -48,11 +48,11 @@ handler by checking `runtime --open-agents` and checking it's **FileRef**. How to track what code was loaded and from where * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/os.md b/docs/commands/os.md index dbb17a591..2eda38c5a 100644 --- a/docs/commands/os.md +++ b/docs/commands/os.md @@ -1,4 +1,4 @@ -# sys.os: `os` +# sys.os > Output the auto-detected OS name @@ -77,9 +77,9 @@ then please write it as `os posix plan9`. ## See Also -* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count: `cpucount`](../commands/cpucount.md): +* [sys.cpu.count](../commands/cpucount.md): Output the number of CPU cores available on your host
diff --git a/docs/commands/out.md b/docs/commands/out.md index ac4886d98..db41d1d8a 100644 --- a/docs/commands/out.md +++ b/docs/commands/out.md @@ -1,4 +1,4 @@ -# io.out: `out` +# io.out > Print a string to the stdout with a trailing new line character @@ -56,18 +56,18 @@ Hello, World! Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../commands/tread.md): +* [`tread`](../deprecated/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.status: `pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.input: `read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.out.type: `tout`](../commands/tout.md): +* [io.out.type (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type +* [io.read](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written
diff --git a/docs/commands/pipe.md b/docs/commands/pipe.md index d5d9a9a53..4dc7289ac 100644 --- a/docs/commands/pipe.md +++ b/docs/commands/pipe.md @@ -1,4 +1,4 @@ -# io.new.pipe: `pipe` +# io.new.pipe > Manage Murex named pipes @@ -128,21 +128,21 @@ that pipes created in modules should be prefixed with the name of its package. * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [io.out: `out`](../commands/out.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/post.md b/docs/commands/post.md index d3ce28ef3..b1c00ce45 100644 --- a/docs/commands/post.md +++ b/docs/commands/post.md @@ -105,7 +105,7 @@ This enables sane, repeatable and readable defaults. Read the documents on Makes a standard HTTP request and returns the result as a JSON object * [`getfile`](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/prefix.md b/docs/commands/prefix.md index 66a830191..332eb4b83 100644 --- a/docs/commands/prefix.md +++ b/docs/commands/prefix.md @@ -1,4 +1,4 @@ -# list.prefix: `prefix` +# list.prefix > Prefix a string to every item in a list @@ -46,17 +46,17 @@ runtime --unmarshallers Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.left: `left`](../commands/left.md): +* [list.left](../commands/left.md): Left substring every item in a list -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.right: `right`](../commands/right.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.right](../commands/right.md): Right substring every item in a list -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/prepend.md b/docs/commands/prepend.md index a202d31a0..f1d7964a8 100644 --- a/docs/commands/prepend.md +++ b/docs/commands/prepend.md @@ -1,4 +1,4 @@ -# list.prepend: `prepend` +# list.prepend > Add data to the start of an array @@ -56,21 +56,21 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco Alters the data-type of the previous function without altering its output * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.regex: `regexp`](../commands/regexp.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [table.new.heading: `addheading` ](../commands/addheading.md): +* [table.add.heading](../commands/addheading.md): Adds headings to a table
diff --git a/docs/commands/pretty.md b/docs/commands/pretty.md index 0a7a32a59..8e1560737 100644 --- a/docs/commands/pretty.md +++ b/docs/commands/pretty.md @@ -1,4 +1,4 @@ -# struct.json.pretty: `pretty` +# struct.json.pretty > Prettifies JSON to make it human readable @@ -40,10 +40,10 @@ outputs that to stdout. * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/commands/private.md b/docs/commands/private.md index 64d771b2a..f58a83607 100644 --- a/docs/commands/private.md +++ b/docs/commands/private.md @@ -1,4 +1,4 @@ -# `private` +# shell.private > Define a private function block @@ -90,26 +90,32 @@ There is an order of precedence for which commands are looked up: You can override this order of precedence via the `fexec` and `exec` builtins. +## Synonyms + +* `private` +* `shell.private` + + ## See Also -* [`alias`](../commands/alias.md): - Create an alias for a command * [`break`](../commands/break.md): Terminate execution of a block within your processes scope -* [`function`](../commands/function.md): - Define a function block * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.function](../commands/function.md): + Define a function block +* [shell.method](../commands/method.md): + Define a methods supported data-types * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value * [var.global: `global`](../commands/global.md): diff --git a/docs/commands/pt.md b/docs/commands/pt.md index 78c0fd680..d8eda4941 100644 --- a/docs/commands/pt.md +++ b/docs/commands/pt.md @@ -1,4 +1,4 @@ -# fs.status: `pt` +# io.status (`pt`) > Pipe telemetry. Writes data-types and bytes written @@ -38,7 +38,7 @@ curl -s https://example.com/bigfile.bin -> pt |> bigfile.bin Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists
diff --git a/docs/commands/read.md b/docs/commands/read.md index f214ce886..127547b5f 100644 --- a/docs/commands/read.md +++ b/docs/commands/read.md @@ -1,4 +1,4 @@ -# io.input: `read` +# io.read > `read` a line of input from the user and store as a variable @@ -99,16 +99,16 @@ with the `--datatype` flag as per the **script usage**. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../commands/tread.md): +* [`tread`](../deprecated/tread.md): `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 363ce5cd2..052894efa 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -1,4 +1,4 @@ -# list.regex: `regexp` +# list.regex > Regexp tools for arrays / lists of strings @@ -97,31 +97,31 @@ same data-type. * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources
diff --git a/docs/commands/return.md b/docs/commands/return.md index 945a92940..3fc4ccb80 100644 --- a/docs/commands/return.md +++ b/docs/commands/return.md @@ -62,14 +62,14 @@ was passed). Terminate process of a block within a caller function * [`exit`](../commands/exit.md): Exit murex -* [`function`](../commands/function.md): - Define a function block -* [`private`](../commands/private.md): - Define a private function block -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [proc.exitnum: `exitnum`](../commands/exitnum.md): +* [proc.exitnum](../commands/exitnum.md): Output the exit number of the previous process +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/commands/right.md b/docs/commands/right.md index 980d6a67d..bbd993ecb 100644 --- a/docs/commands/right.md +++ b/docs/commands/right.md @@ -1,4 +1,4 @@ -# list.right: `right` +# list.right > Right substring every item in a list @@ -62,17 +62,17 @@ runtime --unmarshallers Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.right: `right`](../commands/right.md): +* [list.right](../commands/right.md): Right substring every item in a list -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/runmode.md b/docs/commands/runmode.md index c17bd3b8b..8267b3c14 100644 --- a/docs/commands/runmode.md +++ b/docs/commands/runmode.md @@ -91,10 +91,6 @@ if `runmode ... module` is set. Handles the exception code raised by `try` or `trypipe` * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block -* [`private`](../commands/private.md): - Define a private function block * [`try`](../commands/try.md): Handles non-zero exits inside a block of code * [`tryerr`](../commands/tryerr.md): @@ -105,14 +101,18 @@ if `runmode ... module` is set. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [io.input: `read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [proc.list: `fid-list`](../commands/fid-list.md): +* [io.read](../commands/read.md): + `read` a line of input from the user and store as a variable +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/commands/runtime.md b/docs/commands/runtime.md index 1ebda5571..2fae3a86b 100644 --- a/docs/commands/runtime.md +++ b/docs/commands/runtime.md @@ -1,4 +1,4 @@ -# shell.runtime: `runtime` +# shell.runtime > Returns runtime information on the internal state of Murex @@ -298,33 +298,33 @@ functions. Iterate through a map or other collection of data * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`function`](../commands/function.md): - Define a function block * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types -* [`private`](../commands/private.md): - Define a private function block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information +* [shell.function](../commands/function.md): + Define a function block +* [shell.method](../commands/method.md): + Define a methods supported data-types * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [shell.private](../commands/private.md): + Define a private function block +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/commands/rx.md b/docs/commands/rx.md index a6e25d2c5..143452ff4 100644 --- a/docs/commands/rx.md +++ b/docs/commands/rx.md @@ -1,4 +1,4 @@ -# fs.regex: `rx` +# fs.regex (`rx`) > Regexp pattern matching for file system objects (eg `.*\\.txt`) @@ -120,13 +120,13 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. ## See Also -* [fs.files: `f`](../commands/f.md): +* [fs.files (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array
diff --git a/docs/commands/signal.md b/docs/commands/signal.md index 23a99f6f7..d56aed06b 100644 --- a/docs/commands/signal.md +++ b/docs/commands/signal.md @@ -168,11 +168,11 @@ Signals can be caught (often referred to as "trapped") in Murex with an event: A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [onSignalReceived](../events/onsignalreceived.md): Trap OS signals -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background
diff --git a/docs/commands/source.md b/docs/commands/source.md index 06a6cc586..a0ac74be5 100644 --- a/docs/commands/source.md +++ b/docs/commands/source.md @@ -1,4 +1,4 @@ -# exec.include: `source` +# exec.include (`source`) > Import Murex code from another file or code block @@ -63,23 +63,23 @@ Hello, world! * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`function`](../commands/function.md): - Define a function block -* [`murex-parser` ](../commands/murex-parser.md): +* [`murex-parser` ](../deprecated/murex-parser.md): Runs the Murex parser against a block of code -* [`private`](../commands/private.md): - Define a private function block -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.version: `version`](../commands/version.md): +* [shell.version](../commands/version.md): Get Murex version
diff --git a/docs/commands/stdin.md b/docs/commands/stdin.md index 1f640bb66..dd080c27b 100644 --- a/docs/commands/stdin.md +++ b/docs/commands/stdin.md @@ -1,4 +1,4 @@ -# `` +# io.in (``) > Read the stdin belonging to the parent code block @@ -127,23 +127,24 @@ that pipes created in modules should be prefixed with the name of its package. ## Synonyms * `` +* `io.in` ## See Also * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`function`](../commands/function.md): - Define a function block -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/struct-keys.md b/docs/commands/struct-keys.md index 55c4d0066..69a234b38 100644 --- a/docs/commands/struct-keys.md +++ b/docs/commands/struct-keys.md @@ -1,4 +1,4 @@ -# struct.keys: `struct-keys` +# struct.keys > Outputs all the keys in a structure as a file path diff --git a/docs/commands/suffix.md b/docs/commands/suffix.md index 5423e625a..d3481b41c 100644 --- a/docs/commands/suffix.md +++ b/docs/commands/suffix.md @@ -1,4 +1,4 @@ -# list.suffix: `suffix` +# list.suffix > Prefix a string to every item in a list @@ -46,17 +46,17 @@ runtime --unmarshallers Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.left: `left`](../commands/left.md): +* [list.left](../commands/left.md): Left substring every item in a list -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.right: `right`](../commands/right.md): +* [list.right](../commands/right.md): Right substring every item in a list -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/summary.md b/docs/commands/summary.md index a0cd343e0..65b34f524 100644 --- a/docs/commands/summary.md +++ b/docs/commands/summary.md @@ -1,4 +1,4 @@ -# shell.summary: `summary` +# shell.summary > Defines a summary help text for a command @@ -55,17 +55,17 @@ Hello, world! Displays the man pages for Murex builtins * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.builtins.exist: `bexists`](../commands/bexists.md): - Check which builtins exist -* [shell.builtins: `builtins`](../commands/runtime.md): +* [shell.builtins](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.config: `config`](../commands/config.md): +* [shell.builtins.exist](../commands/bexists.md): + Check which builtins exist +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/ta.md b/docs/commands/ta.md index 21c331dae..3cbbc356e 100644 --- a/docs/commands/ta.md +++ b/docs/commands/ta.md @@ -70,11 +70,11 @@ Please read the documentation on `a` for a more detailed breakdown on of Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/commands/tabulate.md b/docs/commands/tabulate.md index 20e620207..5d3317a82 100644 --- a/docs/commands/tabulate.md +++ b/docs/commands/tabulate.md @@ -63,7 +63,7 @@ rsync --help # print rsync help Iterate through a map or other collection of data * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line
diff --git a/docs/commands/test.md b/docs/commands/test.md index 7133f98d5..2d5c136df 100644 --- a/docs/commands/test.md +++ b/docs/commands/test.md @@ -114,9 +114,9 @@ flushes the table of pending reports. ## See Also -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/time.md b/docs/commands/time.md index f21854b09..8156badfd 100644 --- a/docs/commands/time.md +++ b/docs/commands/time.md @@ -45,7 +45,7 @@ and stderr as usual. Suspends the shell for a number of seconds * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block
diff --git a/docs/commands/tmp.md b/docs/commands/tmp.md index 312b3da3d..a3720aa61 100644 --- a/docs/commands/tmp.md +++ b/docs/commands/tmp.md @@ -1,4 +1,4 @@ -# fs.new.tmpfile: `tmp` +# fs.tmpfile (`tmp`) > Create a temporary file and write to it @@ -106,11 +106,11 @@ which itself is located in the appropriate temp directory for the host OS (eg * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes
diff --git a/docs/commands/tout.md b/docs/commands/tout.md index 541e7ae7e..aaa5759b3 100644 --- a/docs/commands/tout.md +++ b/docs/commands/tout.md @@ -1,4 +1,4 @@ -# io.out.type: `tout` +# io.out.type (`tout`) > Print a string to the stdout and set it's data-type @@ -45,11 +45,11 @@ Unlike `out`, `tout` does not append a carriage return / line feed. Alters the data-type of the previous function without altering its output * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable
diff --git a/docs/commands/try.md b/docs/commands/try.md index 319f7bd50..0461a97cc 100644 --- a/docs/commands/try.md +++ b/docs/commands/try.md @@ -61,7 +61,7 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/tryerr.md b/docs/commands/tryerr.md index e456cf9eb..2b04f82d1 100644 --- a/docs/commands/tryerr.md +++ b/docs/commands/tryerr.md @@ -62,7 +62,7 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/trypipe.md b/docs/commands/trypipe.md index 54fffe7f4..e0ab61861 100644 --- a/docs/commands/trypipe.md +++ b/docs/commands/trypipe.md @@ -64,7 +64,7 @@ command. Checks state of each function in a pipeline and exits block on error * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/trypipeerr.md b/docs/commands/trypipeerr.md index f5201c535..c15acca5d 100644 --- a/docs/commands/trypipeerr.md +++ b/docs/commands/trypipeerr.md @@ -65,7 +65,7 @@ command. Checks for non-zero exits of each function in a pipeline * [`unsafe`](../commands/unsafe.md): Execute a block of code, always returning a zero exit number -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/type.md b/docs/commands/type.md index 087c5d01a..1f1ac7c5a 100644 --- a/docs/commands/type.md +++ b/docs/commands/type.md @@ -69,20 +69,20 @@ In `type`, it is represented by the term **executable**. ## See Also -* [`alias`](../commands/alias.md): - Create an alias for a command * [`exit`](../commands/exit.md): Exit murex -* [`function`](../commands/function.md): - Define a function block * [`which`](../commands/which.md): Locate command origin -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.function](../commands/function.md): + Define a function block
diff --git a/docs/commands/unsafe.md b/docs/commands/unsafe.md index a659c8bb0..2e95a01ac 100644 --- a/docs/commands/unsafe.md +++ b/docs/commands/unsafe.md @@ -46,7 +46,7 @@ try { Checks for non-zero exits of each function in a pipeline * [`trypipeerr`](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/commands/version.md b/docs/commands/version.md index 6b3d6a310..9b35899d2 100644 --- a/docs/commands/version.md +++ b/docs/commands/version.md @@ -1,4 +1,4 @@ -# shell.version: `version` +# shell.version > Get Murex version @@ -52,19 +52,19 @@ murex: 0.51.1200 BETA * [`args` ](../commands/args.md): Command line flag parser for Murex shell scripting -* [`function`](../commands/function.md): - Define a function block -* [`murex-parser` ](../commands/murex-parser.md): +* [`murex-parser` ](../deprecated/murex-parser.md): Runs the Murex parser against a block of code -* [`private`](../commands/private.md): - Define a private function block -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/which.md b/docs/commands/which.md index 0959859ed..b51ddd512 100644 --- a/docs/commands/which.md +++ b/docs/commands/which.md @@ -75,20 +75,20 @@ In `type`, it is represented by the term **executable**. ## See Also -* [`alias`](../commands/alias.md): - Create an alias for a command * [`exit`](../commands/exit.md): Exit murex -* [`function`](../commands/function.md): - Define a function block * [`type`](../commands/type.md): Command type (function, builtin, alias, etc) -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.function](../commands/function.md): + Define a function block
diff --git a/docs/commands/while.md b/docs/commands/while.md index cf3be8fa5..f09fe049d 100644 --- a/docs/commands/while.md +++ b/docs/commands/while.md @@ -104,9 +104,9 @@ The following meta values are defined: Iterate through a map or other collection of data * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.global: `global`](../commands/global.md): Define a global variable and set it's value diff --git a/docs/events/oncommandcompletion.md b/docs/events/oncommandcompletion.md index 306c5bbc5..ddc5e18a7 100644 --- a/docs/events/oncommandcompletion.md +++ b/docs/events/oncommandcompletion.md @@ -119,26 +119,26 @@ Stdout and stderr are both written to the terminal's stderr. * [Named Pipes](../user-guide/namedpipes.md): A detailed breakdown of named pipes in Murex -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`alias`](../commands/alias.md): - Create an alias for a command * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [list.regex: `regexp`](../commands/regexp.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings * [read-named-pipe](../commands/namedpipe.md): Reads from a Murex named pipe -* [shell.config: `config`](../commands/config.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block
diff --git a/docs/events/onfilesystemchange.md b/docs/events/onfilesystemchange.md index 3f1080c2b..1c847274a 100644 --- a/docs/events/onfilesystemchange.md +++ b/docs/events/onfilesystemchange.md @@ -91,7 +91,7 @@ event to Linux, macOS and UNIX systems instead. * [`event`](../commands/event.md): Event driven programming for shell scripts -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/events/onkeypress.md b/docs/events/onkeypress.md index 923ca412a..14a1f1a52 100644 --- a/docs/events/onkeypress.md +++ b/docs/events/onkeypress.md @@ -263,7 +263,7 @@ from different interrupts). Full screen previews for files and command documentation * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/events/onpreview.md b/docs/events/onpreview.md index ccf765cc4..08a062d98 100644 --- a/docs/events/onpreview.md +++ b/docs/events/onpreview.md @@ -170,8 +170,6 @@ from different interrupts). A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`function`](../commands/function.md): - Define a function block * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins * [`onCommandCompletion`](../events/oncommandcompletion.md): @@ -180,8 +178,10 @@ from different interrupts). Custom definable key bindings and macros * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block
diff --git a/docs/events/onprompt.md b/docs/events/onprompt.md index 1207c84bb..1ef9815bf 100644 --- a/docs/events/onprompt.md +++ b/docs/events/onprompt.md @@ -135,7 +135,7 @@ from different interrupts). Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/events/onsecondselapsed.md b/docs/events/onsecondselapsed.md index 691dc0e62..d51e31aa2 100644 --- a/docs/events/onsecondselapsed.md +++ b/docs/events/onsecondselapsed.md @@ -60,7 +60,7 @@ Stdout and stderr are both written to the terminal. * [`event`](../commands/event.md): Event driven programming for shell scripts -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/integrations/chatgpt.md b/docs/integrations/chatgpt.md index 4c097533f..0801bb343 100644 --- a/docs/integrations/chatgpt.md +++ b/docs/integrations/chatgpt.md @@ -139,7 +139,7 @@ under `/integrations`. Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/cheatsh.md b/docs/integrations/cheatsh.md index 3d05e50c9..21f621271 100644 --- a/docs/integrations/cheatsh.md +++ b/docs/integrations/cheatsh.md @@ -42,7 +42,7 @@ under `/integrations`. Displays the man pages for Murex builtins * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/iterm2.md b/docs/integrations/iterm2.md index f0851183c..277531cc4 100644 --- a/docs/integrations/iterm2.md +++ b/docs/integrations/iterm2.md @@ -30,7 +30,7 @@ open https://murex.rocks/git-autocomplete.png Get more out of Kitty terminal emulator * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` diff --git a/docs/integrations/kitty.md b/docs/integrations/kitty.md index f985f42cf..fc5347931 100644 --- a/docs/integrations/kitty.md +++ b/docs/integrations/kitty.md @@ -24,7 +24,7 @@ to Kitty's ANSI escape sequences to render those images beautifully. * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator diff --git a/docs/integrations/make.md b/docs/integrations/make.md index a3f26e8db..3d8024898 100644 --- a/docs/integrations/make.md +++ b/docs/integrations/make.md @@ -30,7 +30,7 @@ under `/integrations`. A list of all the terminal hotkeys and their uses * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/man-pages.md b/docs/integrations/man-pages.md index 2186b5998..4ddb9d503 100644 --- a/docs/integrations/man-pages.md +++ b/docs/integrations/man-pages.md @@ -54,7 +54,7 @@ That command will generally be pulled from its accompanying `man` page. Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/spellcheck.md b/docs/integrations/spellcheck.md index 4f5c47706..c781b6a1b 100644 --- a/docs/integrations/spellcheck.md +++ b/docs/integrations/spellcheck.md @@ -167,13 +167,13 @@ and what the package names are for `aspell` and its corresponding dictionaries. JavaScript Object Notation (JSON) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/integrations/terminology.md b/docs/integrations/terminology.md index ae6bf93e7..2a9604e0d 100644 --- a/docs/integrations/terminology.md +++ b/docs/integrations/terminology.md @@ -25,7 +25,7 @@ beautifully. * [Kitty Integrations](../integrations/kitty.md): Get more out of Kitty terminal emulator -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator diff --git a/docs/integrations/yarn.md b/docs/integrations/yarn.md index 7a6ac4300..44be243a2 100644 --- a/docs/integrations/yarn.md +++ b/docs/integrations/yarn.md @@ -27,7 +27,7 @@ under `/integrations`. A list of all the terminal hotkeys and their uses * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/mkarray/character.md b/docs/mkarray/character.md index 7063d4ab6..ca5de3148 100644 --- a/docs/mkarray/character.md +++ b/docs/mkarray/character.md @@ -68,11 +68,11 @@ a A sophisticated yet simply way to build a JSON array * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/mkarray/date.md b/docs/mkarray/date.md index 8bafe7e9f..b3e5be3c2 100644 --- a/docs/mkarray/date.md +++ b/docs/mkarray/date.md @@ -203,15 +203,15 @@ Friday, 03 January A sophisticated yet simply way to build a JSON array * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/mkarray/decimal.md b/docs/mkarray/decimal.md index 1fe72ff2d..11c60176f 100644 --- a/docs/mkarray/decimal.md +++ b/docs/mkarray/decimal.md @@ -122,11 +122,11 @@ arrays such as JSON (`ja`). A sophisticated yet simply way to build a JSON array * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/mkarray/non-decimal.md b/docs/mkarray/non-decimal.md index 594bfb4e6..83b28892a 100644 --- a/docs/mkarray/non-decimal.md +++ b/docs/mkarray/non-decimal.md @@ -135,11 +135,11 @@ arrays such as JSON (`ja`). A sophisticated yet simply way to build a JSON array * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/mkarray/special.md b/docs/mkarray/special.md index 55f0e9995..afa08aea2 100644 --- a/docs/mkarray/special.md +++ b/docs/mkarray/special.md @@ -228,15 +228,15 @@ var rangeMoon = map[string]int{ A sophisticated yet simply way to build a JSON array * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/optional/base64.md b/docs/optional/base64.md index e7e4e0d39..8d42d7cec 100644 --- a/docs/optional/base64.md +++ b/docs/optional/base64.md @@ -59,13 +59,13 @@ it doesn't require the OS fork processes. Decompress a bz2 file * [`gz`](../optional/gz.md): Compress or decompress a gzip file -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/optional/bz2.md b/docs/optional/bz2.md index bbbb25fb5..2d52bde24 100644 --- a/docs/optional/bz2.md +++ b/docs/optional/bz2.md @@ -27,13 +27,13 @@ Currently there is no support for compressing a stream using bz2. Encode or decode a base64 string * [`gz`](../optional/gz.md): Compress or decompress a gzip file -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/optional/gz.md b/docs/optional/gz.md index 3db6408e5..81347ec6e 100644 --- a/docs/optional/gz.md +++ b/docs/optional/gz.md @@ -26,13 +26,13 @@ An optional builtin for compressing or decompressing a gzip stream from stdin. Decompress a bz2 file * [`base64` ](../optional/base64.md): Encode or decode a base64 string -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/optional/qr.md b/docs/optional/qr.md index 186cf176e..417bd98a1 100644 --- a/docs/optional/qr.md +++ b/docs/optional/qr.md @@ -37,7 +37,7 @@ have to `cast` the output in some circumstances. * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [fs.open.image: `open-image`](../commands/open-image.md): +* [fs.open.image](../commands/open-image.md): Renders bitmap image data on your terminal
diff --git a/docs/optional/select.md b/docs/optional/select.md index 79c9cbc2c..22cdf95c9 100644 --- a/docs/optional/select.md +++ b/docs/optional/select.md @@ -139,7 +139,7 @@ If you do run into any issues then please raise them on [Github](https://github. CSV files (and other character delimited tables) * [`jsonl`](../types/jsonl.md): JSON Lines -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [v2.1](../changelog/v2.1.md): This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details. diff --git a/docs/optional/sleep.md b/docs/optional/sleep.md index 6238d0c50..227d1e23f 100644 --- a/docs/optional/sleep.md +++ b/docs/optional/sleep.md @@ -36,7 +36,7 @@ or similar platforms then you will need to launch with the `exec` builtin: Returns the execution run time of a command or block * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block
diff --git a/docs/parser/add-with.md b/docs/parser/add-with.md index 7479e0f74..a4890fd55 100644 --- a/docs/parser/add-with.md +++ b/docs/parser/add-with.md @@ -63,7 +63,7 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/addition.md b/docs/parser/addition.md index 8486b6a49..080239924 100644 --- a/docs/parser/addition.md +++ b/docs/parser/addition.md @@ -83,7 +83,7 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/array.md b/docs/parser/array.md index 96915413b..515cb99b7 100644 --- a/docs/parser/array.md +++ b/docs/parser/array.md @@ -132,7 +132,7 @@ foo 1 2 3 4 5 bar string (primitive) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/assign-or-merge.md b/docs/parser/assign-or-merge.md index ce0801959..b9ff8c991 100644 --- a/docs/parser/assign-or-merge.md +++ b/docs/parser/assign-or-merge.md @@ -98,9 +98,9 @@ builtin. Expressions: mathematical, string comparisons, logical operators * [`foreach`](../commands/foreach.md): Iterate through an array -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/parser/brace-quote-func.md b/docs/parser/brace-quote-func.md index 0875ee1ab..21b28c827 100644 --- a/docs/parser/brace-quote-func.md +++ b/docs/parser/brace-quote-func.md @@ -54,16 +54,16 @@ characters if you don't want them nested. Writes stdin to disk - appending contents if file already exists * [`cast`](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [fs.status: `pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written
diff --git a/docs/parser/brace-quote.md b/docs/parser/brace-quote.md index 31d993775..15032582e 100644 --- a/docs/parser/brace-quote.md +++ b/docs/parser/brace-quote.md @@ -104,7 +104,7 @@ Hello (World!) Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/c-style-fun.md b/docs/parser/c-style-fun.md index 6341d7790..8a573ce1a 100644 --- a/docs/parser/c-style-fun.md +++ b/docs/parser/c-style-fun.md @@ -105,9 +105,9 @@ It is 23 o' clock Getting started with Murex * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [io.echo: `echo`](../commands/out.md): +* [io.echo](../commands/out.md): Print a string to the stdout with a trailing new line character * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/docs/parser/create-array.md b/docs/parser/create-array.md index eaba9ba99..04ba0baae 100644 --- a/docs/parser/create-array.md +++ b/docs/parser/create-array.md @@ -189,8 +189,8 @@ arrays. For more details on these please refer to the documents for each format Expressions: mathematical, string comparisons, logical operators * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type diff --git a/docs/parser/curly-brace.md b/docs/parser/curly-brace.md index 4605c9715..e5af1145f 100644 --- a/docs/parser/curly-brace.md +++ b/docs/parser/curly-brace.md @@ -86,12 +86,12 @@ constants are available. string (primitive) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/divide-by.md b/docs/parser/divide-by.md index be3968ff4..5c9c761ec 100644 --- a/docs/parser/divide-by.md +++ b/docs/parser/divide-by.md @@ -63,7 +63,7 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/division.md b/docs/parser/division.md index 67d379045..61a4326e0 100644 --- a/docs/parser/division.md +++ b/docs/parser/division.md @@ -78,7 +78,7 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/double-quote.md b/docs/parser/double-quote.md index 76f124ce2..e98322067 100644 --- a/docs/parser/double-quote.md +++ b/docs/parser/double-quote.md @@ -49,7 +49,7 @@ bar Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/element.md b/docs/parser/element.md index 0637df3d8..4f8ca3760 100644 --- a/docs/parser/element.md +++ b/docs/parser/element.md @@ -128,13 +128,13 @@ bool Outputs an element from an array, map or table * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md index 82e609bd7..aa361494d 100644 --- a/docs/parser/elvis.md +++ b/docs/parser/elvis.md @@ -69,9 +69,9 @@ where it says: Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/expr-inlined.md b/docs/parser/expr-inlined.md index 9af96eb19..3b04834e4 100644 --- a/docs/parser/expr-inlined.md +++ b/docs/parser/expr-inlined.md @@ -27,7 +27,7 @@ that parameter will be treated like a string. A table of all supported operators and tokens * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [io.echo: `echo`](../commands/out.md): +* [io.echo](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/file-append.md b/docs/parser/file-append.md index 418499029..aba38d2a2 100644 --- a/docs/parser/file-append.md +++ b/docs/parser/file-append.md @@ -57,13 +57,13 @@ To truncate a file (ie overwrite its contents) use `|>` instead. Pipes stdout from the left hand command to stdin of the right hand command * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe
diff --git a/docs/parser/item-index.md b/docs/parser/item-index.md index e187c2922..0a10e31df 100644 --- a/docs/parser/item-index.md +++ b/docs/parser/item-index.md @@ -153,13 +153,13 @@ Error in `[` ((builtin) 2,11): Key 'foobar' not found Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/parser/lambda.md b/docs/parser/lambda.md index 2df796754..f38255d0d 100644 --- a/docs/parser/lambda.md +++ b/docs/parser/lambda.md @@ -191,11 +191,11 @@ The following meta values are defined: Iterate through a map or other collection of data * [`while`](../commands/while.md): Loop until condition false -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/parser/logical-and.md b/docs/parser/logical-and.md index 5b5410e76..1e83c68f2 100644 --- a/docs/parser/logical-and.md +++ b/docs/parser/logical-and.md @@ -61,9 +61,9 @@ try { Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/logical-or.md b/docs/parser/logical-or.md index 85777a669..d05d01d49 100644 --- a/docs/parser/logical-or.md +++ b/docs/parser/logical-or.md @@ -64,9 +64,9 @@ There is no workaround for `trypipe`. Handles non-zero exits inside a block of code * [`trypipe`](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/multiplication.md b/docs/parser/multiplication.md index 6019c79d1..077b34e55 100644 --- a/docs/parser/multiplication.md +++ b/docs/parser/multiplication.md @@ -78,7 +78,7 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/multiply-by.md b/docs/parser/multiply-by.md index f8457c884..32bfd524f 100644 --- a/docs/parser/multiply-by.md +++ b/docs/parser/multiply-by.md @@ -63,7 +63,7 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md index 07694ce2e..ef7dfbce1 100644 --- a/docs/parser/null-coalescing.md +++ b/docs/parser/null-coalescing.md @@ -76,9 +76,9 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/pipe-arrow.md b/docs/parser/pipe-arrow.md index c0a533f77..8878ac61e 100644 --- a/docs/parser/pipe-arrow.md +++ b/docs/parser/pipe-arrow.md @@ -57,13 +57,13 @@ Hello, Earth! Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings
diff --git a/docs/parser/pipe-err.md b/docs/parser/pipe-err.md index e4c07501b..ecdef523e 100644 --- a/docs/parser/pipe-err.md +++ b/docs/parser/pipe-err.md @@ -49,13 +49,13 @@ Hello, world!? regexp s/world/Earth/ Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings
diff --git a/docs/parser/pipe-generic.md b/docs/parser/pipe-generic.md index 8e4268f65..9508dee68 100644 --- a/docs/parser/pipe-generic.md +++ b/docs/parser/pipe-generic.md @@ -60,7 +60,7 @@ To demonstrate how the previous pipeline might look without a formatted pipe: A sophisticated yet simply way to build a JSON array * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe
diff --git a/docs/parser/pipe-posix.md b/docs/parser/pipe-posix.md index f505c473a..b6002272a 100644 --- a/docs/parser/pipe-posix.md +++ b/docs/parser/pipe-posix.md @@ -52,13 +52,13 @@ Hello, Earth! Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings
diff --git a/docs/parser/range.md b/docs/parser/range.md index d6301f5f7..1a81fb838 100644 --- a/docs/parser/range.md +++ b/docs/parser/range.md @@ -102,17 +102,17 @@ December Outputs an element from a nested structure * [`ja` (mkarray)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [list.append: `append`](../commands/append.md): +* [list.append](../commands/append.md): Add data to the end of an array -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array
diff --git a/docs/parser/scalar.md b/docs/parser/scalar.md index 7541f53f6..a4d7d983a 100644 --- a/docs/parser/scalar.md +++ b/docs/parser/scalar.md @@ -175,7 +175,7 @@ do not. Evaluate a mathematical function and assign to variable (deprecated) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/single-quote.md b/docs/parser/single-quote.md index f81a9b871..c38016bc0 100644 --- a/docs/parser/single-quote.md +++ b/docs/parser/single-quote.md @@ -48,7 +48,7 @@ bar Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/parser/subtract-by.md b/docs/parser/subtract-by.md index 9904bb6ce..bfdd0426f 100644 --- a/docs/parser/subtract-by.md +++ b/docs/parser/subtract-by.md @@ -63,7 +63,7 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/subtraction.md b/docs/parser/subtraction.md index 2c469ef85..25cf28780 100644 --- a/docs/parser/subtraction.md +++ b/docs/parser/subtraction.md @@ -78,7 +78,7 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/parser/tilde.md b/docs/parser/tilde.md index c00d37fab..d8ba89d27 100644 --- a/docs/parser/tilde.md +++ b/docs/parser/tilde.md @@ -76,7 +76,7 @@ But it cannot be expanded inside single quotes. A sophisticated yet simply way to build a JSON array * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/types/csv.md b/docs/types/csv.md index edd484758..f0c2268a4 100644 --- a/docs/types/csv.md +++ b/docs/types/csv.md @@ -80,7 +80,7 @@ use `config`) string (primitive) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [table.select: `select`](../optional/select.md): Inlining SQL into shell pipelines diff --git a/docs/types/generic.md b/docs/types/generic.md index c9810000a..d313eb027 100644 --- a/docs/types/generic.md +++ b/docs/types/generic.md @@ -40,11 +40,11 @@ executables. Floating point number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/hcl.md b/docs/types/hcl.md index 461c5e7b2..a08b6b4a6 100644 --- a/docs/types/hcl.md +++ b/docs/types/hcl.md @@ -97,15 +97,15 @@ See the HashiCorp's [documentation](https://github.com/hashicorp/hcl) for HCL sy JSON Lines * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/int.md b/docs/types/int.md index 56d9789f2..1de201cab 100644 --- a/docs/types/int.md +++ b/docs/types/int.md @@ -38,11 +38,11 @@ AMD64 or other 64bit built of Murex would see the range from Floating point number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/json.md b/docs/types/json.md index c9de3ffce..934e7f4c9 100644 --- a/docs/types/json.md +++ b/docs/types/json.md @@ -227,15 +227,15 @@ jsonl Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonc.md b/docs/types/jsonc.md index 62c793547..a48cea521 100644 --- a/docs/types/jsonc.md +++ b/docs/types/jsonc.md @@ -152,15 +152,15 @@ parser is still in beta), it is shipped as an additional data-type. Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonl.md b/docs/types/jsonl.md index fcf49f2cb..c9fbe24cb 100644 --- a/docs/types/jsonl.md +++ b/docs/types/jsonl.md @@ -163,15 +163,15 @@ cases for JSON lines. Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/mxjson.md b/docs/types/mxjson.md index 7cec1d1c3..d9fa70749 100644 --- a/docs/types/mxjson.md +++ b/docs/types/mxjson.md @@ -78,17 +78,17 @@ Any block quoted by this method will be converted to the following valid JSON: YAML Ain't Markup Language (YAML) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/num.md b/docs/types/num.md index d6b6a0416..05f63981f 100644 --- a/docs/types/num.md +++ b/docs/types/num.md @@ -29,11 +29,11 @@ numbers. Whole number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/str.md b/docs/types/str.md index 3de234e5c..7ff9048ba 100644 --- a/docs/types/str.md +++ b/docs/types/str.md @@ -40,11 +40,11 @@ This type is modelled closely on generic but is more tailored for textual Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/toml.md b/docs/types/toml.md index 98760b073..d39c2a922 100644 --- a/docs/types/toml.md +++ b/docs/types/toml.md @@ -88,11 +88,11 @@ hosts = [ JSON Lines * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/yaml.md b/docs/types/yaml.md index ae72a03cb..db89ff29a 100644 --- a/docs/types/yaml.md +++ b/docs/types/yaml.md @@ -51,11 +51,11 @@ external source packages for the shell to compile. JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index dc869a32f..9af367e4c 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -145,10 +145,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. * [`!` (not)](../commands/not-func.md): Reads the stdin and exit number from previous process and not's it's condition -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [`alias`](../commands/alias.md): - Create an alias for a command * [`and`](../commands/and.md): Returns `true` or `false` depending on whether multiple conditions are met * [`args` ](../commands/args.md): @@ -181,8 +177,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Iterate through a map or other collection of data * [`format`](../commands/format.md): Reformat one data-type into another data-type -* [`function`](../commands/function.md): - Define a function block * [`get-type`](../commands/get-type.md): Returns the data-type of a variable or pipe * [`get`](../commands/get.md): @@ -199,20 +193,14 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Returns character sequences for any key pressed (ie sent from the terminal) * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`method`](../commands/method.md): - Define a methods supported data-types * [`murex-docs`](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [`murex-parser` ](../commands/murex-parser.md): - Runs the Murex parser against a block of code * [`null`](../commands/devnull.md): null function. Similar to /dev/null * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. * [`post`](../commands/post.md): HTTP POST request with a JSON-parsable return -* [`private`](../commands/private.md): - Define a private function block * [`rand`](../commands/rand.md): Random field generator * [`return`](../commands/return.md): @@ -229,8 +217,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Murex's test framework - define tests, run tests and debug shell scripts * [`time`](../commands/time.md): Returns the execution run time of a command or block -* [`tread`](../commands/tread.md): - `read` a line of input from the user and store as a user defined *typed* variable (deprecated) * [`true`](../commands/true.md): Returns a `true` value * [`try`](../commands/try.md): @@ -249,139 +235,151 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Locate command origin * [`while`](../commands/while.md): Loop until condition false -* [escape.cli: `esccli`](../commands/esccli.md): +* [escape.cli](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html: `eschtml`](../commands/eschtml.md): +* [escape.html](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote: `escape`](../commands/escape.md): +* [escape.quote](../commands/escape.md): Escape or unescape input -* [escape.url: `escurl`](../commands/escurl.md): +* [escape.url](../commands/escurl.md): Encode or decodes text for the URL -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.files: `f`](../commands/f.md): +* [fs.files (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.glob: `g`](../commands/g.md): +* [fs.glob (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.lockfile: `lockfile`](../commands/lockfile.md): +* [fs.lockfile](../commands/lockfile.md): Create and manage lock files -* [fs.new.tmpfile: `tmp`](../commands/tmp.md): - Create a temporary file and write to it -* [fs.open.image: `open-image`](../commands/open-image.md): - Renders bitmap image data on your terminal -* [fs.open: `open`](../commands/open.md): +* [fs.open](../commands/open.md): Open a file with a preferred handler -* [fs.regex: `rx`](../commands/rx.md): +* [fs.open.image](../commands/open-image.md): + Renders bitmap image data on your terminal +* [fs.regex (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [fs.status: `pt`](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [help.man.flags: `man-get-flags` ](../commands/man-get-flags.md): +* [fs.tmpfile (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [fs.truncate (`>`)](../commands/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [help.man.flags](../commands/man-get-flags.md): Parses man page files for command line flags -* [help.man.summary: `man-summary`](../commands/man-summary.md): +* [help.man.summary](../commands/man-summary.md): Outputs a man page summary of a command -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.input: `read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.new.pipe: `pipe`](../commands/pipe.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [io.new.pipe](../commands/pipe.md): Manage Murex named pipes -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe -* [list.append: `append`](../commands/append.md): +* [io.read](../commands/read.md): + `read` a line of input from the user and store as a variable +* [io.status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [list.append](../commands/append.md): Add data to the end of an array -* [list.case: `list.case` ](../commands/list.case.md): +* [list.case](../commands/list.case.md): Changes the character case of a string or all elements in an array -* [list.join: `mjoin` ](../commands/mjoin.md): +* [list.join](../commands/mjoin.md): Joins a list or array into a single string -* [list.left: `left`](../commands/left.md): +* [list.left](../commands/left.md): Left substring every item in a list -* [list.new.str: `a` (mkarray)](../commands/a.md): - A sophisticated yet simple way to build an array or list +* [list.new.str (`a`)](../commands/a.md): + A sophisticated yet simple way to build an array or list (mkarray) * [list.new.type: `ta`](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix: `prefix`](../commands/prefix.md): +* [list.prefix](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend: `prepend`](../commands/prepend.md): +* [list.prepend](../commands/prepend.md): Add data to the start of an array -* [list.regex: `regexp`](../commands/regexp.md): +* [list.regex](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse: `mtac`](../commands/mtac.md): +* [list.reverse (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.right: `right`](../commands/right.md): +* [list.right](../commands/right.md): Right substring every item in a list -* [list.sort: `msort`](../commands/msort.md): +* [list.sort](../commands/msort.md): Sorts an array - data type agnostic -* [list.str: `match`](../commands/match.md): +* [list.str (`match`)](../commands/match.md): Match an exact value in an array -* [list.suffix: `suffix`](../commands/suffix.md): +* [list.suffix](../commands/suffix.md): Prefix a string to every item in a list * [num.round: `round`](../commands/round.md): Round a number by a user defined precision -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.exitnum: `exitnum`](../commands/exitnum.md): +* [proc.exitnum](../commands/exitnum.md): Output the exit number of the previous process -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill.all: `fid-killall`](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): +* [proc.kill.all](../commands/fid-killall.md): + Terminate _all_ running Murex functions +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.alias](../commands/alias.md): + Create an alias for a command +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.builtins.exist: `bexists`](../commands/bexists.md): +* [shell.builtins.exist](../commands/bexists.md): Check which builtins exist -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.debug: `debug`](../commands/debug.md): +* [shell.debug](../commands/debug.md): Debugging information -* [shell.history: `history`](../commands/history.md): +* [shell.function](../commands/function.md): + Define a function block +* [shell.history](../commands/history.md): Outputs murex's command history +* [shell.method](../commands/method.md): + Define a methods supported data-types * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [shell.rescan.path: `murex-update-exe-list`](../commands/murex-update-exe-list.md): +* [shell.private](../commands/private.md): + Define a private function block +* [shell.rescan.path](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.summary: `summary` ](../commands/summary.md): +* [shell.summary](../commands/summary.md): Defines a summary help text for a command -* [shell.version: `version`](../commands/version.md): +* [shell.version](../commands/version.md): Get Murex version * [str.datetime: `datetime`](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [str.split: `jsplit` ](../commands/jsplit.md): +* [str.split](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter: `alter`](../commands/alter.md): +* [struct.alter](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count: `count`](../commands/count.md): +* [struct.count](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [struct.json.pretty](../commands/pretty.md): Prettifies JSON to make it human readable -* [struct.keys: `struct-keys`](../commands/struct-keys.md): +* [struct.keys](../commands/struct-keys.md): Outputs all the keys in a structure as a file path -* [struct.new.2darray: `2darray` ](../commands/2darray.md): +* [struct.new.2darray](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map: `map`](../commands/map.md): +* [struct.new.map (`map`)](../commands/map.md): Creates a map from two data sources -* [sys.cpu.arch: `cpuarch`](../commands/cpuarch.md): +* [sys.cpu.arch](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count: `cpucount`](../commands/cpucount.md): +* [sys.cpu.count](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os: `os`](../commands/os.md): +* [sys.os](../commands/os.md): Output the auto-detected OS name -* [table.new.heading: `addheading` ](../commands/addheading.md): +* [table.add.heading](../commands/addheading.md): Adds headings to a table * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/user-guide/ansi.md b/docs/user-guide/ansi.md index 29d971cea..278e37d5e 100644 --- a/docs/user-guide/ansi.md +++ b/docs/user-guide/ansi.md @@ -228,12 +228,12 @@ it persistent. Initiates or terminates a string (variables expanded) * [`(brace quote)`](../parser/brace-quote-func.md): Write a string to the stdout without new line (deprecated) -* [io.err: `err`](../commands/err.md): +* [io.err](../commands/err.md): Print a line to the stderr -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character +* [io.out.type (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type
diff --git a/docs/user-guide/bang-prefix.md b/docs/user-guide/bang-prefix.md index bc62d9dc1..af3ba8c19 100644 --- a/docs/user-guide/bang-prefix.md +++ b/docs/user-guide/bang-prefix.md @@ -31,7 +31,7 @@ bang prefix and what the behavior of that prefix is. Returns `true` or `false` depending on whether multiple conditions are met * [`or`](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/user-guide/fileref.md b/docs/user-guide/fileref.md index ac380150b..72bde0621 100644 --- a/docs/user-guide/fileref.md +++ b/docs/user-guide/fileref.md @@ -58,11 +58,11 @@ empty Filename string. An introduction to Murex modules and packages * [`[[ Element ]]`](../parser/element.md): Outputs an element from a nested structure -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/user-guide/hint-text.md b/docs/user-guide/hint-text.md index 28f9a0bd2..35630e035 100644 --- a/docs/user-guide/hint-text.md +++ b/docs/user-guide/hint-text.md @@ -87,7 +87,7 @@ prompt: * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/user-guide/interactive-shell.md b/docs/user-guide/interactive-shell.md index 6c8b8c729..f24ab37e5 100644 --- a/docs/user-guide/interactive-shell.md +++ b/docs/user-guide/interactive-shell.md @@ -223,19 +223,19 @@ give you as much useful detail as it can. A list of all the terminal hotkeys and their uses * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command -* [`method`](../commands/method.md): - Define a methods supported data-types * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [shell.method](../commands/method.md): + Define a methods supported data-types +* [shell.runtime](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/user-guide/job-control.md b/docs/user-guide/job-control.md index c9777331c..1ed76526e 100644 --- a/docs/user-guide/job-control.md +++ b/docs/user-guide/job-control.md @@ -140,19 +140,19 @@ Task 1 * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [exec.*: `fexec` ](../commands/fexec.md): +* [exec.* (`fexec`)](../commands/fexec.md): Execute a command or function, bypassing the usual order of precedence. * [exec.file: `exec`](../commands/exec.md): Runs an executable -* [proc.bg: `bg`](../commands/bg.md): +* [jobs](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [proc.bg](../commands/bg.md): Run processes in the background -* [proc.fg: `fg`](../commands/fg.md): +* [proc.fg](../commands/fg.md): Sends a background process into the foreground -* [proc.kill: `fid-kill`](../commands/fid-kill.md): +* [proc.kill](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list: `fid-list`](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.list: `jobs`](../commands/fid-list.md): +* [proc.list](../commands/fid-list.md): Lists all running functions within the current Murex session
diff --git a/docs/user-guide/modules.md b/docs/user-guide/modules.md index 7ed7b7fe0..5f6b8537d 100644 --- a/docs/user-guide/modules.md +++ b/docs/user-guide/modules.md @@ -116,14 +116,14 @@ empty Filename string. * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where -* [`private`](../commands/private.md): - Define a private function block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager +* [shell.private](../commands/private.md): + Define a private function block
diff --git a/docs/user-guide/namedpipes.md b/docs/user-guide/namedpipes.md index a0c806a4f..1e6131a29 100644 --- a/docs/user-guide/namedpipes.md +++ b/docs/user-guide/namedpipes.md @@ -49,11 +49,11 @@ command parameter1 parameter2 parameter3 ## See Also -* [``](../commands/stdin.md): - Read the stdin belonging to the parent code block * [`test`](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [io.pipe: `` Read Named Pipe](../commands/namedpipe.md): +* [io.in (``)](../commands/stdin.md): + Read the stdin belonging to the parent code block +* [io.pipe (``)](../commands/namedpipe.md): Reads from a Murex named pipe
diff --git a/docs/user-guide/pipeline.md b/docs/user-guide/pipeline.md index ed2ce02e5..ca8efd162 100644 --- a/docs/user-guide/pipeline.md +++ b/docs/user-guide/pipeline.md @@ -81,7 +81,7 @@ document but you can read more on them in links the links below. Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [proc.bg: `bg`](../commands/bg.md): +* [proc.bg](../commands/bg.md): Run processes in the background
diff --git a/docs/user-guide/profile.md b/docs/user-guide/profile.md index a61de6796..b662c82a6 100644 --- a/docs/user-guide/profile.md +++ b/docs/user-guide/profile.md @@ -79,7 +79,7 @@ how you define that value. * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [shell.packages: `murex-package`](../commands/murex-package.md): +* [shell.packages (`murex-package`)](../commands/murex-package.md): Murex's package manager * [var.env: `export`](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/user-guide/rosetta-stone.md b/docs/user-guide/rosetta-stone.md index f9e426103..79f64f5ed 100644 --- a/docs/user-guide/rosetta-stone.md +++ b/docs/user-guide/rosetta-stone.md @@ -167,7 +167,7 @@ if you want to learn more about shell scripting in Murex. Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [fs.truncate: `>`](../command/file-truncate.md): +* [fs.truncate (`>`)](../commands/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists * [index](../parser/item-index.md): Outputs an element from an array, map or table diff --git a/docs/user-guide/scoping.md b/docs/user-guide/scoping.md index ae93e13a0..9760f237b 100644 --- a/docs/user-guide/scoping.md +++ b/docs/user-guide/scoping.md @@ -57,24 +57,24 @@ scope. Subshells also do not create a new scope either. Event driven programming for shell scripts * [`foreach`](../commands/foreach.md): Iterate through an array -* [`function`](../commands/function.md): - Define a function block * [`if`](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`private`](../commands/private.md): - Define a private function block * [`switch`](../commands/switch.md): Blocks of cascading conditionals -* [exec.include: `source`](../commands/source.md): +* [exec.include (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings +* [shell.function](../commands/function.md): + Define a function block * [shell.open: `openagent`](../commands/openagent.md): Creates a handler function for `open` +* [shell.private](../commands/private.md): + Define a private function block * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index 55b1dbe86..50e42d994 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -56,7 +56,7 @@ changing this option will not cause accidental side-effects in other functions. How scoping works within Murex * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [shell.config: `config`](../commands/config.md): +* [shell.config](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/variables/argv.md b/docs/variables/argv.md index dfae5e0d9..cdde9d49d 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -79,18 +79,18 @@ deprecated and may be removed from future releases. Expand values as an array * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope -* [`function`](../commands/function.md): - Define a function block * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`private`](../commands/private.md): - Define a private function block * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index 198a69b5e..8eecb811e 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -64,16 +64,16 @@ then variables `$1` through to `$19` (inclusive) will all be set. Array of the command name and parameters within a given scope * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope -* [`function`](../commands/function.md): - Define a function block -* [`private`](../commands/private.md): - Define a private function block * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/variables/params.md b/docs/variables/params.md index 87adb18c3..79182e848 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -67,18 +67,18 @@ This is a reserved variable so it cannot be changed. Expand values as an array * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`function`](../commands/function.md): - Define a function block * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`private`](../commands/private.md): - Define a private function block * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out: `out`](../commands/out.md): +* [io.out](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.autocomplete: `autocomplete`](../commands/autocomplete.md): +* [shell.autocomplete](../commands/autocomplete.md): Set definitions for tab-completion in the command line +* [shell.function](../commands/function.md): + Define a function block +* [shell.private](../commands/private.md): + Define a private function block * [var.set: `set`](../commands/set.md): Define a local variable and set it's value diff --git a/docs/variables/self.md b/docs/variables/self.md index 1f9657fb5..5fb879e70 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -121,12 +121,12 @@ terminal (TTY) or a pipe?) Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`function`](../commands/function.md): - Define a function block * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`string` (stringing)](../types/str.md): string (primitive) +* [shell.function](../commands/function.md): + Define a function block
diff --git a/integrations/_namespaces_any.mx b/integrations/_namespaces_any.mx index cfe75d935..f0fb1346f 100644 --- a/integrations/_namespaces_any.mx +++ b/integrations/_namespaces_any.mx @@ -24,9 +24,10 @@ alias struct.alter = alter alias struct.keys = struct-keys alias struct.new.map = map alias struct.new.2darray = 2darray +alias struct.json.pretty = pretty alias table.select = select -alias table.new.heading = addheading +alias table.add.heading = addheading alias var.set = set alias !var.set = !set @@ -43,8 +44,10 @@ alias escape.url = escurl alias !escape.url = !escurl alias escape.cli = esccli +alias io.in = read-namedpipe stdin alias io.out = out alias io.err = err +alias io.read = read alias io.pipe = read-named-pipe alias io.status = pt alias io.new.pipe = pipe @@ -56,7 +59,7 @@ alias fs.regex = rx alias !fs.regex = !rx alias fs.files = f alias fs.lockfile = lockfile -alias fs.new.tmpfile = tmp +alias fs.tmpfile = tmp alias fs.truncate = ">" alias fs.append = ">>" alias fs.open = open @@ -71,6 +74,7 @@ alias !shell.alias = !alias alias shell.function = function alias !shell.function = !function alias shell.private = private +alias shell.method = method alias shell.pipe = pipe alias !shell.pipe = !pipe alias shell.event = event From 8ac4d4065b40ada11b12149f89d94b6ef0992596 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 00:14:18 +0100 Subject: [PATCH 066/142] #860 document titles --- builtins/core/arraytools/2darray_doc.yaml | 2 +- builtins/core/arraytools/addheading_doc.yaml | 4 ++-- builtins/core/arraytools/map_doc.yaml | 2 +- builtins/core/autocomplete/autocomplete_doc.yaml | 2 +- builtins/core/config/config_doc.yaml | 2 +- builtins/core/datatools/alter_doc.yaml | 2 +- builtins/core/datatools/count_doc.yaml | 2 +- builtins/core/datatools/structkeys_doc.yaml | 2 +- builtins/core/element/element_doc.yaml | 4 ++-- builtins/core/escape/escape_doc.yaml | 8 ++++---- builtins/core/httpclient/get_doc.yaml | 2 +- builtins/core/httpclient/post_doc.yaml | 2 +- builtins/core/index/index_doc.yaml | 4 ++-- builtins/core/io/echo_doc.yaml | 6 +++--- builtins/core/io/f_doc.yaml | 2 +- builtins/core/io/file_doc.yaml | 4 ++-- builtins/core/io/g_doc.yaml | 2 +- builtins/core/io/lockfile_doc.yaml | 2 +- builtins/core/io/read_doc.yaml | 2 +- builtins/core/io/rx_doc.yaml | 2 +- builtins/core/io/tmp_doc.yaml | 2 +- builtins/core/lists/append_doc.yaml | 4 ++-- builtins/core/lists/case_doc.yaml | 2 +- builtins/core/lists/jsplit_doc.yaml | 2 +- builtins/core/lists/mjoin_doc.yaml | 2 +- builtins/core/lists/msort_doc.yaml | 2 +- builtins/core/lists/mtac_doc.yaml | 2 +- builtins/core/lists/push_pop_doc.yaml | 8 ++++---- builtins/core/lists/regexp_doc.yaml | 4 ++-- builtins/core/management/debug_doc.yaml | 2 +- builtins/core/management/fexec_doc.yaml | 2 +- builtins/core/management/functions_doc.yaml | 10 +++++----- builtins/core/management/history_doc.yaml | 2 +- builtins/core/management/shell_doc.yaml | 6 +++--- builtins/core/management/source_doc.yaml | 2 +- builtins/core/management/type_doc.yaml | 2 +- builtins/core/management/version_doc.yaml | 2 +- builtins/core/management/which_doc.yaml | 2 +- builtins/core/mkarray/array_doc.yaml | 8 ++++---- builtins/core/modules/murex-package_doc.yaml | 2 +- builtins/core/open/open_doc.yaml | 2 +- builtins/core/openimage/open-image_doc.yaml | 2 +- builtins/core/pipe/namedpipe_doc.yaml | 4 ++-- builtins/core/pipe/pipe_doc.yaml | 2 +- builtins/core/pretty/pretty_doc.yaml | 2 +- builtins/core/processes/bgfg_doc.yaml | 4 ++-- builtins/core/processes/fid-list_doc.yaml | 2 +- builtins/core/processes/kill_doc.yaml | 4 ++-- builtins/core/runtime/runtime_doc.yaml | 2 +- builtins/core/structs/andor_doc.yaml | 4 ++-- builtins/core/structs/break_doc.yaml | 6 +++--- builtins/core/structs/for_doc.yaml | 2 +- builtins/core/structs/foreach_doc.yaml | 2 +- builtins/core/structs/formap_doc.yaml | 2 +- builtins/core/structs/function_doc.yaml | 8 ++++---- builtins/core/structs/if_doc.yaml | 2 +- builtins/core/structs/switch_doc.yaml | 2 +- builtins/core/structs/try_doc.yaml | 10 +++++----- builtins/core/structs/tryerr_doc.yaml | 4 ++-- builtins/core/system/system_doc.yaml | 6 +++--- builtins/core/test/test_doc.yaml | 2 +- builtins/core/time/time_doc.yaml | 2 +- builtins/core/typemgmt/datetime_doc.yaml | 2 +- builtins/core/typemgmt/variables_doc.yaml | 11 ++++++----- 64 files changed, 108 insertions(+), 107 deletions(-) diff --git a/builtins/core/arraytools/2darray_doc.yaml b/builtins/core/arraytools/2darray_doc.yaml index 3da1c2b56..0b75d40db 100644 --- a/builtins/core/arraytools/2darray_doc.yaml +++ b/builtins/core/arraytools/2darray_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: 2darray Title: >- - struct.new.2darray + Struct: Create 2d Array CategoryID: commands Summary: >- Create a 2D JSON array from multiple input sources diff --git a/builtins/core/arraytools/addheading_doc.yaml b/builtins/core/arraytools/addheading_doc.yaml index 4241f9873..716351556 100644 --- a/builtins/core/arraytools/addheading_doc.yaml +++ b/builtins/core/arraytools/addheading_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: addheading Title: >- - table.add.heading + Table: Add Heading (`addheading`) CategoryID: commands Summary: >- Adds headings to a table @@ -21,7 +21,7 @@ Detail: Synonyms: - addheading - - table.new.heading + - table.add.heading Related: - item-index - element diff --git a/builtins/core/arraytools/map_doc.yaml b/builtins/core/arraytools/map_doc.yaml index d0cccfa82..df8e466ff 100644 --- a/builtins/core/arraytools/map_doc.yaml +++ b/builtins/core/arraytools/map_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: map Title: >- - struct.new.map (`map`) + Struct: Create Map (`map`) CategoryID: commands Summary: >- Creates a map from two data sources diff --git a/builtins/core/autocomplete/autocomplete_doc.yaml b/builtins/core/autocomplete/autocomplete_doc.yaml index 075e99241..b60f6e1c9 100644 --- a/builtins/core/autocomplete/autocomplete_doc.yaml +++ b/builtins/core/autocomplete/autocomplete_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: "autocomplete" Title: >+ - shell.autocomplete + Shell: Autocomplete CategoryID: commands Summary: >- Set definitions for tab-completion in the command line diff --git a/builtins/core/config/config_doc.yaml b/builtins/core/config/config_doc.yaml index 62c3c2539..03dfe57ee 100644 --- a/builtins/core/config/config_doc.yaml +++ b/builtins/core/config/config_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: config Title: >+ - shell.config + Shell: Config CategoryID: commands Summary: >- Query or define Murex runtime settings diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index 04a57b4d5..9777e59cb 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: alter Title: >+ - struct.alter + Struct: Alter CategoryID: commands Summary: >- Change a value within a structured data-type and pass that change along the diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index 9ef5875ac..45e246736 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: count Title: >+ - struct.count + Struct: Count CategoryID: commands Summary: >- Count items in a map, list or array diff --git a/builtins/core/datatools/structkeys_doc.yaml b/builtins/core/datatools/structkeys_doc.yaml index 7deead165..35a8fdefd 100644 --- a/builtins/core/datatools/structkeys_doc.yaml +++ b/builtins/core/datatools/structkeys_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: struct-keys Title: >+ - struct.keys + Struct: List Keys CategoryID: commands Summary: >- Outputs all the keys in a structure as a file path diff --git a/builtins/core/element/element_doc.yaml b/builtins/core/element/element_doc.yaml index a6c6ded9b..8b0143612 100644 --- a/builtins/core/element/element_doc.yaml +++ b/builtins/core/element/element_doc.yaml @@ -1,7 +1,7 @@ - DocumentID: element Title: >+ - `[[ Element ]]` - CategoryID: parser + Struct: Get Nested Element (`[[ Element ]]`) + CategoryID: commands Summary: >- Outputs an element from a nested structure Description: |- diff --git a/builtins/core/escape/escape_doc.yaml b/builtins/core/escape/escape_doc.yaml index 3df3b0664..0b416e885 100644 --- a/builtins/core/escape/escape_doc.yaml +++ b/builtins/core/escape/escape_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: escape Title: >+ - escape.quote + Escape: Quote CategoryID: commands Summary: >- Escape or unescape input @@ -51,7 +51,7 @@ - DocumentID: eschtml Title: >+ - escape.html + Escape: HTML CategoryID: commands Summary: >- Encode or decodes text for HTML @@ -110,7 +110,7 @@ - DocumentID: escurl Title: >+ - escape.url + Escape: URL CategoryID: commands Summary: >- Encode or decodes text for the URL @@ -169,7 +169,7 @@ - DocumentID: esccli Title: >+ - escape.cli + Escape: CLI str CategoryID: commands Summary: >- Escapes an array so output is valid shell code diff --git a/builtins/core/httpclient/get_doc.yaml b/builtins/core/httpclient/get_doc.yaml index 98cceabe9..a6028e3b7 100644 --- a/builtins/core/httpclient/get_doc.yaml +++ b/builtins/core/httpclient/get_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: get Title: >+ - `get` + HTTP: Get Request CategoryID: commands Summary: >- Makes a standard HTTP request and returns the result as a JSON object diff --git a/builtins/core/httpclient/post_doc.yaml b/builtins/core/httpclient/post_doc.yaml index fd0402bd8..bfd5b6b2b 100644 --- a/builtins/core/httpclient/post_doc.yaml +++ b/builtins/core/httpclient/post_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: post Title: >+ - `post` + HTTP: Post Request CategoryID: commands Summary: >- HTTP POST request with a JSON-parsable return diff --git a/builtins/core/index/index_doc.yaml b/builtins/core/index/index_doc.yaml index 7fee70cde..9a0ab6764 100644 --- a/builtins/core/index/index_doc.yaml +++ b/builtins/core/index/index_doc.yaml @@ -1,7 +1,7 @@ - DocumentID: item-index Title: >+ - `[ Index ]` - CategoryID: parser + Struct: Get Item (`[ Index ]`) + CategoryID: commands Summary: >- Outputs an element from an array, map or table Description: |- diff --git a/builtins/core/io/echo_doc.yaml b/builtins/core/io/echo_doc.yaml index 3a63ce6ad..d31a00bef 100644 --- a/builtins/core/io/echo_doc.yaml +++ b/builtins/core/io/echo_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: out Title: >+ - io.out + IO: Output String (`out`) CategoryID: commands Summary: >- Print a string to the stdout with a trailing new line character @@ -53,7 +53,7 @@ - DocumentID: tout Title: >+ - io.out.type (`tout`) + IO: Output Type (`tout`) CategoryID: commands Summary: >- Print a string to the stdout and set it's data-type @@ -144,7 +144,7 @@ - DocumentID: err Title: >+ - io.err + IO: Error String (`err`) CategoryID: commands Summary: >- Print a line to the stderr diff --git a/builtins/core/io/f_doc.yaml b/builtins/core/io/f_doc.yaml index 515bd1fff..9942fc379 100644 --- a/builtins/core/io/f_doc.yaml +++ b/builtins/core/io/f_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: f Title: >+ - fs.files (`f`) + Filesystem: List Files (`f`) CategoryID: commands Summary: >- Lists or filters file system objects (eg files) diff --git a/builtins/core/io/file_doc.yaml b/builtins/core/io/file_doc.yaml index 3cdae670c..a40591765 100644 --- a/builtins/core/io/file_doc.yaml +++ b/builtins/core/io/file_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: file-truncate Title: >+ - fs.truncate (`>`) + Filesystem: Truncate File (`>`) CategoryID: commands Summary: >- Writes stdin to disk - overwriting contents if file already exists @@ -37,7 +37,7 @@ - DocumentID: pt Title: >+ - io.status (`pt`) + IO: Get Pipe Status (`pt`) CategoryID: commands Summary: >- Pipe telemetry. Writes data-types and bytes written diff --git a/builtins/core/io/g_doc.yaml b/builtins/core/io/g_doc.yaml index 2077000ca..7d7762c1e 100644 --- a/builtins/core/io/g_doc.yaml +++ b/builtins/core/io/g_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: g Title: >+ - fs.glob (`g`) + Filesystem: Globbing (`g`) CategoryID: commands Summary: >- Glob pattern matching for file system objects (eg `*.txt`) diff --git a/builtins/core/io/lockfile_doc.yaml b/builtins/core/io/lockfile_doc.yaml index 12869d711..612828621 100644 --- a/builtins/core/io/lockfile_doc.yaml +++ b/builtins/core/io/lockfile_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: lockfile Title: >+ - fs.lockfile + Filesystem: Lock Files CategoryID: commands Summary: >- Create and manage lock files diff --git a/builtins/core/io/read_doc.yaml b/builtins/core/io/read_doc.yaml index 790111989..05ac4f5ae 100644 --- a/builtins/core/io/read_doc.yaml +++ b/builtins/core/io/read_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: read Title: >+ - io.read + IO: Read User Input (`read`) CategoryID: commands Summary: >- `read` a line of input from the user and store as a variable diff --git a/builtins/core/io/rx_doc.yaml b/builtins/core/io/rx_doc.yaml index 9425518dd..fb34691f6 100644 --- a/builtins/core/io/rx_doc.yaml +++ b/builtins/core/io/rx_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: rx Title: >+ - fs.regex (`rx`) + Filesystem: Regex Matches (`rx`) CategoryID: commands Summary: >- Regexp pattern matching for file system objects (eg `.*\\.txt`) diff --git a/builtins/core/io/tmp_doc.yaml b/builtins/core/io/tmp_doc.yaml index ef00b81e9..39b1fb414 100644 --- a/builtins/core/io/tmp_doc.yaml +++ b/builtins/core/io/tmp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: tmp Title: >+ - fs.tmpfile (`tmp`) + Filesystem: Temp Files (`tmp`) CategoryID: commands Summary: >- Create a temporary file and write to it diff --git a/builtins/core/lists/append_doc.yaml b/builtins/core/lists/append_doc.yaml index 61fd7e1b2..a7abcde5c 100644 --- a/builtins/core/lists/append_doc.yaml +++ b/builtins/core/lists/append_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: prepend Title: >- - list.prepend + List: Prepend CategoryID: commands Summary: >- Add data to the start of an array @@ -55,7 +55,7 @@ - DocumentID: append Title: >+ - list.append + List: Append CategoryID: commands Summary: >- Add data to the end of an array diff --git a/builtins/core/lists/case_doc.yaml b/builtins/core/lists/case_doc.yaml index eb771d75f..ca6bb25fa 100644 --- a/builtins/core/lists/case_doc.yaml +++ b/builtins/core/lists/case_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: list.case Title: >- - list.case + List: Change Text Case CategoryID: commands Summary: >- Changes the character case of a string or all elements in an array diff --git a/builtins/core/lists/jsplit_doc.yaml b/builtins/core/lists/jsplit_doc.yaml index 5b1f663dd..f8d2f617e 100644 --- a/builtins/core/lists/jsplit_doc.yaml +++ b/builtins/core/lists/jsplit_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: jsplit Title: >- - str.split + String: Split (`jsplit`) CategoryID: commands Summary: >- Splits stdin into a JSON array based on a regex parameter diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml index f923cb3d1..670e5baf5 100644 --- a/builtins/core/lists/mjoin_doc.yaml +++ b/builtins/core/lists/mjoin_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mjoin Title: >- - list.join + List: Join (`mjoin`) CategoryID: commands Summary: >- Joins a list or array into a single string diff --git a/builtins/core/lists/msort_doc.yaml b/builtins/core/lists/msort_doc.yaml index e67577970..61aec4b80 100644 --- a/builtins/core/lists/msort_doc.yaml +++ b/builtins/core/lists/msort_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: msort Title: >- - list.sort + List: Sort CategoryID: commands Summary: >- Sorts an array - data type agnostic diff --git a/builtins/core/lists/mtac_doc.yaml b/builtins/core/lists/mtac_doc.yaml index a5c9480d0..02e000cd3 100644 --- a/builtins/core/lists/mtac_doc.yaml +++ b/builtins/core/lists/mtac_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: mtac Title: >+ - list.reverse (`mtac`) + List: Reverse (`mtac`) CategoryID: commands Summary: >- Reverse the order of an array diff --git a/builtins/core/lists/push_pop_doc.yaml b/builtins/core/lists/push_pop_doc.yaml index 24a90928c..8af7a8074 100644 --- a/builtins/core/lists/push_pop_doc.yaml +++ b/builtins/core/lists/push_pop_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: left Title: >+ - list.left + List: Left Sub-String CategoryID: commands Summary: >- Left substring every item in a list @@ -61,7 +61,7 @@ - DocumentID: right Title: >+ - list.right + List: Right Sub-String CategoryID: commands Summary: >- Right substring every item in a list @@ -122,7 +122,7 @@ - DocumentID: prefix Title: >+ - list.prefix + List: Prefix CategoryID: commands Summary: >- Prefix a string to every item in a list @@ -167,7 +167,7 @@ - DocumentID: suffix Title: >+ - list.suffix + List: Suffix CategoryID: commands Summary: >- Prefix a string to every item in a list diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index 53770ea8f..ba2cfc5a9 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: match Title: >+ - list.str (`match`) + List: Match String (`match`) CategoryID: commands Summary: >- Match an exact value in an array @@ -86,7 +86,7 @@ - DocumentID: regexp Title: >+ - list.regex + List: Regex Pattern (`regexp`) CategoryID: commands Summary: >- Regexp tools for arrays / lists of strings diff --git a/builtins/core/management/debug_doc.yaml b/builtins/core/management/debug_doc.yaml index ab8cbf478..a791b0eba 100644 --- a/builtins/core/management/debug_doc.yaml +++ b/builtins/core/management/debug_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: debug Title: >+ - shell.debug + Shell: Debugging Mode CategoryID: commands Summary: >- Debugging information diff --git a/builtins/core/management/fexec_doc.yaml b/builtins/core/management/fexec_doc.yaml index 00cc49c2d..9b7aeee8d 100644 --- a/builtins/core/management/fexec_doc.yaml +++ b/builtins/core/management/fexec_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fexec Title: >+ - exec.* (`fexec`) + Exec: Shell Function or Builtin (`fexec`) CategoryID: commands Summary: >- Execute a command or function, bypassing the usual order of precedence. diff --git a/builtins/core/management/functions_doc.yaml b/builtins/core/management/functions_doc.yaml index 4c96d062a..2e634f404 100644 --- a/builtins/core/management/functions_doc.yaml +++ b/builtins/core/management/functions_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: exitnum Title: >+ - proc.exitnum + Processes: Get Exit Code (`exitnum`) CategoryID: commands Summary: >- Output the exit number of the previous process @@ -28,7 +28,7 @@ - DocumentID: murex-update-exe-list Title: >+ - shell.rescan.path + Shell: Re-scan $PATH CategoryID: commands Summary: >- Forces Murex to rescan $PATH looking for executables @@ -61,7 +61,7 @@ - DocumentID: man-summary Title: >+ - help.man.summary + Help: Man-Page Summary CategoryID: commands Summary: >- Outputs a man page summary of a command @@ -107,7 +107,7 @@ - DocumentID: cd Title: >+ - `cd` + Core: Change Directory CategoryID: commands Summary: >- Change (working) directory @@ -188,7 +188,7 @@ - DocumentID: bexists Title: >+ - shell.builtins.exist + Shell: Check Builtin Exists CategoryID: commands Summary: >- Check which builtins exist diff --git a/builtins/core/management/history_doc.yaml b/builtins/core/management/history_doc.yaml index 6062e7652..652a50205 100644 --- a/builtins/core/management/history_doc.yaml +++ b/builtins/core/management/history_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: history Title: >+ - shell.history + Shell: Get History CategoryID: commands Summary: >- Outputs murex's command history diff --git a/builtins/core/management/shell_doc.yaml b/builtins/core/management/shell_doc.yaml index 3391e9302..b44525a44 100644 --- a/builtins/core/management/shell_doc.yaml +++ b/builtins/core/management/shell_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: summary Title: >+ - shell.summary + Shell: Command Summary CategoryID: commands Summary: >- Defines a summary help text for a command @@ -88,7 +88,7 @@ - DocumentID: args Title: >+ - `args` + Lang: Define Function Args CategoryID: commands Summary: >- Command line flag parser for Murex shell scripting @@ -119,7 +119,7 @@ - DocumentID: man-get-flags Title: >+ - help.man.flags + Help: Man-Page Flags CategoryID: commands Summary: >- Parses man page files for command line flags diff --git a/builtins/core/management/source_doc.yaml b/builtins/core/management/source_doc.yaml index aab9d4f04..51d30ae1e 100644 --- a/builtins/core/management/source_doc.yaml +++ b/builtins/core/management/source_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: source Title: >+ - exec.include (`source`) + Shell: Include Murex Script (`source`) CategoryID: commands Summary: >- Import Murex code from another file or code block diff --git a/builtins/core/management/type_doc.yaml b/builtins/core/management/type_doc.yaml index 0fdd41f85..16dc03e77 100644 --- a/builtins/core/management/type_doc.yaml +++ b/builtins/core/management/type_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: type Title: >+ - `type` + POSIX: `type` CategoryID: commands Summary: >- Command type (function, builtin, alias, etc) diff --git a/builtins/core/management/version_doc.yaml b/builtins/core/management/version_doc.yaml index af3921bd9..aa6c10e42 100644 --- a/builtins/core/management/version_doc.yaml +++ b/builtins/core/management/version_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: version Title: >+ - shell.version + Shell: Version CategoryID: commands Summary: >- Get Murex version diff --git a/builtins/core/management/which_doc.yaml b/builtins/core/management/which_doc.yaml index 0711a333a..dfd19b1c6 100644 --- a/builtins/core/management/which_doc.yaml +++ b/builtins/core/management/which_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: which Title: >+ - `which` + POSIX: `which` CategoryID: commands Summary: >- Locate command origin diff --git a/builtins/core/mkarray/array_doc.yaml b/builtins/core/mkarray/array_doc.yaml index c67beb4fc..416e0fe77 100644 --- a/builtins/core/mkarray/array_doc.yaml +++ b/builtins/core/mkarray/array_doc.yaml @@ -1,9 +1,9 @@ - DocumentID: a Title: >+ - list.new.str (`a`) + List: Stream New List (`a`) CategoryID: commands Summary: >- - A sophisticated yet simple way to build an array or list (mkarray) + A sophisticated yet simple way to stream an array or list (mkarray) Description: |- _mkarray_, pronounced "make array" like `mkdir` (etc), is Murex's sophisticated syntax for generating arrays. Think like bash's `{1..9}` syntax: @@ -148,7 +148,7 @@ - DocumentID: ja Title: >+ - `ja` (mkarray) + List: Create Json Array (`ja`) CategoryID: commands Summary: >- A sophisticated yet simply way to build a JSON array @@ -213,7 +213,7 @@ - DocumentID: ta Title: >+ - list.new.type: `ta` + List: Create New Array (`ta`) CategoryID: commands Summary: >- A sophisticated yet simple way to build an array of a user defined data-type diff --git a/builtins/core/modules/murex-package_doc.yaml b/builtins/core/modules/murex-package_doc.yaml index 51d335153..5f831ebcb 100644 --- a/builtins/core/modules/murex-package_doc.yaml +++ b/builtins/core/modules/murex-package_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: murex-package Title: >+ - shell.packages (`murex-package`) + Shell: Package Management (`murex-package`) CategoryID: commands Summary: >- Murex's package manager diff --git a/builtins/core/open/open_doc.yaml b/builtins/core/open/open_doc.yaml index 37dcc9da1..cb8176877 100644 --- a/builtins/core/open/open_doc.yaml +++ b/builtins/core/open/open_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open Title: >+ - fs.open + Filesystem: Open File (`open`) CategoryID: commands Summary: >- Open a file with a preferred handler diff --git a/builtins/core/openimage/open-image_doc.yaml b/builtins/core/openimage/open-image_doc.yaml index 459d69e2c..a6f4963ca 100644 --- a/builtins/core/openimage/open-image_doc.yaml +++ b/builtins/core/openimage/open-image_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: open-image Title: >- - fs.open.image + Filesystem: Open Image CategoryID: commands Summary: >- Renders bitmap image data on your terminal diff --git a/builtins/core/pipe/namedpipe_doc.yaml b/builtins/core/pipe/namedpipe_doc.yaml index d627ce644..1398040d6 100644 --- a/builtins/core/pipe/namedpipe_doc.yaml +++ b/builtins/core/pipe/namedpipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: namedpipe Title: >+ - io.pipe (``) + IO: Read / Write To A Named Pipe (``) CategoryID: commands Summary: >- Reads from a Murex named pipe @@ -52,7 +52,7 @@ - DocumentID: stdin Title: >+ - io.in (``) + IO: Read From Stdin (``) CategoryID: commands Summary: >- Read the stdin belonging to the parent code block diff --git a/builtins/core/pipe/pipe_doc.yaml b/builtins/core/pipe/pipe_doc.yaml index 2bfce3fd4..705444caa 100644 --- a/builtins/core/pipe/pipe_doc.yaml +++ b/builtins/core/pipe/pipe_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pipe Title: >+ - io.new.pipe + IO: Create Named Pipe CategoryID: commands Summary: >- Manage Murex named pipes diff --git a/builtins/core/pretty/pretty_doc.yaml b/builtins/core/pretty/pretty_doc.yaml index 62be3e82b..8563ad90b 100644 --- a/builtins/core/pretty/pretty_doc.yaml +++ b/builtins/core/pretty/pretty_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: pretty Title: >+ - struct.json.pretty + Struct: Prettify JSON CategoryID: commands Summary: >- Prettifies JSON to make it human readable diff --git a/builtins/core/processes/bgfg_doc.yaml b/builtins/core/processes/bgfg_doc.yaml index 9ce1ec17c..83af4632f 100644 --- a/builtins/core/processes/bgfg_doc.yaml +++ b/builtins/core/processes/bgfg_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: bg Title: >+ - proc.bg + Processes: Background (`bg`) CategoryID: commands Summary: >- Run processes in the background @@ -44,7 +44,7 @@ - DocumentID: fg Title: >+ - proc.fg + Processes: Foreground (`fg`) CategoryID: commands Summary: >- Sends a background process into the foreground diff --git a/builtins/core/processes/fid-list_doc.yaml b/builtins/core/processes/fid-list_doc.yaml index d41ba1643..972ad5dac 100644 --- a/builtins/core/processes/fid-list_doc.yaml +++ b/builtins/core/processes/fid-list_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-list Title: >+ - proc.list + Processes: List (`fid-list`) CategoryID: commands Summary: >- Lists all running functions within the current Murex session diff --git a/builtins/core/processes/kill_doc.yaml b/builtins/core/processes/kill_doc.yaml index b7912242c..c98d84af6 100644 --- a/builtins/core/processes/kill_doc.yaml +++ b/builtins/core/processes/kill_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: fid-kill Title: >+ - proc.kill + Processes: Kill (`fid-kill`) CategoryID: commands Summary: >- Terminate a running Murex function @@ -34,7 +34,7 @@ - DocumentID: fid-killall Title: >+ - proc.kill.all + Processes: Kill All In Session (`fid-killall`) CategoryID: commands Summary: >- Terminate _all_ running Murex functions diff --git a/builtins/core/runtime/runtime_doc.yaml b/builtins/core/runtime/runtime_doc.yaml index 8a22f7162..7a42b6588 100644 --- a/builtins/core/runtime/runtime_doc.yaml +++ b/builtins/core/runtime/runtime_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: runtime Title: >+ - shell.runtime + Shell: Runtime CategoryID: commands Summary: >- Returns runtime information on the internal state of Murex diff --git a/builtins/core/structs/andor_doc.yaml b/builtins/core/structs/andor_doc.yaml index 48b91b34c..b028e6e46 100644 --- a/builtins/core/structs/andor_doc.yaml +++ b/builtins/core/structs/andor_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: and Title: >+ - `and` + Logic: And CategoryID: commands Summary: >- Returns `true` or `false` depending on whether multiple conditions are met @@ -52,7 +52,7 @@ - DocumentID: or Title: >+ - `or` + Logic: Or CategoryID: commands Summary: >- Returns `true` or `false` depending on whether one code-block out of multiple diff --git a/builtins/core/structs/break_doc.yaml b/builtins/core/structs/break_doc.yaml index 33efe96dd..707cfd880 100644 --- a/builtins/core/structs/break_doc.yaml +++ b/builtins/core/structs/break_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: return Title: >+ - `return` + Control Flow: Exit Function (`return`) CategoryID: commands Summary: >- Exits current function scope @@ -63,7 +63,7 @@ - DocumentID: break Title: >+ - `break` + Control Flow: Exit Block (`break`) CategoryID: commands Summary: >- Terminate execution of a block within your processes scope @@ -170,7 +170,7 @@ - DocumentID: continue Title: >+ - `continue` + Control Flow: Next Iteration (`continue`) CategoryID: commands Summary: >- Terminate process of a block within a caller function diff --git a/builtins/core/structs/for_doc.yaml b/builtins/core/structs/for_doc.yaml index 4e45e787a..ece44cacb 100644 --- a/builtins/core/structs/for_doc.yaml +++ b/builtins/core/structs/for_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: for Title: >+ - `for` + Control Flow: For Loop (`for`) CategoryID: commands Summary: >- A more familiar iteration loop to existing developers diff --git a/builtins/core/structs/foreach_doc.yaml b/builtins/core/structs/foreach_doc.yaml index 03e7a952d..bb99c2cca 100644 --- a/builtins/core/structs/foreach_doc.yaml +++ b/builtins/core/structs/foreach_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: foreach Title: >+ - `foreach` + Control Flow: For Each In List (`foreach`) CategoryID: commands Summary: >- Iterate through an array diff --git a/builtins/core/structs/formap_doc.yaml b/builtins/core/structs/formap_doc.yaml index 3a286e283..c48b8475c 100644 --- a/builtins/core/structs/formap_doc.yaml +++ b/builtins/core/structs/formap_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: formap Title: >+ - `formap` + Control Flow: For Each In Map (`formap`) CategoryID: commands Summary: >- Iterate through a map or other collection of data diff --git a/builtins/core/structs/function_doc.yaml b/builtins/core/structs/function_doc.yaml index 4273fad30..a6bdbb09b 100644 --- a/builtins/core/structs/function_doc.yaml +++ b/builtins/core/structs/function_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: alias Title: >+ - shell.alias + Shell: Alias Pointer CategoryID: commands Summary: >- Create an alias for a command @@ -104,7 +104,7 @@ - DocumentID: function Title: >+ - shell.function + Shell: Public Function CategoryID: commands Summary: >- Define a function block @@ -333,7 +333,7 @@ - DocumentID: private Title: >+ - shell.private + Shell: Private Function CategoryID: commands Summary: >- Define a private function block @@ -411,7 +411,7 @@ - DocumentID: method Title: >+ - shell.method + Shell: Method Relationships CategoryID: commands Summary: >- Define a methods supported data-types diff --git a/builtins/core/structs/if_doc.yaml b/builtins/core/structs/if_doc.yaml index cc764b4ca..8d2165c97 100644 --- a/builtins/core/structs/if_doc.yaml +++ b/builtins/core/structs/if_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: if Title: >+ - `if` + Control Flow: If Conditional (`if`) CategoryID: commands Summary: >- Conditional statement to execute different blocks of code depending on the diff --git a/builtins/core/structs/switch_doc.yaml b/builtins/core/structs/switch_doc.yaml index 66f130d03..455a19483 100644 --- a/builtins/core/structs/switch_doc.yaml +++ b/builtins/core/structs/switch_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: switch Title: >+ - `switch` + Control Flow: Switch Conditional (`switch`) CategoryID: commands Summary: >- Blocks of cascading conditionals diff --git a/builtins/core/structs/try_doc.yaml b/builtins/core/structs/try_doc.yaml index 17b967d25..db2817c33 100644 --- a/builtins/core/structs/try_doc.yaml +++ b/builtins/core/structs/try_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: unsafe Title: >+ - `unsafe` + Error Handling: Disable In Block (`unsafe`) CategoryID: commands Summary: >- Execute a block of code, always returning a zero exit number @@ -41,7 +41,7 @@ - DocumentID: try Title: >+ - `try` + Error Handling: Try Block (`try`) CategoryID: commands Summary: >- Handles non-zero exits inside a block of code @@ -94,7 +94,7 @@ - DocumentID: trypipe Title: >+ - `trypipe` + Error Handling: Pipe Fail (`trypipe`) CategoryID: commands Summary: >- Checks for non-zero exits of each function in a pipeline @@ -150,7 +150,7 @@ - DocumentID: catch Title: >+ - `catch` + Error Handling: Caught Error (`catch`) CategoryID: commands Summary: >- Handles the exception code raised by `try` or `trypipe` @@ -203,7 +203,7 @@ - DocumentID: runmode Title: >+ - `runmode` + Error Handling: Function / Module Defaults (`runmode`) CategoryID: commands Summary: >- Alter the scheduler's behaviour at higher scoping level diff --git a/builtins/core/structs/tryerr_doc.yaml b/builtins/core/structs/tryerr_doc.yaml index bf6e1dbd8..ed634beb0 100644 --- a/builtins/core/structs/tryerr_doc.yaml +++ b/builtins/core/structs/tryerr_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: tryerr Title: >+ - `tryerr` + Error Handling: Stderr Checking In TTY (`tryerr`) CategoryID: commands Summary: >- Handles errors inside a block of code @@ -54,7 +54,7 @@ - DocumentID: trypipeerr Title: >+ - `trypipeerr` + Error Handling: Stderr Checking In Pipes (`trypipeerr`) CategoryID: commands Summary: >- Checks state of each function in a pipeline and exits block on error diff --git a/builtins/core/system/system_doc.yaml b/builtins/core/system/system_doc.yaml index 141e6181a..5ef3a4576 100644 --- a/builtins/core/system/system_doc.yaml +++ b/builtins/core/system/system_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: os Title: >+ - sys.os + System: OS (`os`) CategoryID: commands Summary: >- Output the auto-detected OS name @@ -78,7 +78,7 @@ - DocumentID: cpuarch Title: >+ - sys.cpu.arch + System: CPU Architecture (`cpuarch`) CategoryID: commands Summary: >- Output the hosts CPU architecture @@ -106,7 +106,7 @@ - DocumentID: cpucount Title: >+ - sys.cpu.count + System: CPU Count (`cpucount`) CategoryID: commands Summary: >- Output the number of CPU cores available on your host diff --git a/builtins/core/test/test_doc.yaml b/builtins/core/test/test_doc.yaml index 2343cb39a..f980ba814 100644 --- a/builtins/core/test/test_doc.yaml +++ b/builtins/core/test/test_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: test Title: >+ - `test` + Shell: Test Suite (`test`) CategoryID: commands Summary: >- Murex's test framework - define tests, run tests and debug shell scripts diff --git a/builtins/core/time/time_doc.yaml b/builtins/core/time/time_doc.yaml index dc45f6a22..cc93c53c0 100644 --- a/builtins/core/time/time_doc.yaml +++ b/builtins/core/time/time_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: time Title: >- - `time` + Processes: Execution Time (`time`) CategoryID: commands Summary: >- Returns the execution run time of a command or block diff --git a/builtins/core/typemgmt/datetime_doc.yaml b/builtins/core/typemgmt/datetime_doc.yaml index 0aa3704c3..17c9a2565 100644 --- a/builtins/core/typemgmt/datetime_doc.yaml +++ b/builtins/core/typemgmt/datetime_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: datetime Title: >+ - str.datetime: `datetime` + String: Date And Time Conversion (`datetime`) CategoryID: commands Summary: >- A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/builtins/core/typemgmt/variables_doc.yaml b/builtins/core/typemgmt/variables_doc.yaml index 798c60fcc..b2eba0b4c 100644 --- a/builtins/core/typemgmt/variables_doc.yaml +++ b/builtins/core/typemgmt/variables_doc.yaml @@ -1,11 +1,12 @@ - DocumentID: set Title: >+ - var.set: `set` + Variable: Define (`set`) CategoryID: commands Summary: >- - Define a local variable and set it's value + Define a variable (typically local) and set it's value Description: |- - Defines, updates or deallocates a local variable. + Defines, updates or deallocates a variable. By default that variable will be + local. Usage: |- ``` -> set var_name @@ -71,7 +72,7 @@ - DocumentID: global Title: >+ - var.global: `global` + Variable: Global (`global`) CategoryID: commands Summary: >- Define a global variable and set it's value @@ -142,7 +143,7 @@ - DocumentID: export Title: >+ - var.env: `export` + Variable: Environmental Variable (`export`) CategoryID: commands Summary: >- Define an environmental variable and set it's value From 8ff829d66f17b8fce396b1be424f1a623df16d5f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 18:53:55 +0100 Subject: [PATCH 067/142] docgen: add subcats --- builtins/core/arraytools/2darray_doc.yaml | 4 +- builtins/core/arraytools/addheading_doc.yaml | 4 +- builtins/core/arraytools/map_doc.yaml | 4 +- .../core/autocomplete/autocomplete_doc.yaml | 4 +- builtins/core/config/config_doc.yaml | 5 +- builtins/core/datatools/alter_doc.yaml | 4 +- builtins/core/datatools/count_doc.yaml | 6 +- builtins/core/datatools/structkeys_doc.yaml | 4 +- builtins/core/element/element_doc.yaml | 5 +- builtins/core/escape/escape_doc.yaml | 27 +- .../core/expressions/expressions_doc.yaml | 6 +- builtins/core/httpclient/get_doc.yaml | 8 +- builtins/core/httpclient/post_doc.yaml | 4 +- builtins/core/index/index_doc.yaml | 7 +- builtins/core/io/echo_doc.yaml | 17 +- builtins/core/io/f_doc.yaml | 4 +- builtins/core/io/file_doc.yaml | 10 +- builtins/core/io/g_doc.yaml | 5 +- builtins/core/io/lockfile_doc.yaml | 4 +- builtins/core/io/read_doc.yaml | 11 +- builtins/core/io/rx_doc.yaml | 5 +- builtins/core/io/tmp_doc.yaml | 4 +- builtins/core/lists/append_doc.yaml | 8 +- builtins/core/lists/case_doc.yaml | 5 +- builtins/core/lists/jsplit_doc.yaml | 4 +- builtins/core/lists/mjoin_doc.yaml | 4 +- builtins/core/lists/msort_doc.yaml | 4 +- builtins/core/lists/mtac_doc.yaml | 4 +- builtins/core/lists/push_pop_doc.yaml | 18 +- builtins/core/lists/regexp_doc.yaml | 9 +- builtins/core/management/debug_doc.yaml | 5 +- builtins/core/management/fexec_doc.yaml | 4 +- builtins/core/management/functions_doc.yaml | 21 +- builtins/core/management/history_doc.yaml | 5 +- builtins/core/management/shell_doc.yaml | 20 +- builtins/core/management/source_doc.yaml | 6 +- builtins/core/management/type_doc.yaml | 4 +- builtins/core/management/version_doc.yaml | 5 +- builtins/core/management/which_doc.yaml | 5 +- builtins/core/mkarray/array_doc.yaml | 14 +- builtins/core/modules/murex-package_doc.yaml | 5 +- builtins/core/open/open_doc.yaml | 12 +- builtins/core/openimage/open-image_doc.yaml | 6 +- builtins/core/pipe/namedpipe_doc.yaml | 14 +- builtins/core/pipe/pipe_doc.yaml | 7 +- builtins/core/pretty/pretty_doc.yaml | 5 +- builtins/core/processes/bgfg_doc.yaml | 10 +- builtins/core/processes/fid-list_doc.yaml | 6 +- builtins/core/processes/kill_doc.yaml | 15 +- builtins/core/random/rand_doc.yaml | 5 +- builtins/core/ranges/ranges_doc.yaml | 6 +- builtins/core/runtime/runtime_doc.yaml | 4 +- builtins/core/structs/andor_doc.yaml | 10 +- builtins/core/structs/break_doc.yaml | 9 +- builtins/core/structs/for_doc.yaml | 3 +- builtins/core/structs/foreach_doc.yaml | 5 +- builtins/core/structs/formap_doc.yaml | 6 +- builtins/core/structs/function_doc.yaml | 24 +- builtins/core/structs/if_doc.yaml | 3 +- builtins/core/structs/switch_doc.yaml | 3 +- builtins/core/structs/try_doc.yaml | 15 +- builtins/core/structs/tryerr_doc.yaml | 6 +- builtins/core/structs/while_doc.yaml | 3 +- builtins/core/system/system_doc.yaml | 13 +- builtins/core/tabulate/tabulate_doc.yaml | 5 +- builtins/core/test/test_doc.yaml | 3 +- builtins/core/time/time_doc.yaml | 5 +- builtins/core/typemgmt/datetime_doc.yaml | 3 +- builtins/core/typemgmt/format_doc.yaml | 7 +- builtins/core/typemgmt/gettype_doc.yaml | 3 +- builtins/core/typemgmt/isnull_doc.yaml | 3 +- builtins/core/typemgmt/round_doc.yaml | 3 +- builtins/core/typemgmt/types_doc.yaml | 21 +- builtins/core/typemgmt/variables_doc.yaml | 15 +- builtins/docs/docs_doc.yaml | 3 +- builtins/docs/summaries.go | 1231 ++++++++--------- builtins/events/events_doc.yaml | 3 +- builtins/events/onKeyPress/keycodes_doc.yaml | 1 + .../events/onSignalReceived/signal_doc.yaml | 1 + builtins/optional/select/select_doc.yaml | 3 +- docs/apis/ReadIndex.md | 4 +- docs/apis/ReadNotIndex.md | 4 +- docs/blog/reading_lists.md | 16 +- docs/blog/split_personalities.md | 4 +- docs/changelog/v2.0.md | 14 +- docs/changelog/v2.1.md | 20 +- docs/changelog/v2.10.md | 32 +- docs/changelog/v2.11.md | 24 +- docs/changelog/v2.2.md | 4 +- docs/changelog/v2.3.md | 8 +- docs/changelog/v2.4.md | 32 +- docs/changelog/v2.5.md | 32 +- docs/changelog/v2.6.md | 12 +- docs/changelog/v2.7.md | 16 +- docs/changelog/v2.8.md | 12 +- docs/changelog/v2.9.md | 40 +- docs/changelog/v3.0.md | 44 +- docs/changelog/v3.1.md | 2 +- docs/changelog/v4.0.md | 8 +- docs/changelog/v4.2.md | 34 +- docs/changelog/v4.3.md | 8 +- docs/changelog/v4.4.md | 32 +- docs/changelog/v5.0.md | 24 +- docs/changelog/v5.1.md | 2 +- docs/changelog/v5.2.md | 16 +- docs/changelog/v5.3.md | 14 +- docs/changelog/v6.0.md | 14 +- docs/changelog/v6.1.md | 32 +- docs/changelog/v6.2.md | 12 +- docs/commands/2darray.md | 39 +- docs/commands/README.md | 593 +++++--- docs/commands/a.md | 31 +- docs/commands/addheading.md | 39 +- docs/commands/alias.md | 42 +- docs/commands/alter.md | 29 +- docs/commands/and.md | 26 +- docs/commands/append.md | 42 +- docs/commands/args.md | 2 +- docs/commands/autocomplete.md | 35 +- docs/commands/bexists.md | 8 +- docs/commands/bg.md | 21 +- docs/commands/break.md | 26 +- docs/commands/cast.md | 14 +- docs/commands/catch.md | 30 +- docs/commands/cd.md | 6 +- docs/commands/config.md | 44 +- docs/commands/continue.md | 24 +- docs/commands/count.md | 41 +- docs/commands/cpuarch.md | 6 +- docs/commands/cpucount.md | 6 +- docs/commands/datetime.md | 8 +- docs/commands/debug.md | 9 +- docs/commands/devnull.md | 8 +- docs/commands/die.md | 6 +- docs/commands/err.md | 39 +- docs/commands/escape.md | 10 +- docs/commands/esccli.md | 21 +- docs/commands/eschtml.md | 22 +- docs/commands/escurl.md | 20 +- docs/commands/event.md | 14 +- docs/commands/exec.md | 38 +- docs/commands/exit.md | 8 +- docs/commands/exitnum.md | 9 +- docs/commands/export.md | 14 +- docs/commands/expr.md | 10 +- docs/commands/f.md | 11 +- docs/commands/false.md | 16 +- docs/commands/fexec.md | 42 +- docs/commands/fg.md | 23 +- docs/commands/fid-kill.md | 37 +- docs/commands/fid-killall.md | 40 +- docs/commands/fid-list.md | 44 +- docs/commands/for.md | 26 +- docs/commands/foreach.md | 52 +- docs/commands/formap.md | 26 +- docs/commands/format.md | 10 +- docs/commands/function.md | 56 +- docs/commands/g.md | 14 +- docs/commands/get-type.md | 26 +- docs/commands/get.md | 14 +- docs/commands/getfile.md | 12 +- docs/commands/global.md | 24 +- docs/commands/history.md | 7 +- docs/commands/if.md | 34 +- docs/commands/is-null.md | 14 +- docs/commands/ja.md | 28 +- docs/commands/jsplit.md | 38 +- docs/commands/key-code.md | 4 +- docs/commands/left.md | 28 +- docs/commands/let.md | 24 +- docs/commands/list.case.md | 2 +- docs/commands/lockfile.md | 9 +- docs/commands/man-get-flags.md | 11 +- docs/commands/man-summary.md | 12 +- docs/commands/map.md | 33 +- docs/commands/match.md | 46 +- docs/commands/method.md | 23 +- docs/commands/mjoin.md | 6 +- docs/commands/msort.md | 34 +- docs/commands/mtac.md | 44 +- docs/commands/murex-docs.md | 30 +- docs/commands/murex-package.md | 23 +- docs/commands/murex-parser.md | 8 +- docs/commands/murex-update-exe-list.md | 9 +- docs/commands/not-func.md | 14 +- docs/commands/open-image.md | 7 +- docs/commands/open.md | 35 +- docs/commands/openagent.md | 12 +- docs/commands/or.md | 28 +- docs/commands/os.md | 6 +- docs/commands/out.md | 33 +- docs/commands/pipe.md | 30 +- docs/commands/post.md | 14 +- docs/commands/prefix.md | 28 +- docs/commands/prepend.md | 40 +- docs/commands/pretty.md | 11 +- docs/commands/private.md | 45 +- docs/commands/pt.md | 17 +- docs/commands/rand.md | 8 +- docs/commands/read.md | 27 +- docs/commands/regexp.md | 48 +- docs/commands/return.md | 22 +- docs/commands/right.md | 28 +- docs/commands/round.md | 2 +- docs/commands/runmode.md | 50 +- docs/commands/runtime.md | 82 +- docs/commands/rx.md | 16 +- docs/commands/set.md | 33 +- docs/commands/signal.md | 8 +- docs/commands/source.md | 35 +- docs/commands/struct-keys.md | 15 +- docs/commands/suffix.md | 28 +- docs/commands/summary.md | 30 +- docs/commands/switch.md | 42 +- docs/commands/ta.md | 27 +- docs/commands/tabulate.md | 14 +- docs/commands/test.md | 6 +- docs/commands/time.md | 10 +- docs/commands/tmp.md | 15 +- docs/commands/tout.md | 19 +- docs/commands/tread.md | 26 +- docs/commands/true.md | 16 +- docs/commands/try.md | 34 +- docs/commands/tryerr.md | 34 +- docs/commands/trypipe.md | 34 +- docs/commands/trypipeerr.md | 34 +- docs/commands/type.md | 22 +- docs/commands/unsafe.md | 34 +- docs/commands/version.md | 27 +- docs/commands/which.md | 22 +- docs/commands/while.md | 26 +- docs/events/oncommandcompletion.md | 26 +- docs/events/onfilesystemchange.md | 4 +- docs/events/onkeypress.md | 4 +- docs/events/onpreview.md | 12 +- docs/events/onprompt.md | 4 +- docs/events/onsecondselapsed.md | 4 +- docs/integrations/chatgpt.md | 8 +- docs/integrations/cheatsh.md | 8 +- docs/integrations/direnv.md | 4 +- docs/integrations/iterm2.md | 8 +- docs/integrations/kitty.md | 8 +- docs/integrations/make.md | 4 +- docs/integrations/man-pages.md | 8 +- docs/integrations/spellcheck.md | 20 +- docs/integrations/terminology.md | 6 +- docs/integrations/yarn.md | 4 +- docs/mkarray/character.md | 24 +- docs/mkarray/date.md | 32 +- docs/mkarray/decimal.md | 24 +- docs/mkarray/non-decimal.md | 20 +- docs/mkarray/special.md | 28 +- docs/optional/README.md | 6 +- docs/optional/base64.md | 16 +- docs/optional/bz2.md | 16 +- docs/optional/gz.md | 16 +- docs/optional/qr.md | 4 +- docs/optional/select.md | 6 +- docs/optional/sleep.md | 8 +- docs/parser/README.md | 18 +- docs/parser/add-with.md | 8 +- docs/parser/addition.md | 8 +- docs/parser/array.md | 12 +- docs/parser/assign-or-merge.md | 12 +- docs/parser/brace-quote-func.md | 20 +- docs/parser/brace-quote.md | 8 +- docs/parser/c-style-fun.md | 12 +- docs/parser/create-array.md | 12 +- docs/parser/curly-brace.md | 16 +- docs/parser/divide-by.md | 8 +- docs/parser/division.md | 8 +- docs/parser/double-quote.md | 8 +- docs/parser/element.md | 22 +- docs/parser/elvis.md | 16 +- docs/parser/equ.md | 28 +- docs/parser/expr-inlined.md | 4 +- docs/parser/file-append.md | 16 +- docs/{commands => parser}/file-truncate.md | 19 +- docs/parser/item-index.md | 22 +- docs/parser/lambda.md | 24 +- docs/parser/logical-and.md | 16 +- docs/parser/logical-or.md | 16 +- docs/parser/multiplication.md | 8 +- docs/parser/multiply-by.md | 8 +- docs/{commands => parser}/namedpipe.md | 21 +- docs/parser/null-coalescing.md | 20 +- docs/parser/pipe-arrow.md | 16 +- docs/parser/pipe-err.md | 16 +- docs/parser/pipe-generic.md | 12 +- docs/parser/pipe-posix.md | 16 +- docs/parser/range.md | 30 +- docs/parser/scalar.md | 12 +- docs/parser/single-quote.md | 8 +- docs/{commands => parser}/stdin.md | 23 +- docs/parser/subtract-by.md | 8 +- docs/parser/subtraction.md | 8 +- docs/parser/tilde.md | 12 +- docs/types/commonlog.md | 12 +- docs/types/csv.md | 20 +- docs/types/generic.md | 16 +- docs/types/hcl.md | 20 +- docs/types/int.md | 16 +- docs/types/json.md | 20 +- docs/types/jsonc.md | 28 +- docs/types/jsonl.md | 28 +- docs/types/mxjson.md | 32 +- docs/types/num.md | 16 +- docs/types/str.md | 20 +- docs/types/toml.md | 16 +- docs/types/yaml.md | 16 +- docs/user-guide/README.md | 462 ++++--- docs/user-guide/ansi.md | 12 +- docs/user-guide/bang-prefix.md | 18 +- docs/user-guide/fileref.md | 12 +- docs/user-guide/hint-text.md | 2 +- docs/user-guide/interactive-shell.md | 16 +- docs/user-guide/job-control.md | 26 +- docs/user-guide/modules.md | 10 +- docs/user-guide/namedpipes.md | 10 +- docs/user-guide/pipeline.md | 4 +- docs/user-guide/profile.md | 6 +- docs/user-guide/reserved-vars.md | 12 +- docs/user-guide/rosetta-stone.md | 24 +- docs/user-guide/schedulers.md | 24 +- docs/user-guide/scoping.md | 40 +- docs/user-guide/strict-types.md | 4 +- docs/variables/argv.md | 20 +- docs/variables/columns.md | 4 +- docs/variables/hostname.md | 4 +- docs/variables/meta-values.md | 10 +- docs/variables/murex_exe.md | 4 +- docs/variables/numeric.md | 20 +- docs/variables/params.md | 20 +- docs/variables/pwd.md | 8 +- docs/variables/pwdhist.md | 8 +- docs/variables/self.md | 4 +- docs/variables/shell.md | 4 +- gen/commands-md-cat.tmpl | 14 +- gen/docgen.yaml | 68 +- integrations/_namespaces_any.mx | 72 - utils/docgen/api/category.go | 105 +- utils/docgen/api/document.go | 33 + utils/docgen/api/functions.go | 12 + utils/docgen/api/unmarshaller.go | 6 +- utils/docgen/main.go | 2 +- 345 files changed, 4152 insertions(+), 3883 deletions(-) rename docs/{commands => parser}/file-truncate.md (82%) rename docs/{commands => parser}/namedpipe.md (87%) rename docs/{commands => parser}/stdin.md (90%) diff --git a/builtins/core/arraytools/2darray_doc.yaml b/builtins/core/arraytools/2darray_doc.yaml index 0b75d40db..574c47830 100644 --- a/builtins/core/arraytools/2darray_doc.yaml +++ b/builtins/core/arraytools/2darray_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: 2darray Title: >- - Struct: Create 2d Array + Create 2d Array (`2darray`) CategoryID: commands + SubCategoryIDs: [ commands.struct ] Summary: >- Create a 2D JSON array from multiple input sources Description: |- @@ -87,7 +88,6 @@ `2darray` can have as many or as few code blocks as you wish. Synonyms: - 2darray - - struct.new.2darray Related: - prepend - append diff --git a/builtins/core/arraytools/addheading_doc.yaml b/builtins/core/arraytools/addheading_doc.yaml index 716351556..6db34fb50 100644 --- a/builtins/core/arraytools/addheading_doc.yaml +++ b/builtins/core/arraytools/addheading_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: addheading Title: >- - Table: Add Heading (`addheading`) + Add Heading (`addheading`) CategoryID: commands + SubCategoryIDs: [ commands.table ] Summary: >- Adds headings to a table Description: |- @@ -21,7 +22,6 @@ Detail: Synonyms: - addheading - - table.add.heading Related: - item-index - element diff --git a/builtins/core/arraytools/map_doc.yaml b/builtins/core/arraytools/map_doc.yaml index df8e466ff..eaff112f6 100644 --- a/builtins/core/arraytools/map_doc.yaml +++ b/builtins/core/arraytools/map_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: map Title: >- - Struct: Create Map (`map`) + Create Map (`map`) CategoryID: commands + SubCategoryIDs: [ commands.struct ] Summary: >- Creates a map from two data sources Description: |- @@ -24,7 +25,6 @@ Detail: Synonyms: - map - - struct.new.map Related: - prepend - append diff --git a/builtins/core/autocomplete/autocomplete_doc.yaml b/builtins/core/autocomplete/autocomplete_doc.yaml index b60f6e1c9..0dc629663 100644 --- a/builtins/core/autocomplete/autocomplete_doc.yaml +++ b/builtins/core/autocomplete/autocomplete_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: "autocomplete" Title: >+ - Shell: Autocomplete + Tab Autocompletion (`autocomplete`) CategoryID: commands + SubCategoryIDs: [ commands.shell ] Summary: >- Set definitions for tab-completion in the command line Description: |- @@ -28,7 +29,6 @@ set: define a new autocompletion schema Synonyms: - autocomplete - - shell.autocomplete Related: - config - private diff --git a/builtins/core/config/config_doc.yaml b/builtins/core/config/config_doc.yaml index 03dfe57ee..eaadc1722 100644 --- a/builtins/core/config/config_doc.yaml +++ b/builtins/core/config/config_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: config Title: >+ - Shell: Config + Shell Configuration And Settings (`config`) CategoryID: commands + SubCategoryIDs: [ commands.shell ] Summary: >- Query or define Murex runtime settings Description: |- @@ -115,8 +116,6 @@ Synonyms: - config - "!config" - - shell.config - - "!shell.config" Related: - runtime - open diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index 9777e59cb..1a87ac845 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: alter Title: >+ - Struct: Alter + Alter Data Structure (`alter`) CategoryID: commands + SubCategoryIDs: [ commands.struct ] Summary: >- Change a value within a structured data-type and pass that change along the pipeline without altering the original source input @@ -169,7 +170,6 @@ Synonyms: - alter - "~>" - - struct.alter Related: - item-index - element diff --git a/builtins/core/datatools/count_doc.yaml b/builtins/core/datatools/count_doc.yaml index 45e246736..b8b118eb7 100644 --- a/builtins/core/datatools/count_doc.yaml +++ b/builtins/core/datatools/count_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: count Title: >+ - Struct: Count + Count (`count`) CategoryID: commands + SubCategoryIDs: + - commands.list + - commands.struct Summary: >- Count items in a map, list or array Description: |- @@ -132,7 +135,6 @@ Synonyms: - count - len - - struct.count Related: - prepend - append diff --git a/builtins/core/datatools/structkeys_doc.yaml b/builtins/core/datatools/structkeys_doc.yaml index 35a8fdefd..ce43d5c5f 100644 --- a/builtins/core/datatools/structkeys_doc.yaml +++ b/builtins/core/datatools/structkeys_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: struct-keys Title: >+ - Struct: List Keys + Print Map / Structure Keys (`struct-keys`) CategoryID: commands + SubCategoryIDs: [ commands.struct ] Summary: >- Outputs all the keys in a structure as a file path Description: |- @@ -149,7 +150,6 @@ Detail: Synonyms: - struct-keys - - struct.keys Related: - set - item-index diff --git a/builtins/core/element/element_doc.yaml b/builtins/core/element/element_doc.yaml index 8b0143612..d233ac695 100644 --- a/builtins/core/element/element_doc.yaml +++ b/builtins/core/element/element_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: element Title: >+ - Struct: Get Nested Element (`[[ Element ]]`) - CategoryID: commands + Get Nested Element (`[[ Element ]]`) + CategoryID: parser + SubCategoryIDs: [ commands.struct ] Summary: >- Outputs an element from a nested structure Description: |- diff --git a/builtins/core/escape/escape_doc.yaml b/builtins/core/escape/escape_doc.yaml index 0b416e885..e57978068 100644 --- a/builtins/core/escape/escape_doc.yaml +++ b/builtins/core/escape/escape_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: escape Title: >+ - Escape: Quote + Quote String (`escape`) CategoryID: commands + SubCategoryIDs: + - commands.esc + - commands.str Summary: >- Escape or unescape input Description: |- @@ -40,8 +43,6 @@ Synonyms: - escape - "!escape" - - "escape.quote" - - "!escape.quote" Related: - esccli - eschtml @@ -51,8 +52,11 @@ - DocumentID: eschtml Title: >+ - Escape: HTML + Escape HTML (`eschtml`) CategoryID: commands + SubCategoryIDs: + - commands.esc + - commands.str Summary: >- Encode or decodes text for HTML Description: |- @@ -96,8 +100,6 @@ Synonyms: - eschtml - "!eschtml" - - "escape.html" - - "!escape.html" Related: - esccli - escape @@ -110,8 +112,11 @@ - DocumentID: escurl Title: >+ - Escape: URL + Escape URL (`escurl`) CategoryID: commands + SubCategoryIDs: + - commands.esc + - commands.str Summary: >- Encode or decodes text for the URL Description: |- @@ -155,8 +160,6 @@ Synonyms: - escurl - "!escurl" - - "escape.url" - - "!escape.url" Related: - esccli - escape @@ -169,8 +172,11 @@ - DocumentID: esccli Title: >+ - Escape: CLI str + Escape Command Line String (`esccli`) CategoryID: commands + SubCategoryIDs: + - commands.esc + - commands.str Summary: >- Escapes an array so output is valid shell code Description: |- @@ -210,7 +216,6 @@ Detail: Synonyms: - "esccli" - - "escape.cli" Related: - alias - out diff --git a/builtins/core/expressions/expressions_doc.yaml b/builtins/core/expressions/expressions_doc.yaml index 1ea508333..8c1d586e6 100644 --- a/builtins/core/expressions/expressions_doc.yaml +++ b/builtins/core/expressions/expressions_doc.yaml @@ -2,6 +2,10 @@ Title: >+ `expr` CategoryID: commands + SubCategoryIDs: + - commands.num + - commands.lang + - commands.posix Summary: >- Expressions: mathematical, string comparisons, logical operators Description: |- @@ -15,7 +19,7 @@ # idiomatic expressions 1 + 2 - # non-idiotmatic expressions + # non-idiomatic expressions expr 1 + 2 ``` diff --git a/builtins/core/httpclient/get_doc.yaml b/builtins/core/httpclient/get_doc.yaml index a6028e3b7..27988ce72 100644 --- a/builtins/core/httpclient/get_doc.yaml +++ b/builtins/core/httpclient/get_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: get Title: >+ - HTTP: Get Request + Get Request (`get`) CategoryID: commands + SubCategoryIDs: + - commands.http Summary: >- Makes a standard HTTP request and returns the result as a JSON object Description: |- @@ -77,8 +79,10 @@ - DocumentID: getfile Title: >+ - `getfile` + Download File (`getfile`) CategoryID: commands + SubCategoryIDs: + - commands.http Summary: >- Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. diff --git a/builtins/core/httpclient/post_doc.yaml b/builtins/core/httpclient/post_doc.yaml index bfd5b6b2b..b331aa9b7 100644 --- a/builtins/core/httpclient/post_doc.yaml +++ b/builtins/core/httpclient/post_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: post Title: >+ - HTTP: Post Request + Post Request (`post`) CategoryID: commands + SubCategoryIDs: + - commands.http Summary: >- HTTP POST request with a JSON-parsable return Description: |- diff --git a/builtins/core/index/index_doc.yaml b/builtins/core/index/index_doc.yaml index 9a0ab6764..ba0d9be86 100644 --- a/builtins/core/index/index_doc.yaml +++ b/builtins/core/index/index_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: item-index Title: >+ - Struct: Get Item (`[ Index ]`) - CategoryID: commands + Get Item (`[ Index ]`) + CategoryID: parser + SubCategoryIDs: + - commands.struct + - commands.list Summary: >- Outputs an element from an array, map or table Description: |- diff --git a/builtins/core/io/echo_doc.yaml b/builtins/core/io/echo_doc.yaml index d31a00bef..4dbf187df 100644 --- a/builtins/core/io/echo_doc.yaml +++ b/builtins/core/io/echo_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: out Title: >+ - IO: Output String (`out`) + Output String (`out`) CategoryID: commands + SubCategoryIDs: + - commands.io + - commands.posix Summary: >- Print a string to the stdout with a trailing new line character Description: |- @@ -20,7 +23,7 @@ ### echo - For compatibility with other shells, `echo` is also supported: + For compatibility with other shells (and POSIX), `echo` is also supported: ``` » echo Hello, World! @@ -35,7 +38,6 @@ `out` supports ANSI constants. Synonyms: - out - - io.out - echo Related: - tout @@ -53,8 +55,9 @@ - DocumentID: tout Title: >+ - IO: Output Type (`tout`) + Output With Type Annotation (`tout`) CategoryID: commands + SubCategoryIDs: [ commands.io ] Summary: >- Print a string to the stdout and set it's data-type Description: |- @@ -78,7 +81,6 @@ Unlike `out`, `tout` does not append a carriage return / line feed. Synonyms: - tout - - io.out.type Related: - out - err @@ -94,6 +96,7 @@ Title: >+ `(brace quote)` CategoryID: parser + SubCategoryIDs: [ commands.io ] Summary: >- Write a string to the stdout without new line (deprecated) Description: |- @@ -144,8 +147,9 @@ - DocumentID: err Title: >+ - IO: Error String (`err`) + Error String (`err`) CategoryID: commands + SubCategoryIDs: [ commands.io ] Summary: >- Print a line to the stderr Description: |- @@ -189,7 +193,6 @@ `err` supports ANSI constants. Synonyms: - err - - io.err Related: - tout - out diff --git a/builtins/core/io/f_doc.yaml b/builtins/core/io/f_doc.yaml index 9942fc379..7cffc2232 100644 --- a/builtins/core/io/f_doc.yaml +++ b/builtins/core/io/f_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: f Title: >+ - Filesystem: List Files (`f`) + List Filesystem Objects (`f`) CategoryID: commands + SubCategoryIDs: [ commands.fs ] Summary: >- Lists or filters file system objects (eg files) Description: |- @@ -83,7 +84,6 @@ any matches from the `+` flags. Synonyms: - f - - fs.files Related: - g - rx diff --git a/builtins/core/io/file_doc.yaml b/builtins/core/io/file_doc.yaml index a40591765..0e4797025 100644 --- a/builtins/core/io/file_doc.yaml +++ b/builtins/core/io/file_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: file-truncate Title: >+ - Filesystem: Truncate File (`>`) - CategoryID: commands + Truncate File (`>`) + CategoryID: parser + SubCategoryIDs: [ commands.fs ] Summary: >- Writes stdin to disk - overwriting contents if file already exists Description: |- @@ -20,7 +21,6 @@ Detail: Synonyms: - ">" - - fs.truncate - "|>" - "fwrite" Related: @@ -37,8 +37,9 @@ - DocumentID: pt Title: >+ - IO: Get Pipe Status (`pt`) + Get Pipe Status (`pt`) CategoryID: commands + SubCategoryIDs: [ commands.io ] Summary: >- Pipe telemetry. Writes data-types and bytes written Description: |- @@ -58,7 +59,6 @@ Detail: Synonyms: - pt - - fs.status Related: - file-truncate - file-append diff --git a/builtins/core/io/g_doc.yaml b/builtins/core/io/g_doc.yaml index 7d7762c1e..85082f97b 100644 --- a/builtins/core/io/g_doc.yaml +++ b/builtins/core/io/g_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: g Title: >+ - Filesystem: Globbing (`g`) + Globbing (`g`) CategoryID: commands + SubCategoryIDs: [ commands.fs ] Summary: >- Glob pattern matching for file system objects (eg `*.txt`) Description: |- @@ -125,8 +126,6 @@ Synonyms: - g - "!g" - - fs.glob - - "!fs.glob" Related: - rx - f diff --git a/builtins/core/io/lockfile_doc.yaml b/builtins/core/io/lockfile_doc.yaml index 612828621..b38598bf0 100644 --- a/builtins/core/io/lockfile_doc.yaml +++ b/builtins/core/io/lockfile_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: lockfile Title: >+ - Filesystem: Lock Files + Lock Files (`lockfile`) CategoryID: commands + SubCategoryIDs: [ commands.fs ] Summary: >- Create and manage lock files Description: |- @@ -47,7 +48,6 @@ Detail: Synonyms: - lockfile - - fs.lockfile Related: - out - bg diff --git a/builtins/core/io/read_doc.yaml b/builtins/core/io/read_doc.yaml index 05ac4f5ae..ce55c8ca1 100644 --- a/builtins/core/io/read_doc.yaml +++ b/builtins/core/io/read_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: read Title: >+ - IO: Read User Input (`read`) + Read User Input (`read`) CategoryID: commands + SubCategoryIDs: + - commands.io + - commands.posix Summary: >- `read` a line of input from the user and store as a variable Description: |- @@ -74,7 +77,6 @@ --mask: "Optional password mask, for reading secrets" Synonyms: - read - - io.input Related: - tout - err @@ -89,8 +91,9 @@ - DocumentID: tread Title: >+ - `tread` - CategoryID: deprecated + Read With Type (`tread`) (removed 7.x) + CategoryID: commands + SubCategoryIDs: [ commands.io ] Summary: >- `read` a line of input from the user and store as a user defined *typed* variable (deprecated) Description: |- diff --git a/builtins/core/io/rx_doc.yaml b/builtins/core/io/rx_doc.yaml index fb34691f6..ae7cb0ca2 100644 --- a/builtins/core/io/rx_doc.yaml +++ b/builtins/core/io/rx_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: rx Title: >+ - Filesystem: Regex Matches (`rx`) + Regex Matches (`rx`) CategoryID: commands + SubCategoryIDs: [ commands.fs ] Summary: >- Regexp pattern matching for file system objects (eg `.*\\.txt`) Description: |- @@ -107,8 +108,6 @@ Synonyms: - rx - "!rx" - - fs.regex - - "!fs.regex" Related: - g - f diff --git a/builtins/core/io/tmp_doc.yaml b/builtins/core/io/tmp_doc.yaml index 39b1fb414..5b4a83566 100644 --- a/builtins/core/io/tmp_doc.yaml +++ b/builtins/core/io/tmp_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: tmp Title: >+ - Filesystem: Temp Files (`tmp`) + Create Temporary File (`tmp`) CategoryID: commands + SubCategoryIDs: [ commands.fs ] Summary: >- Create a temporary file and write to it Description: |- @@ -41,7 +42,6 @@ `$TMPDIR` on macOS). Synonyms: - tmp - - fs.new.tmpfile Related: - open - file-truncate diff --git a/builtins/core/lists/append_doc.yaml b/builtins/core/lists/append_doc.yaml index a7abcde5c..1162e189c 100644 --- a/builtins/core/lists/append_doc.yaml +++ b/builtins/core/lists/append_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: prepend Title: >- - List: Prepend + Prepend To List (`prepend`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Add data to the start of an array Description: |- @@ -55,8 +57,10 @@ - DocumentID: append Title: >+ - List: Append + Append To List (`append`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Add data to the end of an array Description: |- diff --git a/builtins/core/lists/case_doc.yaml b/builtins/core/lists/case_doc.yaml index ca6bb25fa..b0bd02635 100644 --- a/builtins/core/lists/case_doc.yaml +++ b/builtins/core/lists/case_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: list.case Title: >- - List: Change Text Case + Change Text Case (`list.case`) CategoryID: commands + SubCategoryIDs: + - commands.list + - commands.str Summary: >- Changes the character case of a string or all elements in an array Description: |- diff --git a/builtins/core/lists/jsplit_doc.yaml b/builtins/core/lists/jsplit_doc.yaml index f8d2f617e..5b27fa397 100644 --- a/builtins/core/lists/jsplit_doc.yaml +++ b/builtins/core/lists/jsplit_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: jsplit Title: >- - String: Split (`jsplit`) + Split String (`jsplit`) CategoryID: commands + SubCategoryIDs: + - commands.str Summary: >- Splits stdin into a JSON array based on a regex parameter Description: |- diff --git a/builtins/core/lists/mjoin_doc.yaml b/builtins/core/lists/mjoin_doc.yaml index 670e5baf5..34257d1b2 100644 --- a/builtins/core/lists/mjoin_doc.yaml +++ b/builtins/core/lists/mjoin_doc.yaml @@ -1,6 +1,8 @@ - DocumentID: mjoin Title: >- - List: Join (`mjoin`) + Join Array To String (`mjoin`) + SubCategoryIDs: + - commands.list CategoryID: commands Summary: >- Joins a list or array into a single string diff --git a/builtins/core/lists/msort_doc.yaml b/builtins/core/lists/msort_doc.yaml index 61aec4b80..46fc64b32 100644 --- a/builtins/core/lists/msort_doc.yaml +++ b/builtins/core/lists/msort_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: msort Title: >- - List: Sort + Sort Array (`msort`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Sorts an array - data type agnostic Description: |- diff --git a/builtins/core/lists/mtac_doc.yaml b/builtins/core/lists/mtac_doc.yaml index 02e000cd3..470909ff8 100644 --- a/builtins/core/lists/mtac_doc.yaml +++ b/builtins/core/lists/mtac_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: mtac Title: >+ - List: Reverse (`mtac`) + Reverse Array (`mtac`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Reverse the order of an array Description: |- diff --git a/builtins/core/lists/push_pop_doc.yaml b/builtins/core/lists/push_pop_doc.yaml index 8af7a8074..6c61d8e9b 100644 --- a/builtins/core/lists/push_pop_doc.yaml +++ b/builtins/core/lists/push_pop_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: left Title: >+ - List: Left Sub-String + Left Sub-String (`left`) CategoryID: commands + SubCategoryIDs: + - commands.list + - commands.str Summary: >- Left substring every item in a list Description: |- @@ -61,8 +64,11 @@ - DocumentID: right Title: >+ - List: Right Sub-String + Right Sub-String (`right`) CategoryID: commands + SubCategoryIDs: + - commands.list + - commands.str Summary: >- Right substring every item in a list Description: |- @@ -122,8 +128,10 @@ - DocumentID: prefix Title: >+ - List: Prefix + Add Prefix (`prefix`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Prefix a string to every item in a list Description: |- @@ -167,8 +175,10 @@ - DocumentID: suffix Title: >+ - List: Suffix + Add Suffix (`suffix`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Prefix a string to every item in a list Description: |- diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index ba2cfc5a9..17dcea3cb 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: match Title: >+ - List: Match String (`match`) + Match String (`match`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Match an exact value in an array Description: |- @@ -86,8 +88,11 @@ - DocumentID: regexp Title: >+ - List: Regex Pattern (`regexp`) + Regex Operations (`regexp`) CategoryID: commands + SubCategoryIDs: + - commands.list + - commands.str Summary: >- Regexp tools for arrays / lists of strings Description: |- diff --git a/builtins/core/management/debug_doc.yaml b/builtins/core/management/debug_doc.yaml index a791b0eba..f553290ab 100644 --- a/builtins/core/management/debug_doc.yaml +++ b/builtins/core/management/debug_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: debug Title: >+ - Shell: Debugging Mode + Debugging Mode (`debug`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Debugging information Description: |- @@ -185,7 +187,6 @@ ``` Synonyms: - debug - - shell.debug Related: - runtime - test \ No newline at end of file diff --git a/builtins/core/management/fexec_doc.yaml b/builtins/core/management/fexec_doc.yaml index 9b7aeee8d..e6e2bd3ef 100644 --- a/builtins/core/management/fexec_doc.yaml +++ b/builtins/core/management/fexec_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: fexec Title: >+ - Exec: Shell Function or Builtin (`fexec`) + Execute Shell Function or Builtin (`fexec`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Execute a command or function, bypassing the usual order of precedence. Description: |- diff --git a/builtins/core/management/functions_doc.yaml b/builtins/core/management/functions_doc.yaml index 2e634f404..81fca5ce4 100644 --- a/builtins/core/management/functions_doc.yaml +++ b/builtins/core/management/functions_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: exitnum Title: >+ - Processes: Get Exit Code (`exitnum`) + Get Exit Code (`exitnum`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- Output the exit number of the previous process Description: |- @@ -19,7 +21,6 @@ Detail: Synonyms: - exitnum - - proc.exitnum Related: - runtime - test @@ -28,7 +29,9 @@ - DocumentID: murex-update-exe-list Title: >+ - Shell: Re-scan $PATH + Re-Scan $PATH For Executables + SubCategoryIDs: + - commands.shell CategoryID: commands Summary: >- Forces Murex to rescan $PATH looking for executables @@ -51,7 +54,6 @@ invoked for command name completion via the REPL shell. Synonyms: - murex-update-exe-list - - shell.rescan.path Related: - os - cpuarch @@ -61,8 +63,10 @@ - DocumentID: man-summary Title: >+ - Help: Man-Page Summary + Man-Page Summary (`man-summary`) CategoryID: commands + SubCategoryIDs: + - commands.help Summary: >- Outputs a man page summary of a command Description: |- @@ -107,8 +111,10 @@ - DocumentID: cd Title: >+ - Core: Change Directory + Change Directory (`cd`) CategoryID: commands + SubCategoryIDs: + - commands.posix Summary: >- Change (working) directory Description: |- @@ -188,8 +194,9 @@ - DocumentID: bexists Title: >+ - Shell: Check Builtin Exists + Check Builtin Exists (`bexists`) CategoryID: commands + SubCategoryIDs: [ commands.proc ] Summary: >- Check which builtins exist Description: |- diff --git a/builtins/core/management/history_doc.yaml b/builtins/core/management/history_doc.yaml index 652a50205..3c0e18283 100644 --- a/builtins/core/management/history_doc.yaml +++ b/builtins/core/management/history_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: history Title: >+ - Shell: Get History + Command Line History (`history`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Outputs murex's command history Description: |- @@ -36,7 +38,6 @@ The history file is typically located on disk in a file called `~/.murex.history`. Synonyms: - history - - shell.history Related: - config - runtime diff --git a/builtins/core/management/shell_doc.yaml b/builtins/core/management/shell_doc.yaml index b44525a44..afcbbc7ae 100644 --- a/builtins/core/management/shell_doc.yaml +++ b/builtins/core/management/shell_doc.yaml @@ -1,6 +1,9 @@ - DocumentID: summary Title: >+ - Shell: Command Summary + Set Command Summary Hint (`summary`) + SubCategoryIDs: + - commands.shell + - commands.help CategoryID: commands Summary: >- Defines a summary help text for a command @@ -43,8 +46,6 @@ Synonyms: - summary - "!summary" - - shell.summary - - "!shell.summary" Related: - config - runtime @@ -59,8 +60,8 @@ - DocumentID: murex-parser Title: >+ - `murex-parser` - CategoryID: deprecated + `murex-parser` + CategoryID: commands Summary: >- Runs the Murex parser against a block of code Description: |- @@ -88,8 +89,10 @@ - DocumentID: args Title: >+ - Lang: Define Function Args + Define Function Arguments (`args`) CategoryID: commands + SubCategoryIDs: + - commands.lang Summary: >- Command line flag parser for Murex shell scripting Description: |- @@ -119,8 +122,10 @@ - DocumentID: man-get-flags Title: >+ - Help: Man-Page Flags + Parse Man-Page For Flags (`man-get-flags`) CategoryID: commands + SubCategoryIDs: + - commands.help Summary: >- Parses man page files for command line flags Description: |- @@ -165,7 +170,6 @@ requirement is that flags are hyphen prefixed, eg `--flag`. Synonyms: - man-get-flags - - help.man.flags Related: - murex-docs - summary diff --git a/builtins/core/management/source_doc.yaml b/builtins/core/management/source_doc.yaml index 51d30ae1e..db78a1aca 100644 --- a/builtins/core/management/source_doc.yaml +++ b/builtins/core/management/source_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: source Title: >+ - Shell: Include Murex Script (`source`) + Include / Evaluate Murex Code (`source`) CategoryID: commands + SubCategoryIDs: + - commands.proc + - commands.shell Summary: >- Import Murex code from another file or code block Description: |- @@ -54,7 +57,6 @@ Synonyms: - source - "." - - exec.include Related: - config - runtime diff --git a/builtins/core/management/type_doc.yaml b/builtins/core/management/type_doc.yaml index 16dc03e77..dfb232c0f 100644 --- a/builtins/core/management/type_doc.yaml +++ b/builtins/core/management/type_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: type Title: >+ - POSIX: `type` + Display Command Type (`type`) CategoryID: commands + SubCategoryIDs: + - commands.posix Summary: >- Command type (function, builtin, alias, etc) Description: |- diff --git a/builtins/core/management/version_doc.yaml b/builtins/core/management/version_doc.yaml index aa6c10e42..2c7cf1f2c 100644 --- a/builtins/core/management/version_doc.yaml +++ b/builtins/core/management/version_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: version Title: >+ - Shell: Version + Murex Version (`version`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Get Murex version Description: |- @@ -39,7 +41,6 @@ Detail: Synonyms: - version - - shell.version Related: - config - runtime diff --git a/builtins/core/management/which_doc.yaml b/builtins/core/management/which_doc.yaml index dfd19b1c6..693524a34 100644 --- a/builtins/core/management/which_doc.yaml +++ b/builtins/core/management/which_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: which Title: >+ - POSIX: `which` + Location Of Command (`which`) CategoryID: commands + SubCategoryIDs: + - commands.proc + - commands.posix Summary: >- Locate command origin Description: |- diff --git a/builtins/core/mkarray/array_doc.yaml b/builtins/core/mkarray/array_doc.yaml index 416e0fe77..a5341c3e4 100644 --- a/builtins/core/mkarray/array_doc.yaml +++ b/builtins/core/mkarray/array_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: a Title: >+ - List: Stream New List (`a`) + Stream New List (`a`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- A sophisticated yet simple way to stream an array or list (mkarray) Description: |- @@ -133,7 +135,6 @@ Synonyms: - a - mkarray - - list.new.str Related: - create-array - range @@ -148,8 +149,10 @@ - DocumentID: ja Title: >+ - List: Create Json Array (`ja`) + Create JSON Array (`ja`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- A sophisticated yet simply way to build a JSON array Description: |- @@ -213,8 +216,10 @@ - DocumentID: ta Title: >+ - List: Create New Array (`ta`) + Create New Array (`ta`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- A sophisticated yet simple way to build an array of a user defined data-type Description: |- @@ -262,7 +267,6 @@ `ta`'s supported features. Synonyms: - ta - - list.new.type Related: - create-array - range diff --git a/builtins/core/modules/murex-package_doc.yaml b/builtins/core/modules/murex-package_doc.yaml index 5f831ebcb..adfff308c 100644 --- a/builtins/core/modules/murex-package_doc.yaml +++ b/builtins/core/modules/murex-package_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: murex-package Title: >+ - Shell: Package Management (`murex-package`) + Murex Package Management (`murex-package`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Murex's package manager Description: |- @@ -91,7 +93,6 @@ `runtime --modules`. Synonyms: - murex-package - - shell.packages Related: - runtime - config diff --git a/builtins/core/open/open_doc.yaml b/builtins/core/open/open_doc.yaml index cb8176877..3a0ba76ef 100644 --- a/builtins/core/open/open_doc.yaml +++ b/builtins/core/open/open_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: open Title: >+ - Filesystem: Open File (`open`) + Open File (`open`) CategoryID: commands + SubCategoryIDs: + - commands.fs + - commands.http Summary: >- Open a file with a preferred handler Description: |- @@ -156,7 +159,6 @@ ``` Synonyms: - open - - fs.open Related: - openagent - fexec @@ -172,8 +174,10 @@ - DocumentID: openagent Title: >+ - shell.open: `openagent` + Define Handlers For "`open`" (`openagent`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Creates a handler function for `open` Description: |- @@ -207,8 +211,6 @@ Synonyms: - openagent - "!openagent" - - shell.open - - "!shell.open" Related: - open - fexec diff --git a/builtins/core/openimage/open-image_doc.yaml b/builtins/core/openimage/open-image_doc.yaml index a6f4963ca..b645a0b62 100644 --- a/builtins/core/openimage/open-image_doc.yaml +++ b/builtins/core/openimage/open-image_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: open-image Title: >- - Filesystem: Open Image + Render Image In Terminal (`open-image`) CategoryID: commands + SubCategoryIDs: + - commands.io + - commands.fs Summary: >- Renders bitmap image data on your terminal Description: |- @@ -30,7 +33,6 @@ `open-image` will fail if stdout is not a TTY. Synonyms: - open-image - - fs.open.image Related: - qr - open diff --git a/builtins/core/pipe/namedpipe_doc.yaml b/builtins/core/pipe/namedpipe_doc.yaml index 1398040d6..d7a7fccbc 100644 --- a/builtins/core/pipe/namedpipe_doc.yaml +++ b/builtins/core/pipe/namedpipe_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: namedpipe Title: >+ - IO: Read / Write To A Named Pipe (``) - CategoryID: commands + Read / Write To A Named Pipe (``) + CategoryID: parser + SubCategoryIDs: + - commands.io Summary: >- Reads from a Murex named pipe Description: |- @@ -39,7 +41,6 @@ - "(murex named pipe)" - "<>" - read-named-pipe - - io.pipe Related: - pipe - stdin @@ -52,8 +53,10 @@ - DocumentID: stdin Title: >+ - IO: Read From Stdin (``) - CategoryID: commands + Read From Stdin (``) + CategoryID: parser + SubCategoryIDs: + - commands.io Summary: >- Read the stdin belonging to the parent code block Description: |- @@ -105,7 +108,6 @@ {{ include "gen/includes/named-pipes.inc.md" }} Synonyms: - "" - - io.in Related: - pipe - namedpipe diff --git a/builtins/core/pipe/pipe_doc.yaml b/builtins/core/pipe/pipe_doc.yaml index 705444caa..7e660638e 100644 --- a/builtins/core/pipe/pipe_doc.yaml +++ b/builtins/core/pipe/pipe_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: pipe Title: >+ - IO: Create Named Pipe + Create Named Pipe (`pipe`) CategoryID: commands + SubCategoryIDs: + - commands.io + - commands.shell Summary: >- Manage Murex named pipes Description: |- @@ -46,8 +49,6 @@ Synonyms: - pipe - "!pipe" - - io.new.pipe - - "!io.new.pipe" Related: - namedpipe - stdin diff --git a/builtins/core/pretty/pretty_doc.yaml b/builtins/core/pretty/pretty_doc.yaml index 8563ad90b..5a84dfbb6 100644 --- a/builtins/core/pretty/pretty_doc.yaml +++ b/builtins/core/pretty/pretty_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: pretty Title: >+ - Struct: Prettify JSON + Prettify JSON CategoryID: commands + SubCategoryIDs: + - commands.str Summary: >- Prettifies JSON to make it human readable Description: |- @@ -30,7 +32,6 @@ Detail: Synonyms: - pretty - - struct.json.pretty Related: - tout - out diff --git a/builtins/core/processes/bgfg_doc.yaml b/builtins/core/processes/bgfg_doc.yaml index 83af4632f..bdb775269 100644 --- a/builtins/core/processes/bgfg_doc.yaml +++ b/builtins/core/processes/bgfg_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: bg Title: >+ - Processes: Background (`bg`) + Background Process (`bg`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- Run processes in the background Description: |- @@ -31,7 +33,6 @@ cross platform while `bg int` currently does not work on Windows nor Plan 9. Synonyms: - bg - - proc.bg Related: - fid-list - fid-kill @@ -44,8 +45,10 @@ - DocumentID: fg Title: >+ - Processes: Foreground (`fg`) + Foreground Process (`fg`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- Sends a background process into the foreground Description: |- @@ -63,7 +66,6 @@ for Windows (due to the kernel not supporting the right signals) nor Plan 9. Synonyms: - fg - - proc.fg Related: - fid-list - fid-kill diff --git a/builtins/core/processes/fid-list_doc.yaml b/builtins/core/processes/fid-list_doc.yaml index 972ad5dac..5b6cecee3 100644 --- a/builtins/core/processes/fid-list_doc.yaml +++ b/builtins/core/processes/fid-list_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: fid-list Title: >+ - Processes: List (`fid-list`) + Display Running Functions (`fid-list`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- Lists all running functions within the current Murex session Description: |- @@ -54,8 +56,6 @@ Synonyms: - fid-list - jobs - - proc.list - - proc.jobs Related: - fid-kill - fid-killall diff --git a/builtins/core/processes/kill_doc.yaml b/builtins/core/processes/kill_doc.yaml index c98d84af6..ad32232c4 100644 --- a/builtins/core/processes/kill_doc.yaml +++ b/builtins/core/processes/kill_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: fid-kill Title: >+ - Processes: Kill (`fid-kill`) + Kill Function (`fid-kill`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- Terminate a running Murex function Description: |- @@ -17,7 +19,6 @@ {{ include "gen/includes/fid-kill.inc.md" }} Synonyms: - fid-kill - - proc.kill Related: - fid-list - fid-killall @@ -34,12 +35,15 @@ - DocumentID: fid-killall Title: >+ - Processes: Kill All In Session (`fid-killall`) + Kill All In Session (`fid-killall`) CategoryID: commands + SubCategoryIDs: + - commands.proc Summary: >- - Terminate _all_ running Murex functions + Terminate all running Murex functions in current session Description: |- - `fid-killall` will terminate _all_ running Murex functions. + `fid-killall` will terminate **all** processes and Murex functions in the + current session. Usage: |- ``` fid-killall @@ -52,7 +56,6 @@ {{ include "gen/includes/fid-kill.inc.md" }} Synonyms: - fid-killall - - proc.kill.all Related: - fid-list - fid-kill diff --git a/builtins/core/random/rand_doc.yaml b/builtins/core/random/rand_doc.yaml index eca4bc82a..3639f54a8 100644 --- a/builtins/core/random/rand_doc.yaml +++ b/builtins/core/random/rand_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: rand Title: >+ - `rand` + Generate Random Sequence (`rand`) CategoryID: commands + SubCategoryIDs: + - commands.str + - commands.num Summary: >- Random field generator Description: |- diff --git a/builtins/core/ranges/ranges_doc.yaml b/builtins/core/ranges/ranges_doc.yaml index fea586126..e673825b0 100644 --- a/builtins/core/ranges/ranges_doc.yaml +++ b/builtins/core/ranges/ranges_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: range Title: >- - `[ ..Range ]` + Filter By Range `[ ..Range ]` CategoryID: parser + SubCategoryIDs: + - commands.list Summary: >- Outputs a ranged subset of data from stdin Description: |- @@ -76,7 +78,7 @@ b: removes blank (empty) lines from source t: trims whitespace from source 8: handles backspace characters (char 8) instead of treating it like a printable character - Detail: |- + Detail: Synonyms: - "@[" Related: diff --git a/builtins/core/runtime/runtime_doc.yaml b/builtins/core/runtime/runtime_doc.yaml index 7a42b6588..504686bb7 100644 --- a/builtins/core/runtime/runtime_doc.yaml +++ b/builtins/core/runtime/runtime_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: runtime Title: >+ - Shell: Runtime + Shell Runtime (`runtime`) CategoryID: commands + SubCategoryIDs: + - commands.shell Summary: >- Returns runtime information on the internal state of Murex Description: |- diff --git a/builtins/core/structs/andor_doc.yaml b/builtins/core/structs/andor_doc.yaml index b028e6e46..081c35022 100644 --- a/builtins/core/structs/andor_doc.yaml +++ b/builtins/core/structs/andor_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: and Title: >+ - Logic: And + Logic And Statements (`and`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Returns `true` or `false` depending on whether multiple conditions are met Description: |- @@ -40,6 +41,8 @@ - and - "!and" Related: + - logical-and + - logical-or - or - if - try @@ -52,8 +55,9 @@ - DocumentID: or Title: >+ - Logic: Or + Logic Or Statements (`or`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. @@ -93,6 +97,8 @@ - or - "!or" Related: + - logical-or + - logical-and - and - if - try diff --git a/builtins/core/structs/break_doc.yaml b/builtins/core/structs/break_doc.yaml index 707cfd880..216aeebd5 100644 --- a/builtins/core/structs/break_doc.yaml +++ b/builtins/core/structs/break_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: return Title: >+ - Control Flow: Exit Function (`return`) + Exit Function (`return`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Exits current function scope Description: |- @@ -63,8 +64,9 @@ - DocumentID: break Title: >+ - Control Flow: Exit Block (`break`) + Exit Block (`break`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Terminate execution of a block within your processes scope Description: |- @@ -170,8 +172,9 @@ - DocumentID: continue Title: >+ - Control Flow: Next Iteration (`continue`) + Next Iteration (`continue`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Terminate process of a block within a caller function Description: |- diff --git a/builtins/core/structs/for_doc.yaml b/builtins/core/structs/for_doc.yaml index ece44cacb..90ad35758 100644 --- a/builtins/core/structs/for_doc.yaml +++ b/builtins/core/structs/for_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: for Title: >+ - Control Flow: For Loop (`for`) + For Loop (`for`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- A more familiar iteration loop to existing developers Description: |- diff --git a/builtins/core/structs/foreach_doc.yaml b/builtins/core/structs/foreach_doc.yaml index bb99c2cca..ba2a7d38a 100644 --- a/builtins/core/structs/foreach_doc.yaml +++ b/builtins/core/structs/foreach_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: foreach Title: >+ - Control Flow: For Each In List (`foreach`) + For Each In List (`foreach`) CategoryID: commands + SubCategoryIDs: + - commands.lang + - commands.list Summary: >- Iterate through an array Description: |- diff --git a/builtins/core/structs/formap_doc.yaml b/builtins/core/structs/formap_doc.yaml index c48b8475c..c730c5ec0 100644 --- a/builtins/core/structs/formap_doc.yaml +++ b/builtins/core/structs/formap_doc.yaml @@ -1,7 +1,11 @@ - DocumentID: formap Title: >+ - Control Flow: For Each In Map (`formap`) + For Each In Map (`formap`) CategoryID: commands + SubCategoryIDs: + - commands.lang + - commands.table + - commands.struct Summary: >- Iterate through a map or other collection of data Description: |- diff --git a/builtins/core/structs/function_doc.yaml b/builtins/core/structs/function_doc.yaml index a6bdbb09b..0db650ccd 100644 --- a/builtins/core/structs/function_doc.yaml +++ b/builtins/core/structs/function_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: alias Title: >+ - Shell: Alias Pointer + Alias Pointer (`alias`) CategoryID: commands + SubCategoryIDs: + - commands.shell + - commands.posix Summary: >- Create an alias for a command Description: |- @@ -85,8 +88,6 @@ Synonyms: - alias - "!alias" - - shell.alias - - "!shell.alias" Related: - function - private @@ -104,8 +105,11 @@ - DocumentID: function Title: >+ - Shell: Public Function + Public Function (`function`) CategoryID: commands + SubCategoryIDs: + - commands.lang + - commands.shell Summary: >- Define a function block Description: |- @@ -310,8 +314,6 @@ Synonyms: - function - "!function" - - shell.function - - "!shell.function" Related: - args - alias @@ -333,8 +335,11 @@ - DocumentID: private Title: >+ - Shell: Private Function + Private Function (`private`) CategoryID: commands + SubCategoryIDs: + - commands.lang + - commands.shell Summary: >- Define a private function block Description: |- @@ -392,7 +397,6 @@ {{ include "gen/includes/order-of-precedence.inc.md" }} Synonyms: - private - - shell.private Related: - function - alias @@ -411,8 +415,9 @@ - DocumentID: method Title: >+ - Shell: Method Relationships + Define Method Relationships (`method`) CategoryID: commands + SubCategoryIDs: [ commands.shell ] Summary: >- Define a methods supported data-types Description: |- @@ -441,7 +446,6 @@ ``` Synonyms: - method - - shell.method Related: - function - alias diff --git a/builtins/core/structs/if_doc.yaml b/builtins/core/structs/if_doc.yaml index 8d2165c97..e7017605c 100644 --- a/builtins/core/structs/if_doc.yaml +++ b/builtins/core/structs/if_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: if Title: >+ - Control Flow: If Conditional (`if`) + If Conditional (`if`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Conditional statement to execute different blocks of code depending on the result of the condition diff --git a/builtins/core/structs/switch_doc.yaml b/builtins/core/structs/switch_doc.yaml index 455a19483..13201de46 100644 --- a/builtins/core/structs/switch_doc.yaml +++ b/builtins/core/structs/switch_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: switch Title: >+ - Control Flow: Switch Conditional (`switch`) + Switch Conditional (`switch`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Blocks of cascading conditionals Description: |- diff --git a/builtins/core/structs/try_doc.yaml b/builtins/core/structs/try_doc.yaml index db2817c33..aafdc508f 100644 --- a/builtins/core/structs/try_doc.yaml +++ b/builtins/core/structs/try_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: unsafe Title: >+ - Error Handling: Disable In Block (`unsafe`) + Disable Error Handling In Block (`unsafe`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Execute a block of code, always returning a zero exit number Description: |- @@ -41,8 +42,9 @@ - DocumentID: try Title: >+ - Error Handling: Try Block (`try`) + Try Block (`try`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Handles non-zero exits inside a block of code Description: |- @@ -94,8 +96,9 @@ - DocumentID: trypipe Title: >+ - Error Handling: Pipe Fail (`trypipe`) + Pipe Fail (`trypipe`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Checks for non-zero exits of each function in a pipeline Description: |- @@ -150,8 +153,9 @@ - DocumentID: catch Title: >+ - Error Handling: Caught Error (`catch`) + Caught Error Block (`catch`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Handles the exception code raised by `try` or `trypipe` Description: |- @@ -203,8 +207,9 @@ - DocumentID: runmode Title: >+ - Error Handling: Function / Module Defaults (`runmode`) + Function / Module Defaults (`runmode`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Alter the scheduler's behaviour at higher scoping level Description: |- diff --git a/builtins/core/structs/tryerr_doc.yaml b/builtins/core/structs/tryerr_doc.yaml index ed634beb0..f3a554887 100644 --- a/builtins/core/structs/tryerr_doc.yaml +++ b/builtins/core/structs/tryerr_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: tryerr Title: >+ - Error Handling: Stderr Checking In TTY (`tryerr`) + Stderr Checking In TTY (`tryerr`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Handles errors inside a block of code Description: |- @@ -54,8 +55,9 @@ - DocumentID: trypipeerr Title: >+ - Error Handling: Stderr Checking In Pipes (`trypipeerr`) + Stderr Checking In Pipes (`trypipeerr`) CategoryID: commands + SubCategoryIDs: [ commands.err ] Summary: >- Checks state of each function in a pipeline and exits block on error Description: |- diff --git a/builtins/core/structs/while_doc.yaml b/builtins/core/structs/while_doc.yaml index 67aca156a..0a0324ff9 100644 --- a/builtins/core/structs/while_doc.yaml +++ b/builtins/core/structs/while_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: while Title: >+ - `while` + Loop While (`while`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Loop until condition false Description: |- diff --git a/builtins/core/system/system_doc.yaml b/builtins/core/system/system_doc.yaml index 5ef3a4576..2393955d7 100644 --- a/builtins/core/system/system_doc.yaml +++ b/builtins/core/system/system_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: os Title: >+ - System: OS (`os`) + Operating System (`os`) CategoryID: commands + SubCategoryIDs: [ commands.sys ] Summary: >- Output the auto-detected OS name Description: |- @@ -66,7 +67,7 @@ parameter when run on Plan 9. If you want to include Plan 9 in the check then please write it as `os posix plan9`. Flags: - Detail: |- + Detail: Synonyms: - os - sys.os @@ -78,8 +79,9 @@ - DocumentID: cpuarch Title: >+ - System: CPU Architecture (`cpuarch`) + CPU Architecture (`cpuarch`) CategoryID: commands + SubCategoryIDs: [ commands.sys ] Summary: >- Output the hosts CPU architecture Description: |- @@ -94,7 +96,7 @@ amd64 ``` Flags: - Detail: |- + Detail: Synonyms: - cpuarch - sys.cpu.arch @@ -106,8 +108,9 @@ - DocumentID: cpucount Title: >+ - System: CPU Count (`cpucount`) + CPU Count (`cpucount`) CategoryID: commands + SubCategoryIDs: [ commands.sys ] Summary: >- Output the number of CPU cores available on your host Description: |- diff --git a/builtins/core/tabulate/tabulate_doc.yaml b/builtins/core/tabulate/tabulate_doc.yaml index ad8aaeb50..f3d801761 100644 --- a/builtins/core/tabulate/tabulate_doc.yaml +++ b/builtins/core/tabulate/tabulate_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: tabulate Title: >+ - `tabulate` + Transformation Tools (`tabulate`) CategoryID: commands + SubCategoryIDs: + - commands.struct + - commands.table Summary: >- Table transformation tools Description: |- diff --git a/builtins/core/test/test_doc.yaml b/builtins/core/test/test_doc.yaml index f980ba814..1b356bfaf 100644 --- a/builtins/core/test/test_doc.yaml +++ b/builtins/core/test/test_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: test Title: >+ - Shell: Test Suite (`test`) + Shell Script Tests (`test`) CategoryID: commands + SubCategoryIDs: [ commands.shell ] Summary: >- Murex's test framework - define tests, run tests and debug shell scripts Description: |- diff --git a/builtins/core/time/time_doc.yaml b/builtins/core/time/time_doc.yaml index cc93c53c0..ff3ca2389 100644 --- a/builtins/core/time/time_doc.yaml +++ b/builtins/core/time/time_doc.yaml @@ -1,7 +1,10 @@ - DocumentID: time Title: >- - Processes: Execution Time (`time`) + Processes Execution Time (`time`) CategoryID: commands + SubCategoryIDs: + - commands.posix + - commands.proc Summary: >- Returns the execution run time of a command or block Description: |- diff --git a/builtins/core/typemgmt/datetime_doc.yaml b/builtins/core/typemgmt/datetime_doc.yaml index 17c9a2565..1e0ae1e4f 100644 --- a/builtins/core/typemgmt/datetime_doc.yaml +++ b/builtins/core/typemgmt/datetime_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: datetime Title: >+ - String: Date And Time Conversion (`datetime`) + Date And Time Conversion (`datetime`) CategoryID: commands + SubCategoryIDs: [ commands.str ] Summary: >- A date and/or time conversion tool (like `printf` but for date and time values) Description: |- diff --git a/builtins/core/typemgmt/format_doc.yaml b/builtins/core/typemgmt/format_doc.yaml index 0b098bbb8..31c04fd2d 100644 --- a/builtins/core/typemgmt/format_doc.yaml +++ b/builtins/core/typemgmt/format_doc.yaml @@ -1,7 +1,12 @@ - DocumentID: format Title: >+ - `format` + Reformat Data type (`format`) CategoryID: commands + SubCategoryIDs: + - commands.str + - commands.list + - commands.struct + - commands.table Summary: >- Reformat one data-type into another data-type Description: |- diff --git a/builtins/core/typemgmt/gettype_doc.yaml b/builtins/core/typemgmt/gettype_doc.yaml index af9925156..c869c86c3 100644 --- a/builtins/core/typemgmt/gettype_doc.yaml +++ b/builtins/core/typemgmt/gettype_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: get-type Title: >+ - `get-type` + Get Data Type (`get-type`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Returns the data-type of a variable or pipe Description: |- diff --git a/builtins/core/typemgmt/isnull_doc.yaml b/builtins/core/typemgmt/isnull_doc.yaml index ca0b58654..b6a600a03 100644 --- a/builtins/core/typemgmt/isnull_doc.yaml +++ b/builtins/core/typemgmt/isnull_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: is-null Title: >+ - `is-null` + Is Value Null (`is-null`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Checks if a variable is null or undefined Description: |- diff --git a/builtins/core/typemgmt/round_doc.yaml b/builtins/core/typemgmt/round_doc.yaml index 1d16959f3..c3c18f82b 100644 --- a/builtins/core/typemgmt/round_doc.yaml +++ b/builtins/core/typemgmt/round_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: round Title: >+ - num.round: `round` + Round Number (`round`) CategoryID: commands + SubCategoryIDs: [ commands.num ] Summary: >- Round a number by a user defined precision Description: |- diff --git a/builtins/core/typemgmt/types_doc.yaml b/builtins/core/typemgmt/types_doc.yaml index 2a7c725bc..5dd1f3a66 100644 --- a/builtins/core/typemgmt/types_doc.yaml +++ b/builtins/core/typemgmt/types_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: exec Title: >+ - exec.file: `exec` + Execute External Command (`exec`) CategoryID: commands + SubCategoryIDs: [ commands.proc ] Summary: >- Runs an executable Description: |- @@ -111,8 +112,9 @@ - DocumentID: exit Title: >+ - `exit` + Exit Murex (`exit`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Exit murex Description: |- @@ -146,8 +148,9 @@ - DocumentID: devnull Title: >+ - `null` + Null (`null`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- null function. Similar to /dev/null Description: |- @@ -180,8 +183,9 @@ - DocumentID: "true" Title: >+ - `true` + True (`true`) CategoryID: commands + SubCategoryIDs: [ commands.posix ] Summary: >- Returns a `true` value Description: |- @@ -222,8 +226,9 @@ - DocumentID: "false" Title: >+ - `false` + False (`false`) CategoryID: commands + SubCategoryIDs: [ commands.posix ] Summary: >- Returns a `false` value Description: |- @@ -264,8 +269,9 @@ - DocumentID: not-func Title: >+ - `!` (not) + Not (`!`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Reads the stdin and exit number from previous process and not's it's condition Description: |- @@ -304,8 +310,9 @@ - DocumentID: cast Title: >+ - `cast` + Define Type (`cast`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Alters the data-type of the previous function without altering its output Description: |- diff --git a/builtins/core/typemgmt/variables_doc.yaml b/builtins/core/typemgmt/variables_doc.yaml index b2eba0b4c..73bb1d17d 100644 --- a/builtins/core/typemgmt/variables_doc.yaml +++ b/builtins/core/typemgmt/variables_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: set Title: >+ - Variable: Define (`set`) + Define Variable (`set`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Define a variable (typically local) and set it's value Description: |- @@ -54,8 +55,6 @@ Synonyms: - set - "!set" - - var.set - - "!var.set" Related: - is-null - null-coalescing @@ -72,8 +71,9 @@ - DocumentID: global Title: >+ - Variable: Global (`global`) + Define Global (`global`) CategoryID: commands + SubCategoryIDs: [ commands.lang ] Summary: >- Define a global variable and set it's value Description: |- @@ -126,8 +126,6 @@ Synonyms: - global - "!global" - - var.global - - "!var.global" Related: - set - is-null @@ -143,8 +141,9 @@ - DocumentID: export Title: >+ - Variable: Environmental Variable (`export`) + Define Environmental Variable (`export`) CategoryID: commands + SubCategoryIDs: [ commands.sys ] Summary: >- Define an environmental variable and set it's value Description: |- @@ -223,4 +222,4 @@ - global - brace-quote - scoping - - reserved-vars + - reserved-vars \ No newline at end of file diff --git a/builtins/docs/docs_doc.yaml b/builtins/docs/docs_doc.yaml index 4e52e6137..25552661e 100644 --- a/builtins/docs/docs_doc.yaml +++ b/builtins/docs/docs_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: murex-docs Title: >+ - `murex-docs` + Murex's Offline Documentation (`murex-docs`) CategoryID: commands + SubCategoryIDs: [ commands.help ] Summary: >- Displays the man pages for Murex builtins Description: |- diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 3cc173ef6..0745a4546 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -6,271 +6,275 @@ package docs func init() { Summary = map[string]string{ - "not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "and": "Returns `true` or `false` depending on whether multiple conditions are met", - "args": "Command line flag parser for Murex shell scripting", - "break": "Terminate execution of a block within your processes scope", - "cast": "Alters the data-type of the previous function without altering its output", + "addheading": "Adds headings to a table", + "prefix": "Prefix a string to every item in a list", + "suffix": "Prefix a string to every item in a list", + "alias": "Create an alias for a command", + "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "append": "Add data to the end of an array", + "bg": "Run processes in the background", + "cpuarch": "Output the hosts CPU architecture", + "cpucount": "Output the number of CPU cores available on your host", "catch": "Handles the exception code raised by `try` or `trypipe`", "cd": "Change (working) directory", - "continue": "Terminate process of a block within a caller function", - "die": "Terminate murex with an exit number of 1 (deprecated)", - "event": "Event driven programming for shell scripts", + "list.case": "Changes the character case of a string or all elements in an array", + "bexists": "Check which builtins exist", + "history": "Outputs murex's command history", + "count": "Count items in a map, list or array", + "2darray": "Create a 2D JSON array from multiple input sources", + "ja": "A sophisticated yet simply way to build a JSON array", + "map": "Creates a map from two data sources", + "pipe": "Manage Murex named pipes", + "ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "tmp": "Create a temporary file and write to it", + "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "debug": "Debugging information", + "export": "Define an environmental variable and set it's value", + "args": "Command line flag parser for Murex shell scripting", + "global": "Define a global variable and set it's value", + "openagent": "Creates a handler function for `open`", + "method": "Define a methods supported data-types", + "cast": "Alters the data-type of the previous function without altering its output", + "set": "Define a variable (typically local) and set it's value", + "unsafe": "Execute a block of code, always returning a zero exit number", + "type": "Command type (function, builtin, alias, etc)", + "fid-list": "Lists all running functions within the current Murex session", + "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "err": "Print a line to the stderr", + "esccli": "Escapes an array so output is valid shell code", + "eschtml": "Encode or decodes text for HTML", + "escurl": "Encode or decodes text for the URL", + "exec": "Runs an executable", + "fexec": "Execute a command or function, bypassing the usual order of precedence.", + "break": "Terminate execution of a block within your processes scope", + "return": "Exits current function scope", "exit": "Exit murex", - "expr": "Expressions: mathematical, string comparisons, logical operators", "false": "Returns a `false` value", - "for": "A more familiar iteration loop to existing developers", "foreach": "Iterate through an array", "formap": "Iterate through a map or other collection of data", - "format": "Reformat one data-type into another data-type", + "for": "A more familiar iteration loop to existing developers", + "fg": "Sends a background process into the foreground", + "runmode": "Alter the scheduler's behaviour at higher scoping level", + "rand": "Random field generator", "get-type": "Returns the data-type of a variable or pipe", + "exitnum": "Output the exit number of the previous process", + "pt": "Pipe telemetry. Writes data-types and bytes written", "get": "Makes a standard HTTP request and returns the result as a JSON object", - "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "g": "Glob pattern matching for file system objects (eg `*.txt`)", "if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "is-null": "Checks if a variable is null or undefined", - "ja": "A sophisticated yet simply way to build a JSON array", - "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "murex-docs": "Displays the man pages for Murex builtins", - "devnull": "null function. Similar to /dev/null", - "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "post": "HTTP POST request with a JSON-parsable return", - "rand": "Random field generator", - "return": "Exits current function scope", - "runmode": "Alter the scheduler's behaviour at higher scoping level", - "signal": "Sends a signal RPC", - "switch": "Blocks of cascading conditionals", - "tabulate": "Table transformation tools", - "test": "Murex's test framework - define tests, run tests and debug shell scripts", - "time": "Returns the execution run time of a command or block", - "true": "Returns a `true` value", - "try": "Handles non-zero exits inside a block of code", - "tryerr": "Handles errors inside a block of code", - "trypipe": "Checks for non-zero exits of each function in a pipeline", - "trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "type": "Command type (function, builtin, alias, etc)", - "unsafe": "Execute a block of code, always returning a zero exit number", - "which": "Locate command origin", - "while": "Loop until condition false", - "esccli": "Escapes an array so output is valid shell code", - "eschtml": "Encode or decodes text for HTML", - "escape": "Escape or unescape input", - "escurl": "Encode or decodes text for the URL", - "fexec": "Execute a command or function, bypassing the usual order of precedence.", - "exec": "Runs an executable", "source": "Import Murex code from another file or code block", + "is-null": "Checks if a variable is null or undefined", + "mjoin": "Joins a list or array into a single string", + "fid-killall": "Terminate all running Murex functions in current session", + "fid-kill": "Terminate a running Murex function", + "left": "Left substring every item in a list", "f": "Lists or filters file system objects (eg files)", - "g": "Glob pattern matching for file system objects (eg `*.txt`)", + "which": "Locate command origin", "lockfile": "Create and manage lock files", - "open": "Open a file with a preferred handler", - "open-image": "Renders bitmap image data on your terminal", - "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "tmp": "Create a temporary file and write to it", - "file-truncate": "Writes stdin to disk - overwriting contents if file already exists", - "man-get-flags": "Parses man page files for command line flags", + "and": "Returns `true` or `false` depending on whether multiple conditions are met", + "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "while": "Loop until condition false", "man-summary": "Outputs a man page summary of a command", - "err": "Print a line to the stderr", - "stdin": "Read the stdin belonging to the parent code block", - "pipe": "Manage Murex named pipes", + "match": "Match an exact value in an array", + "murex-package": "Murex's package manager", + "version": "Get Murex version", + "murex-docs": "Displays the man pages for Murex builtins", + "continue": "Terminate process of a block within a caller function", + "not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "devnull": "null function. Similar to /dev/null", + "open": "Open a file with a preferred handler", + "os": "Output the auto-detected OS name", "out": "Print a string to the stdout with a trailing new line character", "tout": "Print a string to the stdout and set it's data-type", - "namedpipe": "Reads from a Murex named pipe", - "read": "`read` a line of input from the user and store as a variable", - "pt": "Pipe telemetry. Writes data-types and bytes written", - "append": "Add data to the end of an array", - "list.case": "Changes the character case of a string or all elements in an array", - "mjoin": "Joins a list or array into a single string", - "left": "Left substring every item in a list", - "a": "A sophisticated yet simple way to build an array or list (mkarray)", - "ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "prefix": "Prefix a string to every item in a list", + "man-get-flags": "Parses man page files for command line flags", + "trypipe": "Checks for non-zero exits of each function in a pipeline", + "post": "HTTP POST request with a JSON-parsable return", "prepend": "Add data to the start of an array", + "pretty": "Prettifies JSON to make it human readable", + "struct-keys": "Outputs all the keys in a structure as a file path", + "private": "Define a private function block", + "time": "Returns the execution run time of a command or block", + "function": "Define a function block", + "escape": "Escape or unescape input", + "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "read": "`read` a line of input from the user and store as a variable", + "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "format": "Reformat one data-type into another data-type", + "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", "regexp": "Regexp tools for arrays / lists of strings", + "open-image": "Renders bitmap image data on your terminal", "mtac": "Reverse the order of an array", "right": "Right substring every item in a list", - "msort": "Sorts an array - data type agnostic", - "match": "Match an exact value in an array", - "suffix": "Prefix a string to every item in a list", "round": "Round a number by a user defined precision", - "bg": "Run processes in the background", - "exitnum": "Output the exit number of the previous process", - "fg": "Sends a background process into the foreground", - "fid-kill": "Terminate a running Murex function", - "fid-killall": "Terminate _all_ running Murex functions", - "fid-list": "Lists all running functions within the current Murex session", - "alias": "Create an alias for a command", - "autocomplete": "Set definitions for tab-completion in the command line", - "bexists": "Check which builtins exist", + "summary": "Defines a summary help text for a command", "config": "Query or define Murex runtime settings", - "debug": "Debugging information", - "function": "Define a function block", - "history": "Outputs murex's command history", - "method": "Define a methods supported data-types", - "openagent": "Creates a handler function for `open`", - "murex-package": "Murex's package manager", - "private": "Define a private function block", - "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "runtime": "Returns runtime information on the internal state of Murex", - "summary": "Defines a summary help text for a command", - "version": "Get Murex version", - "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "test": "Murex's test framework - define tests, run tests and debug shell scripts", + "msort": "Sorts an array - data type agnostic", "jsplit": "Splits stdin into a JSON array based on a regex parameter", - "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "count": "Count items in a map, list or array", - "pretty": "Prettifies JSON to make it human readable", - "struct-keys": "Outputs all the keys in a structure as a file path", - "2darray": "Create a 2D JSON array from multiple input sources", - "map": "Creates a map from two data sources", - "cpuarch": "Output the hosts CPU architecture", - "cpucount": "Output the number of CPU cores available on your host", - "os": "Output the auto-detected OS name", - "addheading": "Adds headings to a table", - "export": "Define an environmental variable and set it's value", - "global": "Define a global variable and set it's value", - "set": "Define a local variable and set it's value", + "trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "tryerr": "Handles errors inside a block of code", + "a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "switch": "Blocks of cascading conditionals", + "autocomplete": "Set definitions for tab-completion in the command line", + "tabulate": "Table transformation tools", + "true": "Returns a `true` value", + "try": "Handles non-zero exits inside a block of code", + "die": "Terminate murex with an exit number of 1 (deprecated)", + "event": "Event driven programming for shell scripts", + "expr": "Expressions: mathematical, string comparisons, logical operators", + "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "let": "Evaluate a mathematical function and assign to variable (deprecated)", + "murex-parser": "Runs the Murex parser against a block of code", + "signal": "Sends a signal RPC", + "select": "Inlining SQL into shell pipelines", "bz2": "Decompress a bz2 file", "base64": "Encode or decode a base64 string", "gz": "Compress or decompress a gzip file", "qr": "Creates a QR code from stdin", "sleep": "Suspends the shell for a number of seconds", - "select": "Inlining SQL into shell pipelines", - "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", - "commands/args": "Command line flag parser for Murex shell scripting", - "commands/break": "Terminate execution of a block within your processes scope", - "commands/cast": "Alters the data-type of the previous function without altering its output", + "commands/addheading": "Adds headings to a table", + "commands/prefix": "Prefix a string to every item in a list", + "commands/suffix": "Prefix a string to every item in a list", + "commands/alias": "Create an alias for a command", + "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "commands/append": "Add data to the end of an array", + "commands/bg": "Run processes in the background", + "commands/cpuarch": "Output the hosts CPU architecture", + "commands/cpucount": "Output the number of CPU cores available on your host", "commands/catch": "Handles the exception code raised by `try` or `trypipe`", "commands/cd": "Change (working) directory", - "commands/continue": "Terminate process of a block within a caller function", - "commands/die": "Terminate murex with an exit number of 1 (deprecated)", - "commands/event": "Event driven programming for shell scripts", + "commands/list.case": "Changes the character case of a string or all elements in an array", + "commands/bexists": "Check which builtins exist", + "commands/history": "Outputs murex's command history", + "commands/count": "Count items in a map, list or array", + "commands/2darray": "Create a 2D JSON array from multiple input sources", + "commands/ja": "A sophisticated yet simply way to build a JSON array", + "commands/map": "Creates a map from two data sources", + "commands/pipe": "Manage Murex named pipes", + "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "commands/tmp": "Create a temporary file and write to it", + "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "commands/debug": "Debugging information", + "commands/export": "Define an environmental variable and set it's value", + "commands/args": "Command line flag parser for Murex shell scripting", + "commands/global": "Define a global variable and set it's value", + "commands/openagent": "Creates a handler function for `open`", + "commands/method": "Define a methods supported data-types", + "commands/cast": "Alters the data-type of the previous function without altering its output", + "commands/set": "Define a variable (typically local) and set it's value", + "commands/unsafe": "Execute a block of code, always returning a zero exit number", + "commands/type": "Command type (function, builtin, alias, etc)", + "commands/fid-list": "Lists all running functions within the current Murex session", + "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "commands/err": "Print a line to the stderr", + "commands/esccli": "Escapes an array so output is valid shell code", + "commands/eschtml": "Encode or decodes text for HTML", + "commands/escurl": "Encode or decodes text for the URL", + "commands/exec": "Runs an executable", + "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", + "commands/break": "Terminate execution of a block within your processes scope", + "commands/return": "Exits current function scope", "commands/exit": "Exit murex", - "commands/expr": "Expressions: mathematical, string comparisons, logical operators", "commands/false": "Returns a `false` value", - "commands/for": "A more familiar iteration loop to existing developers", "commands/foreach": "Iterate through an array", "commands/formap": "Iterate through a map or other collection of data", - "commands/format": "Reformat one data-type into another data-type", + "commands/for": "A more familiar iteration loop to existing developers", + "commands/fg": "Sends a background process into the foreground", + "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", + "commands/rand": "Random field generator", "commands/get-type": "Returns the data-type of a variable or pipe", + "commands/exitnum": "Output the exit number of the previous process", + "commands/pt": "Pipe telemetry. Writes data-types and bytes written", "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", - "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "commands/is-null": "Checks if a variable is null or undefined", - "commands/ja": "A sophisticated yet simply way to build a JSON array", - "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/murex-docs": "Displays the man pages for Murex builtins", - "commands/devnull": "null function. Similar to /dev/null", - "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "commands/post": "HTTP POST request with a JSON-parsable return", - "commands/rand": "Random field generator", - "commands/return": "Exits current function scope", - "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", - "commands/signal": "Sends a signal RPC", - "commands/switch": "Blocks of cascading conditionals", - "commands/tabulate": "Table transformation tools", - "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", - "commands/time": "Returns the execution run time of a command or block", - "commands/true": "Returns a `true` value", - "commands/try": "Handles non-zero exits inside a block of code", - "commands/tryerr": "Handles errors inside a block of code", - "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", - "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "commands/type": "Command type (function, builtin, alias, etc)", - "commands/unsafe": "Execute a block of code, always returning a zero exit number", - "commands/which": "Locate command origin", - "commands/while": "Loop until condition false", - "commands/esccli": "Escapes an array so output is valid shell code", - "commands/eschtml": "Encode or decodes text for HTML", - "commands/escape": "Escape or unescape input", - "commands/escurl": "Encode or decodes text for the URL", - "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", - "commands/exec": "Runs an executable", "commands/source": "Import Murex code from another file or code block", + "commands/is-null": "Checks if a variable is null or undefined", + "commands/mjoin": "Joins a list or array into a single string", + "commands/fid-killall": "Terminate all running Murex functions in current session", + "commands/fid-kill": "Terminate a running Murex function", + "commands/left": "Left substring every item in a list", "commands/f": "Lists or filters file system objects (eg files)", - "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", + "commands/which": "Locate command origin", "commands/lockfile": "Create and manage lock files", - "commands/open": "Open a file with a preferred handler", - "commands/open-image": "Renders bitmap image data on your terminal", - "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "commands/tmp": "Create a temporary file and write to it", - "commands/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", - "commands/man-get-flags": "Parses man page files for command line flags", + "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", + "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "commands/while": "Loop until condition false", "commands/man-summary": "Outputs a man page summary of a command", - "commands/err": "Print a line to the stderr", - "commands/stdin": "Read the stdin belonging to the parent code block", - "commands/pipe": "Manage Murex named pipes", + "commands/match": "Match an exact value in an array", + "commands/murex-package": "Murex's package manager", + "commands/version": "Get Murex version", + "commands/murex-docs": "Displays the man pages for Murex builtins", + "commands/continue": "Terminate process of a block within a caller function", + "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "commands/devnull": "null function. Similar to /dev/null", + "commands/open": "Open a file with a preferred handler", + "commands/os": "Output the auto-detected OS name", "commands/out": "Print a string to the stdout with a trailing new line character", "commands/tout": "Print a string to the stdout and set it's data-type", - "commands/namedpipe": "Reads from a Murex named pipe", - "commands/read": "`read` a line of input from the user and store as a variable", - "commands/pt": "Pipe telemetry. Writes data-types and bytes written", - "commands/append": "Add data to the end of an array", - "commands/list.case": "Changes the character case of a string or all elements in an array", - "commands/mjoin": "Joins a list or array into a single string", - "commands/left": "Left substring every item in a list", - "commands/a": "A sophisticated yet simple way to build an array or list (mkarray)", - "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "commands/prefix": "Prefix a string to every item in a list", + "commands/man-get-flags": "Parses man page files for command line flags", + "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", + "commands/post": "HTTP POST request with a JSON-parsable return", "commands/prepend": "Add data to the start of an array", + "commands/pretty": "Prettifies JSON to make it human readable", + "commands/struct-keys": "Outputs all the keys in a structure as a file path", + "commands/private": "Define a private function block", + "commands/time": "Returns the execution run time of a command or block", + "commands/function": "Define a function block", + "commands/escape": "Escape or unescape input", + "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "commands/read": "`read` a line of input from the user and store as a variable", + "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "commands/format": "Reformat one data-type into another data-type", + "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", "commands/regexp": "Regexp tools for arrays / lists of strings", + "commands/open-image": "Renders bitmap image data on your terminal", "commands/mtac": "Reverse the order of an array", "commands/right": "Right substring every item in a list", - "commands/msort": "Sorts an array - data type agnostic", - "commands/match": "Match an exact value in an array", - "commands/suffix": "Prefix a string to every item in a list", "commands/round": "Round a number by a user defined precision", - "commands/bg": "Run processes in the background", - "commands/exitnum": "Output the exit number of the previous process", - "commands/fg": "Sends a background process into the foreground", - "commands/fid-kill": "Terminate a running Murex function", - "commands/fid-killall": "Terminate _all_ running Murex functions", - "commands/fid-list": "Lists all running functions within the current Murex session", - "commands/alias": "Create an alias for a command", - "commands/autocomplete": "Set definitions for tab-completion in the command line", - "commands/bexists": "Check which builtins exist", + "commands/summary": "Defines a summary help text for a command", "commands/config": "Query or define Murex runtime settings", - "commands/debug": "Debugging information", - "commands/function": "Define a function block", - "commands/history": "Outputs murex's command history", - "commands/method": "Define a methods supported data-types", - "commands/openagent": "Creates a handler function for `open`", - "commands/murex-package": "Murex's package manager", - "commands/private": "Define a private function block", - "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", "commands/runtime": "Returns runtime information on the internal state of Murex", - "commands/summary": "Defines a summary help text for a command", - "commands/version": "Get Murex version", - "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", + "commands/msort": "Sorts an array - data type agnostic", "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", - "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "commands/count": "Count items in a map, list or array", - "commands/pretty": "Prettifies JSON to make it human readable", - "commands/struct-keys": "Outputs all the keys in a structure as a file path", - "commands/2darray": "Create a 2D JSON array from multiple input sources", - "commands/map": "Creates a map from two data sources", - "commands/cpuarch": "Output the hosts CPU architecture", - "commands/cpucount": "Output the number of CPU cores available on your host", - "commands/os": "Output the auto-detected OS name", - "commands/addheading": "Adds headings to a table", - "commands/export": "Define an environmental variable and set it's value", - "commands/global": "Define a global variable and set it's value", - "commands/set": "Define a local variable and set it's value", + "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "commands/tryerr": "Handles errors inside a block of code", + "commands/a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "commands/switch": "Blocks of cascading conditionals", + "commands/autocomplete": "Set definitions for tab-completion in the command line", + "commands/tabulate": "Table transformation tools", + "commands/true": "Returns a `true` value", + "commands/try": "Handles non-zero exits inside a block of code", + "commands/die": "Terminate murex with an exit number of 1 (deprecated)", + "commands/event": "Event driven programming for shell scripts", + "commands/expr": "Expressions: mathematical, string comparisons, logical operators", + "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", + "commands/murex-parser": "Runs the Murex parser against a block of code", + "commands/signal": "Sends a signal RPC", "mkarray/date": "Create arrays of dates", "mkarray/character": "Making character arrays (a to z)", "mkarray/decimal": "Create arrays of decimal integers", "mkarray/non-decimal": "Create arrays of integers from non-decimal number bases", "mkarray/special": "Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc)", + "optional/select": "Inlining SQL into shell pipelines", "optional/bz2": "Decompress a bz2 file", "optional/base64": "Encode or decode a base64 string", "optional/gz": "Compress or decompress a gzip file", "optional/qr": "Creates a QR code from stdin", "optional/sleep": "Suspends the shell for a number of seconds", - "optional/select": "Inlining SQL into shell pipelines", "parser/expr-inlined": "Inline expressions", "parser/c-style-fun": "Inlined commands for expressions and statements", + "parser/range": "Outputs a ranged subset of data from stdin", + "parser/item-index": "Outputs an element from an array, map or table", + "parser/element": "Outputs an element from a nested structure", + "parser/namedpipe": "Reads from a Murex named pipe", + "parser/stdin": "Read the stdin belonging to the parent code block", + "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", "parser/double-quote": "Initiates or terminates a string (variables expanded)", "parser/scalar": "Expand values as a scalar", "parser/brace-quote": "Initiates or terminates a string (variables expanded)", @@ -296,9 +300,6 @@ func init() { "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined (expression)", "parser/pipe-err": "Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED)", "parser/array": "Expand values as an array", - "parser/range": "Outputs a ranged subset of data from stdin", - "parser/item-index": "Outputs an element from an array, map or table", - "parser/element": "Outputs an element from a nested structure", "parser/lambda": "Iterate through structured data", "parser/curly-brace": "Initiates or terminates a code block", "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", @@ -414,261 +415,192 @@ func init() { Synonym = map[string]string{ - "!": "not-func", - "not": "not-func", - "and": "and", - "!and": "and", - "args": "args", - "break": "break", - "cast": "cast", + "addheading": "addheading", + "prefix": "prefix", + "list.prefix": "prefix", + "suffix": "suffix", + "list.suffix": "suffix", + "alias": "alias", + "!alias": "alias", + "alter": "alter", + "~>": "alter", + "append": "append", + "list.append": "append", + "bg": "bg", + "cpuarch": "cpuarch", + "sys.cpu.arch": "cpuarch", + "cpucount": "cpucount", + "sys.cpu.count": "cpucount", "catch": "catch", "!catch": "catch", "cd": "cd", - "continue": "continue", - "die": "die", - "event": "event", - "!event": "event", - "exit": "exit", - "expr": "expr", - "false": "false", - "for": "for", - "foreach": "foreach", - "formap": "formap", - "format": "format", - "get-type": "get-type", - "get": "get", - "getfile": "getfile", - "if": "if", - "!if": "if", - "is-null": "is-null", - "ja": "ja", - "key-code": "key-code", - "let": "let", - "murex-docs": "murex-docs", - "help": "murex-docs", - "null": "devnull", - "or": "or", - "!or": "or", - "post": "post", - "rand": "rand", - "return": "return", - "runmode": "runmode", - "signal": "signal", - "switch": "switch", - "tabulate": "tabulate", - "test": "test", - "!test": "test", - "time": "time", - "true": "true", - "try": "try", - "tryerr": "tryerr", - "trypipe": "trypipe", - "trypipeerr": "trypipeerr", - "type": "type", + "list.case": "list.case", + "bexists": "bexists", + "history": "history", + "count": "count", + "len": "count", + "2darray": "2darray", + "ja": "ja", + "map": "map", + "pipe": "pipe", + "!pipe": "pipe", + "ta": "ta", + "tmp": "tmp", + "datetime": "datetime", + "str.datetime": "datetime", + "debug": "debug", + "export": "export", + "!export": "export", + "unset": "export", + "var.env": "export", + "!var.env": "export", + "args": "args", + "global": "global", + "!global": "global", + "openagent": "openagent", + "!openagent": "openagent", + "method": "method", + "cast": "cast", + "set": "set", + "!set": "set", "unsafe": "unsafe", - "which": "which", - "while": "while", - "!while": "while", + "type": "type", + "fid-list": "fid-list", + "jobs": "fid-list", + "getfile": "getfile", + "err": "err", "esccli": "esccli", - "escape.cli": "esccli", "eschtml": "eschtml", "!eschtml": "eschtml", - "escape.html": "eschtml", - "!escape.html": "eschtml", - "escape": "escape", - "!escape": "escape", - "escape.quote": "escape", - "!escape.quote": "escape", "escurl": "escurl", "!escurl": "escurl", - "escape.url": "escurl", - "!escape.url": "escurl", + "exec": "exec", + "command": "exec", + "exec.file": "exec", "fexec": "fexec", "builtin": "fexec", "exec.builtin": "fexec", "exec.function": "fexec", "exec.private": "fexec", - "exec": "exec", - "command": "exec", - "exec.file": "exec", + "break": "break", + "return": "return", + "exit": "exit", + "false": "false", + "foreach": "foreach", + "formap": "formap", + "for": "for", + "fg": "fg", + "runmode": "runmode", + "rand": "rand", + "get-type": "get-type", + "exitnum": "exitnum", + "pt": "pt", + "get": "get", + "g": "g", + "!g": "g", + "if": "if", + "!if": "if", "source": "source", ".": "source", - "exec.include": "source", + "is-null": "is-null", + "mjoin": "mjoin", + "list.join": "mjoin", + "fid-killall": "fid-killall", + "fid-kill": "fid-kill", + "left": "left", + "list.left": "left", "f": "f", - "fs.files": "f", - "g": "g", - "!g": "g", - "fs.glob": "g", - "!fs.glob": "g", + "which": "which", "lockfile": "lockfile", - "fs.lockfile": "lockfile", - "open": "open", - "fs.open": "open", - "open-image": "open-image", - "fs.open.image": "open-image", - "rx": "rx", - "!rx": "rx", - "fs.regex": "rx", - "!fs.regex": "rx", - "tmp": "tmp", - "fs.new.tmpfile": "tmp", - ">": "file-truncate", - "fs.truncate": "file-truncate", - "|>": "file-truncate", - "fwrite": "file-truncate", - "man-get-flags": "man-get-flags", - "help.man.flags": "man-get-flags", + "and": "and", + "!and": "and", + "or": "or", + "!or": "or", + "while": "while", + "!while": "while", "man-summary": "man-summary", "help.man.summary": "man-summary", - "err": "err", - "io.err": "err", - "": "stdin", - "io.in": "stdin", - "pipe": "pipe", - "!pipe": "pipe", - "io.new.pipe": "pipe", - "!io.new.pipe": "pipe", + "match": "match", + "!match": "match", + "list.str": "match", + "!list.str": "match", + "murex-package": "murex-package", + "version": "version", + "murex-docs": "murex-docs", + "help": "murex-docs", + "continue": "continue", + "!": "not-func", + "not": "not-func", + "null": "devnull", + "open": "open", + "os": "os", + "sys.os": "os", "out": "out", - "io.out": "out", "echo": "out", "tout": "tout", - "io.out.type": "tout", - "(murex named pipe)": "namedpipe", - "<>": "namedpipe", - "read-named-pipe": "namedpipe", - "io.pipe": "namedpipe", - "read": "read", - "io.input": "read", - "pt": "pt", - "fs.status": "pt", - "append": "append", - "list.append": "append", - "list.case": "list.case", - "mjoin": "mjoin", - "list.join": "mjoin", - "left": "left", - "list.left": "left", - "a": "a", - "mkarray": "a", - "list.new.str": "a", - "ta": "ta", - "list.new.type": "ta", - "prefix": "prefix", - "list.prefix": "prefix", + "man-get-flags": "man-get-flags", + "trypipe": "trypipe", + "post": "post", "prepend": "prepend", "list.prepend": "prepend", + "pretty": "pretty", + "struct-keys": "struct-keys", + "private": "private", + "time": "time", + "function": "function", + "!function": "function", + "escape": "escape", + "!escape": "escape", + "murex-update-exe-list": "murex-update-exe-list", + "read": "read", + "tread": "tread", + "format": "format", + "rx": "rx", + "!rx": "rx", "regexp": "regexp", "!regexp": "regexp", "list.regex": "regexp", "!list.regex": "regexp", + "open-image": "open-image", "mtac": "mtac", "list.reverse": "mtac", "right": "right", "list.right": "right", - "msort": "msort", - "list.sort": "msort", - "match": "match", - "!match": "match", - "list.str": "match", - "!list.str": "match", - "suffix": "suffix", - "list.suffix": "suffix", "round": "round", "num.round": "round", - "bg": "bg", - "proc.bg": "bg", - "exitnum": "exitnum", - "proc.exitnum": "exitnum", - "fg": "fg", - "proc.fg": "fg", - "fid-kill": "fid-kill", - "proc.kill": "fid-kill", - "fid-killall": "fid-killall", - "proc.kill.all": "fid-killall", - "fid-list": "fid-list", - "jobs": "fid-list", - "proc.list": "fid-list", - "proc.jobs": "fid-list", - "alias": "alias", - "!alias": "alias", - "shell.alias": "alias", - "!shell.alias": "alias", - "autocomplete": "autocomplete", - "shell.autocomplete": "autocomplete", - "bexists": "bexists", + "summary": "summary", + "!summary": "summary", "config": "config", "!config": "config", - "shell.config": "config", - "!shell.config": "config", - "debug": "debug", - "shell.debug": "debug", - "function": "function", - "!function": "function", - "shell.function": "function", - "!shell.function": "function", - "history": "history", - "shell.history": "history", - "method": "method", - "shell.method": "method", - "openagent": "openagent", - "!openagent": "openagent", - "shell.open": "openagent", - "!shell.open": "openagent", - "murex-package": "murex-package", - "shell.packages": "murex-package", - "private": "private", - "shell.private": "private", - "murex-update-exe-list": "murex-update-exe-list", - "shell.rescan.path": "murex-update-exe-list", "runtime": "runtime", "builtins": "runtime", "shell.runtime": "runtime", - "summary": "summary", - "!summary": "summary", - "shell.summary": "summary", - "!shell.summary": "summary", - "version": "version", - "shell.version": "version", - "datetime": "datetime", - "str.datetime": "datetime", + "test": "test", + "!test": "test", + "msort": "msort", + "list.sort": "msort", "jsplit": "jsplit", "str.split": "jsplit", - "alter": "alter", - "~>": "alter", - "struct.alter": "alter", - "count": "count", - "len": "count", - "struct.count": "count", - "pretty": "pretty", - "struct.json.pretty": "pretty", - "struct-keys": "struct-keys", - "struct.keys": "struct-keys", - "2darray": "2darray", - "struct.new.2darray": "2darray", - "map": "map", - "struct.new.map": "map", - "cpuarch": "cpuarch", - "sys.cpu.arch": "cpuarch", - "cpucount": "cpucount", - "sys.cpu.count": "cpucount", - "os": "os", - "sys.os": "os", - "addheading": "addheading", - "table.new.heading": "addheading", - "export": "export", - "!export": "export", - "unset": "export", - "var.env": "export", - "!var.env": "export", - "global": "global", - "!global": "global", - "var.global": "global", - "!var.global": "global", - "set": "set", - "!set": "set", - "var.set": "set", - "!var.set": "set", + "trypipeerr": "trypipeerr", + "tryerr": "tryerr", + "a": "a", + "mkarray": "a", + "switch": "switch", + "autocomplete": "autocomplete", + "tabulate": "tabulate", + "true": "true", + "try": "try", + "die": "die", + "event": "event", + "!event": "event", + "expr": "expr", + "key-code": "key-code", + "let": "let", + "murex-parser": "murex-parser", + "signal": "signal", + "select": "optional/select", + "table.select": "optional/select", "!bz2": "optional/bz2", "base64": "optional/base64", "!base64": "optional/base64", @@ -676,309 +608,245 @@ func init() { "!gz": "optional/gz", "qr": "optional/qr", "sleep": "optional/sleep", - "select": "optional/select", - "table.select": "optional/select", - "expr-inlined": "parser/expr-inlined", - "c-style-fun": "parser/c-style-fun", - "double-quote": "parser/double-quote", - "scalar": "parser/scalar", - "brace-quote": "parser/brace-quote", - "create-array": "parser/create-array", - "create-object": "parser/create-object", - "logical-and": "parser/logical-and", - "single-quote": "parser/single-quote", - "(": "parser/brace-quote-func", - "multiply-by": "parser/multiply-by", - "multiplication": "parser/multiplication", - "add-with": "parser/add-with", - "addition": "parser/addition", - "subtract-by": "parser/subtract-by", - "pipe-arrow": "parser/pipe-arrow", - "subtraction": "parser/subtraction", - "divide-by": "parser/divide-by", - "division": "parser/division", - "assign-or-merge": "parser/assign-or-merge", - "pipe-generic": "parser/pipe-generic", - "=": "parser/equ", - ">>": "parser/file-append", - "fappend": "parser/file-append", - "elvis": "parser/elvis", - "null-coalescing": "parser/null-coalescing", - "pipe-err": "parser/pipe-err", - "array": "parser/array", - "@[": "parser/range", - "[": "parser/item-index", - "![": "parser/item-index", - "item-index": "parser/item-index", - "index": "parser/item-index", - "[[": "parser/element", - "element": "parser/element", - "lambda": "parser/lambda", - "curly-brace": "parser/curly-brace", - "pipe-posix": "parser/pipe-posix", - "logical-or": "parser/logical-or", - "tilde": "parser/tilde", + "expr-inlined": "parser/expr-inlined", + "c-style-fun": "parser/c-style-fun", + "@[": "parser/range", + "[": "parser/item-index", + "![": "parser/item-index", + "item-index": "parser/item-index", + "index": "parser/item-index", + "[[": "parser/element", + "element": "parser/element", + "(murex named pipe)": "parser/namedpipe", + "<>": "parser/namedpipe", + "read-named-pipe": "parser/namedpipe", + "": "parser/stdin", + ">": "parser/file-truncate", + "|>": "parser/file-truncate", + "fwrite": "parser/file-truncate", + "double-quote": "parser/double-quote", + "scalar": "parser/scalar", + "brace-quote": "parser/brace-quote", + "create-array": "parser/create-array", + "create-object": "parser/create-object", + "logical-and": "parser/logical-and", + "single-quote": "parser/single-quote", + "(": "parser/brace-quote-func", + "multiply-by": "parser/multiply-by", + "multiplication": "parser/multiplication", + "add-with": "parser/add-with", + "addition": "parser/addition", + "subtract-by": "parser/subtract-by", + "pipe-arrow": "parser/pipe-arrow", + "subtraction": "parser/subtraction", + "divide-by": "parser/divide-by", + "division": "parser/division", + "assign-or-merge": "parser/assign-or-merge", + "pipe-generic": "parser/pipe-generic", + "=": "parser/equ", + ">>": "parser/file-append", + "fappend": "parser/file-append", + "elvis": "parser/elvis", + "null-coalescing": "parser/null-coalescing", + "pipe-err": "parser/pipe-err", + "array": "parser/array", + "lambda": "parser/lambda", + "curly-brace": "parser/curly-brace", + "pipe-posix": "parser/pipe-posix", + "logical-or": "parser/logical-or", + "tilde": "parser/tilde", - "commands/!": "commands/not-func", - "commands/not": "commands/not-func", - "commands/and": "commands/and", - "commands/!and": "commands/and", + "commands/addheading": "commands/addheading", + "commands/prefix": "commands/prefix", + "commands/list.prefix": "commands/prefix", + "commands/suffix": "commands/suffix", + "commands/list.suffix": "commands/suffix", + "commands/alias": "commands/alias", + "commands/!alias": "commands/alias", + "commands/alter": "commands/alter", + "commands/~>": "commands/alter", + "commands/append": "commands/append", + "commands/list.append": "commands/append", + "commands/bg": "commands/bg", + "commands/cpuarch": "commands/cpuarch", + "commands/sys.cpu.arch": "commands/cpuarch", + "commands/cpucount": "commands/cpucount", + "commands/sys.cpu.count": "commands/cpucount", + "commands/catch": "commands/catch", + "commands/!catch": "commands/catch", + "commands/cd": "commands/cd", + "commands/list.case": "commands/list.case", + "commands/bexists": "commands/bexists", + "commands/history": "commands/history", + "commands/count": "commands/count", + "commands/len": "commands/count", + "commands/2darray": "commands/2darray", + "commands/ja": "commands/ja", + "commands/map": "commands/map", + "commands/pipe": "commands/pipe", + "commands/!pipe": "commands/pipe", + "commands/ta": "commands/ta", + "commands/tmp": "commands/tmp", + "commands/datetime": "commands/datetime", + "commands/str.datetime": "commands/datetime", + "commands/debug": "commands/debug", + "commands/export": "commands/export", + "commands/!export": "commands/export", + "commands/unset": "commands/export", + "commands/var.env": "commands/export", + "commands/!var.env": "commands/export", "commands/args": "commands/args", - "commands/break": "commands/break", + "commands/global": "commands/global", + "commands/!global": "commands/global", + "commands/openagent": "commands/openagent", + "commands/!openagent": "commands/openagent", + "commands/method": "commands/method", "commands/cast": "commands/cast", - "commands/catch": "commands/catch", - "commands/!catch": "commands/catch", - "commands/cd": "commands/cd", - "commands/continue": "commands/continue", - "commands/die": "commands/die", - "commands/event": "commands/event", - "commands/!event": "commands/event", - "commands/exit": "commands/exit", - "commands/expr": "commands/expr", - "commands/false": "commands/false", - "commands/for": "commands/for", - "commands/foreach": "commands/foreach", - "commands/formap": "commands/formap", - "commands/format": "commands/format", - "commands/get-type": "commands/get-type", - "commands/get": "commands/get", - "commands/getfile": "commands/getfile", - "commands/if": "commands/if", - "commands/!if": "commands/if", - "commands/is-null": "commands/is-null", - "commands/ja": "commands/ja", - "commands/key-code": "commands/key-code", - "commands/let": "commands/let", - "commands/murex-docs": "commands/murex-docs", - "commands/help": "commands/murex-docs", - "commands/null": "commands/devnull", - "commands/or": "commands/or", - "commands/!or": "commands/or", - "commands/post": "commands/post", - "commands/rand": "commands/rand", - "commands/return": "commands/return", - "commands/runmode": "commands/runmode", - "commands/signal": "commands/signal", - "commands/switch": "commands/switch", - "commands/tabulate": "commands/tabulate", - "commands/test": "commands/test", - "commands/!test": "commands/test", - "commands/time": "commands/time", - "commands/true": "commands/true", - "commands/try": "commands/try", - "commands/tryerr": "commands/tryerr", - "commands/trypipe": "commands/trypipe", - "commands/trypipeerr": "commands/trypipeerr", - "commands/type": "commands/type", + "commands/set": "commands/set", + "commands/!set": "commands/set", "commands/unsafe": "commands/unsafe", - "commands/which": "commands/which", - "commands/while": "commands/while", - "commands/!while": "commands/while", + "commands/type": "commands/type", + "commands/fid-list": "commands/fid-list", + "commands/jobs": "commands/fid-list", + "commands/getfile": "commands/getfile", + "commands/err": "commands/err", "commands/esccli": "commands/esccli", - "commands/escape.cli": "commands/esccli", "commands/eschtml": "commands/eschtml", "commands/!eschtml": "commands/eschtml", - "commands/escape.html": "commands/eschtml", - "commands/!escape.html": "commands/eschtml", - "commands/escape": "commands/escape", - "commands/!escape": "commands/escape", - "commands/escape.quote": "commands/escape", - "commands/!escape.quote": "commands/escape", "commands/escurl": "commands/escurl", "commands/!escurl": "commands/escurl", - "commands/escape.url": "commands/escurl", - "commands/!escape.url": "commands/escurl", + "commands/exec": "commands/exec", + "commands/command": "commands/exec", + "commands/exec.file": "commands/exec", "commands/fexec": "commands/fexec", "commands/builtin": "commands/fexec", "commands/exec.builtin": "commands/fexec", "commands/exec.function": "commands/fexec", "commands/exec.private": "commands/fexec", - "commands/exec": "commands/exec", - "commands/command": "commands/exec", - "commands/exec.file": "commands/exec", + "commands/break": "commands/break", + "commands/return": "commands/return", + "commands/exit": "commands/exit", + "commands/false": "commands/false", + "commands/foreach": "commands/foreach", + "commands/formap": "commands/formap", + "commands/for": "commands/for", + "commands/fg": "commands/fg", + "commands/runmode": "commands/runmode", + "commands/rand": "commands/rand", + "commands/get-type": "commands/get-type", + "commands/exitnum": "commands/exitnum", + "commands/pt": "commands/pt", + "commands/get": "commands/get", + "commands/g": "commands/g", + "commands/!g": "commands/g", + "commands/if": "commands/if", + "commands/!if": "commands/if", "commands/source": "commands/source", "commands/.": "commands/source", - "commands/exec.include": "commands/source", + "commands/is-null": "commands/is-null", + "commands/mjoin": "commands/mjoin", + "commands/list.join": "commands/mjoin", + "commands/fid-killall": "commands/fid-killall", + "commands/fid-kill": "commands/fid-kill", + "commands/left": "commands/left", + "commands/list.left": "commands/left", "commands/f": "commands/f", - "commands/fs.files": "commands/f", - "commands/g": "commands/g", - "commands/!g": "commands/g", - "commands/fs.glob": "commands/g", - "commands/!fs.glob": "commands/g", + "commands/which": "commands/which", "commands/lockfile": "commands/lockfile", - "commands/fs.lockfile": "commands/lockfile", - "commands/open": "commands/open", - "commands/fs.open": "commands/open", - "commands/open-image": "commands/open-image", - "commands/fs.open.image": "commands/open-image", - "commands/rx": "commands/rx", - "commands/!rx": "commands/rx", - "commands/fs.regex": "commands/rx", - "commands/!fs.regex": "commands/rx", - "commands/tmp": "commands/tmp", - "commands/fs.new.tmpfile": "commands/tmp", - "commands/>": "commands/file-truncate", - "commands/fs.truncate": "commands/file-truncate", - "commands/|>": "commands/file-truncate", - "commands/fwrite": "commands/file-truncate", - "commands/man-get-flags": "commands/man-get-flags", - "commands/help.man.flags": "commands/man-get-flags", + "commands/and": "commands/and", + "commands/!and": "commands/and", + "commands/or": "commands/or", + "commands/!or": "commands/or", + "commands/while": "commands/while", + "commands/!while": "commands/while", "commands/man-summary": "commands/man-summary", "commands/help.man.summary": "commands/man-summary", - "commands/err": "commands/err", - "commands/io.err": "commands/err", - "commands/": "commands/stdin", - "commands/io.in": "commands/stdin", - "commands/pipe": "commands/pipe", - "commands/!pipe": "commands/pipe", - "commands/io.new.pipe": "commands/pipe", - "commands/!io.new.pipe": "commands/pipe", + "commands/match": "commands/match", + "commands/!match": "commands/match", + "commands/list.str": "commands/match", + "commands/!list.str": "commands/match", + "commands/murex-package": "commands/murex-package", + "commands/version": "commands/version", + "commands/murex-docs": "commands/murex-docs", + "commands/help": "commands/murex-docs", + "commands/continue": "commands/continue", + "commands/!": "commands/not-func", + "commands/not": "commands/not-func", + "commands/null": "commands/devnull", + "commands/open": "commands/open", + "commands/os": "commands/os", + "commands/sys.os": "commands/os", "commands/out": "commands/out", - "commands/io.out": "commands/out", "commands/echo": "commands/out", "commands/tout": "commands/tout", - "commands/io.out.type": "commands/tout", - "commands/(murex named pipe)": "commands/namedpipe", - "commands/<>": "commands/namedpipe", - "commands/read-named-pipe": "commands/namedpipe", - "commands/io.pipe": "commands/namedpipe", - "commands/read": "commands/read", - "commands/io.input": "commands/read", - "commands/pt": "commands/pt", - "commands/fs.status": "commands/pt", - "commands/append": "commands/append", - "commands/list.append": "commands/append", - "commands/list.case": "commands/list.case", - "commands/mjoin": "commands/mjoin", - "commands/list.join": "commands/mjoin", - "commands/left": "commands/left", - "commands/list.left": "commands/left", - "commands/a": "commands/a", - "commands/mkarray": "commands/a", - "commands/list.new.str": "commands/a", - "commands/ta": "commands/ta", - "commands/list.new.type": "commands/ta", - "commands/prefix": "commands/prefix", - "commands/list.prefix": "commands/prefix", + "commands/man-get-flags": "commands/man-get-flags", + "commands/trypipe": "commands/trypipe", + "commands/post": "commands/post", "commands/prepend": "commands/prepend", "commands/list.prepend": "commands/prepend", + "commands/pretty": "commands/pretty", + "commands/struct-keys": "commands/struct-keys", + "commands/private": "commands/private", + "commands/time": "commands/time", + "commands/function": "commands/function", + "commands/!function": "commands/function", + "commands/escape": "commands/escape", + "commands/!escape": "commands/escape", + "commands/murex-update-exe-list": "commands/murex-update-exe-list", + "commands/read": "commands/read", + "commands/tread": "commands/tread", + "commands/format": "commands/format", + "commands/rx": "commands/rx", + "commands/!rx": "commands/rx", "commands/regexp": "commands/regexp", "commands/!regexp": "commands/regexp", "commands/list.regex": "commands/regexp", "commands/!list.regex": "commands/regexp", + "commands/open-image": "commands/open-image", "commands/mtac": "commands/mtac", "commands/list.reverse": "commands/mtac", "commands/right": "commands/right", "commands/list.right": "commands/right", - "commands/msort": "commands/msort", - "commands/list.sort": "commands/msort", - "commands/match": "commands/match", - "commands/!match": "commands/match", - "commands/list.str": "commands/match", - "commands/!list.str": "commands/match", - "commands/suffix": "commands/suffix", - "commands/list.suffix": "commands/suffix", "commands/round": "commands/round", "commands/num.round": "commands/round", - "commands/bg": "commands/bg", - "commands/proc.bg": "commands/bg", - "commands/exitnum": "commands/exitnum", - "commands/proc.exitnum": "commands/exitnum", - "commands/fg": "commands/fg", - "commands/proc.fg": "commands/fg", - "commands/fid-kill": "commands/fid-kill", - "commands/proc.kill": "commands/fid-kill", - "commands/fid-killall": "commands/fid-killall", - "commands/proc.kill.all": "commands/fid-killall", - "commands/fid-list": "commands/fid-list", - "commands/jobs": "commands/fid-list", - "commands/proc.list": "commands/fid-list", - "commands/proc.jobs": "commands/fid-list", - "commands/alias": "commands/alias", - "commands/!alias": "commands/alias", - "commands/shell.alias": "commands/alias", - "commands/!shell.alias": "commands/alias", - "commands/autocomplete": "commands/autocomplete", - "commands/shell.autocomplete": "commands/autocomplete", - "commands/bexists": "commands/bexists", + "commands/summary": "commands/summary", + "commands/!summary": "commands/summary", "commands/config": "commands/config", "commands/!config": "commands/config", - "commands/shell.config": "commands/config", - "commands/!shell.config": "commands/config", - "commands/debug": "commands/debug", - "commands/shell.debug": "commands/debug", - "commands/function": "commands/function", - "commands/!function": "commands/function", - "commands/shell.function": "commands/function", - "commands/!shell.function": "commands/function", - "commands/history": "commands/history", - "commands/shell.history": "commands/history", - "commands/method": "commands/method", - "commands/shell.method": "commands/method", - "commands/openagent": "commands/openagent", - "commands/!openagent": "commands/openagent", - "commands/shell.open": "commands/openagent", - "commands/!shell.open": "commands/openagent", - "commands/murex-package": "commands/murex-package", - "commands/shell.packages": "commands/murex-package", - "commands/private": "commands/private", - "commands/shell.private": "commands/private", - "commands/murex-update-exe-list": "commands/murex-update-exe-list", - "commands/shell.rescan.path": "commands/murex-update-exe-list", "commands/runtime": "commands/runtime", "commands/builtins": "commands/runtime", "commands/shell.runtime": "commands/runtime", - "commands/summary": "commands/summary", - "commands/!summary": "commands/summary", - "commands/shell.summary": "commands/summary", - "commands/!shell.summary": "commands/summary", - "commands/version": "commands/version", - "commands/shell.version": "commands/version", - "commands/datetime": "commands/datetime", - "commands/str.datetime": "commands/datetime", + "commands/test": "commands/test", + "commands/!test": "commands/test", + "commands/msort": "commands/msort", + "commands/list.sort": "commands/msort", "commands/jsplit": "commands/jsplit", "commands/str.split": "commands/jsplit", - "commands/alter": "commands/alter", - "commands/~>": "commands/alter", - "commands/struct.alter": "commands/alter", - "commands/count": "commands/count", - "commands/len": "commands/count", - "commands/struct.count": "commands/count", - "commands/pretty": "commands/pretty", - "commands/struct.json.pretty": "commands/pretty", - "commands/struct-keys": "commands/struct-keys", - "commands/struct.keys": "commands/struct-keys", - "commands/2darray": "commands/2darray", - "commands/struct.new.2darray": "commands/2darray", - "commands/map": "commands/map", - "commands/struct.new.map": "commands/map", - "commands/cpuarch": "commands/cpuarch", - "commands/sys.cpu.arch": "commands/cpuarch", - "commands/cpucount": "commands/cpucount", - "commands/sys.cpu.count": "commands/cpucount", - "commands/os": "commands/os", - "commands/sys.os": "commands/os", - "commands/addheading": "commands/addheading", - "commands/table.new.heading": "commands/addheading", - "commands/export": "commands/export", - "commands/!export": "commands/export", - "commands/unset": "commands/export", - "commands/var.env": "commands/export", - "commands/!var.env": "commands/export", - "commands/global": "commands/global", - "commands/!global": "commands/global", - "commands/var.global": "commands/global", - "commands/!var.global": "commands/global", - "commands/set": "commands/set", - "commands/!set": "commands/set", - "commands/var.set": "commands/set", - "commands/!var.set": "commands/set", + "commands/trypipeerr": "commands/trypipeerr", + "commands/tryerr": "commands/tryerr", + "commands/a": "commands/a", + "commands/mkarray": "commands/a", + "commands/switch": "commands/switch", + "commands/autocomplete": "commands/autocomplete", + "commands/tabulate": "commands/tabulate", + "commands/true": "commands/true", + "commands/try": "commands/try", + "commands/die": "commands/die", + "commands/event": "commands/event", + "commands/!event": "commands/event", + "commands/expr": "commands/expr", + "commands/key-code": "commands/key-code", + "commands/let": "commands/let", + "commands/murex-parser": "commands/murex-parser", + "commands/signal": "commands/signal", "mkarray/date": "mkarray/date", "mkarray/character": "mkarray/character", "mkarray/decimal": "mkarray/decimal", "mkarray/non-decimal": "mkarray/non-decimal", "mkarray/special": "mkarray/special", + "optional/select": "optional/select", + "optional/table.select": "optional/select", "optional/!bz2": "optional/bz2", "optional/base64": "optional/base64", "optional/!base64": "optional/base64", @@ -986,10 +854,22 @@ func init() { "optional/!gz": "optional/gz", "optional/qr": "optional/qr", "optional/sleep": "optional/sleep", - "optional/select": "optional/select", - "optional/table.select": "optional/select", "parser/expr-inlined": "parser/expr-inlined", "parser/c-style-fun": "parser/c-style-fun", + "parser/@[": "parser/range", + "parser/[": "parser/item-index", + "parser/![": "parser/item-index", + "parser/item-index": "parser/item-index", + "parser/index": "parser/item-index", + "parser/[[": "parser/element", + "parser/element": "parser/element", + "parser/(murex named pipe)": "parser/namedpipe", + "parser/<>": "parser/namedpipe", + "parser/read-named-pipe": "parser/namedpipe", + "parser/": "parser/stdin", + "parser/>": "parser/file-truncate", + "parser/|>": "parser/file-truncate", + "parser/fwrite": "parser/file-truncate", "parser/double-quote": "parser/double-quote", "parser/scalar": "parser/scalar", "parser/brace-quote": "parser/brace-quote", @@ -1016,13 +896,6 @@ func init() { "parser/null-coalescing": "parser/null-coalescing", "parser/pipe-err": "parser/pipe-err", "parser/array": "parser/array", - "parser/@[": "parser/range", - "parser/[": "parser/item-index", - "parser/![": "parser/item-index", - "parser/item-index": "parser/item-index", - "parser/index": "parser/item-index", - "parser/[[": "parser/element", - "parser/element": "parser/element", "parser/lambda": "parser/lambda", "parser/curly-brace": "parser/curly-brace", "parser/pipe-posix": "parser/pipe-posix", diff --git a/builtins/events/events_doc.yaml b/builtins/events/events_doc.yaml index 3393f02ba..5ebf455c1 100644 --- a/builtins/events/events_doc.yaml +++ b/builtins/events/events_doc.yaml @@ -2,12 +2,13 @@ Title: >+ `event` CategoryID: commands + SubCategoryIDs: [ commands.shell ] Summary: >- Event driven programming for shell scripts Description: |- Create or destroy an event interrupt, - Each event will have subtilty different behaviour depending on the event itself + Each event will have subtly different behaviour depending on the event itself due to the differing roles of each event system. Therefore it is recommended that you read the docs on each event to understand its behaviour. diff --git a/builtins/events/onKeyPress/keycodes_doc.yaml b/builtins/events/onKeyPress/keycodes_doc.yaml index 176a5f0a5..2903ffc0a 100644 --- a/builtins/events/onKeyPress/keycodes_doc.yaml +++ b/builtins/events/onKeyPress/keycodes_doc.yaml @@ -2,6 +2,7 @@ Title: >+ `key-code` CategoryID: commands + SubCategoryIDs: [ commands.esc ] Summary: >- Returns character sequences for any key pressed (ie sent from the terminal) Description: |- diff --git a/builtins/events/onSignalReceived/signal_doc.yaml b/builtins/events/onSignalReceived/signal_doc.yaml index fcd2eeba9..405f73ea3 100644 --- a/builtins/events/onSignalReceived/signal_doc.yaml +++ b/builtins/events/onSignalReceived/signal_doc.yaml @@ -2,6 +2,7 @@ Title: >+ `signal` CategoryID: commands + SubCategoryIDs: [ commands.proc ] Summary: >- Sends a signal RPC Description: |- diff --git a/builtins/optional/select/select_doc.yaml b/builtins/optional/select/select_doc.yaml index e92609644..ec1fd55e3 100644 --- a/builtins/optional/select/select_doc.yaml +++ b/builtins/optional/select/select_doc.yaml @@ -1,7 +1,8 @@ - DocumentID: select Title: >- - table.select: `select` + Inline SQL (`select`) CategoryID: optional + SubCategoryIDs: [ commands.table ] Summary: >- Inlining SQL into shell pipelines Description: |- diff --git a/docs/apis/ReadIndex.md b/docs/apis/ReadIndex.md index 334f93c2b..3201a52a2 100644 --- a/docs/apis/ReadIndex.md +++ b/docs/apis/ReadIndex.md @@ -69,6 +69,8 @@ both agnostic to the bang prefix. * [user-guide/Bang Prefix](../user-guide/bang-prefix.md): Bang prefixing to reverse default actions +* [parser/Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure * [apis/`ReadArray()` (type)](../apis/ReadArray.md): Read from a data type one array element at a time * [apis/`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): @@ -77,8 +79,6 @@ both agnostic to the bang prefix. Data type handler for the bang-prefixed index, `![`, builtin * [apis/`WriteArray()` (type)](../apis/WriteArray.md): Write a data type, one array element at a time -* [parser/`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [apis/`lang.IndexTemplateObject()` (template API)](../apis/lang.IndexTemplateObject.md): Returns element(s) from a data structure * [apis/`lang.IndexTemplateTable()` (template API)](../apis/lang.IndexTemplateTable.md): diff --git a/docs/apis/ReadNotIndex.md b/docs/apis/ReadNotIndex.md index 49e74004f..8f9a85eee 100644 --- a/docs/apis/ReadNotIndex.md +++ b/docs/apis/ReadNotIndex.md @@ -70,6 +70,8 @@ both agnostic to the bang prefix. * [user-guide/Bang Prefix](../user-guide/bang-prefix.md): Bang prefixing to reverse default actions +* [parser/Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure * [apis/`ReadArray()` (type)](../apis/ReadArray.md): Read from a data type one array element at a time * [apis/`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): @@ -78,8 +80,6 @@ both agnostic to the bang prefix. Data type handler for the index, `[`, builtin * [apis/`WriteArray()` (type)](../apis/WriteArray.md): Write a data type, one array element at a time -* [parser/`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [apis/`lang.IndexTemplateObject()` (template API)](../apis/lang.IndexTemplateObject.md): Returns element(s) from a data structure * [apis/`lang.IndexTemplateTable()` (template API)](../apis/lang.IndexTemplateTable.md): diff --git a/docs/blog/reading_lists.md b/docs/blog/reading_lists.md index 95e766e0c..7a6ae970d 100644 --- a/docs/blog/reading_lists.md +++ b/docs/blog/reading_lists.md @@ -143,18 +143,18 @@ Published: 22.04.2023 at 11:43 ## See Also -* [`%[]` Array Builder](../parser/create-array.md): - Quickly generate arrays -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays
diff --git a/docs/blog/split_personalities.md b/docs/blog/split_personalities.md index 8357dff38..ee2124015 100644 --- a/docs/blog/split_personalities.md +++ b/docs/blog/split_personalities.md @@ -228,14 +228,14 @@ Published: 02.10.2021 at 22:42 ## See Also +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Reading Lists From The Command Line](../blog/reading_lists.md): How hard can it be to read a list of data from the command line? If your list is line delimited then it should be easy. However what if your list is a JSON array? This post will explore how to work with lists in a different command line environments. * [Rosetta Stone](../user-guide/rosetta-stone.md): A tabulated list of Bashism's and their equivalent Murex syntax -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition
diff --git a/docs/changelog/v2.0.md b/docs/changelog/v2.0.md index 757a4da04..1490ccb1b 100644 --- a/docs/changelog/v2.0.md +++ b/docs/changelog/v2.0.md @@ -35,16 +35,16 @@ Published: 17.04.2021 at 12:49 What's different about Murex's interactive shell? * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking -* [fs.open](../commands/open.md): +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): + Murex's package manager +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [fs.open.image](../commands/open-image.md): +* [Render Image In Terminal (`open-image`)](../commands/open-image.md): Renders bitmap image data on your terminal -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.packages (`murex-package`)](../commands/murex-package.md): - Murex's package manager +* [Spellcheck](../integrations/spellcheck.md): + How to enable inline spellchecking
diff --git a/docs/changelog/v2.1.md b/docs/changelog/v2.1.md index 45ddd63bd..dc1909536 100644 --- a/docs/changelog/v2.1.md +++ b/docs/changelog/v2.1.md @@ -77,24 +77,24 @@ Published: 30.04.2021 at 10:00 ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines * [`*` (generic)](../types/generic.md): generic (primitive) * [`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): Read from a data type one array element at a time and return the elements contents and data type * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`foreach`](../commands/foreach.md): - Iterate through an array * [`jsonl`](../types/jsonl.md): JSON Lines -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines
diff --git a/docs/changelog/v2.10.md b/docs/changelog/v2.10.md index d0c9dc344..0bc361e5a 100644 --- a/docs/changelog/v2.10.md +++ b/docs/changelog/v2.10.md @@ -50,34 +50,34 @@ Published: 01.08.2022 at 20:10 * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Globbing (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [List Filesystem Objects (`f`)](../commands/f.md): + Lists or filters file system objects (eg files) * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up +* [Regex Matches (`rx`)](../commands/rx.md): + Regexp pattern matching for file system objects (eg `.*\\.txt`) * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex * [Spellcheck](../integrations/spellcheck.md): How to enable inline spellchecking +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes -* [`[ ..Range ]`](../parser/range.md): - Outputs a ranged subset of data from stdin -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [fs.files (`f`)](../commands/f.md): - Lists or filters file system objects (eg files) -* [fs.glob (`g`)](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [fs.regex (`rx`)](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v2.11.md b/docs/changelog/v2.11.md index a75725658..c692b34c1 100644 --- a/docs/changelog/v2.11.md +++ b/docs/changelog/v2.11.md @@ -52,22 +52,22 @@ Published: 12.09.2022 at 08:10 ## See Also +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Change Directory (`cd`)](../commands/cd.md): + Change (working) directory +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Print Map / Structure Keys (`struct-keys`)](../commands/struct-keys.md): + Outputs all the keys in a structure as a file path * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`cd`](../commands/cd.md): - Change (working) directory +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [struct.keys](../commands/struct-keys.md): - Outputs all the keys in a structure as a file path -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/changelog/v2.2.md b/docs/changelog/v2.2.md index 115ddaa40..aaad04c76 100644 --- a/docs/changelog/v2.2.md +++ b/docs/changelog/v2.2.md @@ -62,10 +62,10 @@ Published: 21.06.2021 at 21:51 ## See Also +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground * [`*` (generic)](../types/generic.md): generic (primitive) -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground
diff --git a/docs/changelog/v2.3.md b/docs/changelog/v2.3.md index a9dc28186..13754e47b 100644 --- a/docs/changelog/v2.3.md +++ b/docs/changelog/v2.3.md @@ -80,14 +80,14 @@ Published: 26.09.2021 at 11:33 ## See Also +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex
diff --git a/docs/changelog/v2.4.md b/docs/changelog/v2.4.md index 296a26a2b..417294b55 100644 --- a/docs/changelog/v2.4.md +++ b/docs/changelog/v2.4.md @@ -98,30 +98,30 @@ Published: 09.12.2021 at 08:00 * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/changelog/v2.5.md b/docs/changelog/v2.5.md index ec31483b9..71d37cb3c 100644 --- a/docs/changelog/v2.5.md +++ b/docs/changelog/v2.5.md @@ -56,26 +56,26 @@ Published: 12.02.2022 at 16:16 ## See Also +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [io.pipe (``)](../commands/namedpipe.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): Reads from a Murex named pipe -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated)
diff --git a/docs/changelog/v2.6.md b/docs/changelog/v2.6.md index 41745ad97..1541ce41e 100644 --- a/docs/changelog/v2.6.md +++ b/docs/changelog/v2.6.md @@ -48,14 +48,14 @@ Published: 26.02.2022 at 18:33 ## See Also -* [`while`](../commands/while.md): +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines +* [Loop While (`while`)](../commands/while.md): Loop until condition false -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index 5a8a587df..568251290 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -78,22 +78,22 @@ Published: 15.05.2022 at 22:49 ## See Also +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Read User Input (`read`)](../commands/read.md): + `read` a line of input from the user and store as a variable * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes * [`event`](../commands/event.md): Event driven programming for shell scripts * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.read](../commands/read.md): - `read` a line of input from the user and store as a variable -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open`
diff --git a/docs/changelog/v2.8.md b/docs/changelog/v2.8.md index 67dc8d26e..81301df8e 100644 --- a/docs/changelog/v2.8.md +++ b/docs/changelog/v2.8.md @@ -36,18 +36,18 @@ Published: 23.05.2022 at 22:23 ## See Also +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`jsonc`](../types/jsonc.md): Concatenated JSON * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block
diff --git a/docs/changelog/v2.9.md b/docs/changelog/v2.9.md index 0eaffe1aa..6bbd6d77a 100644 --- a/docs/changelog/v2.9.md +++ b/docs/changelog/v2.9.md @@ -58,34 +58,34 @@ Published: 15.07.2022 at 20:35 ## See Also +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists * [`>>` Append File](../parser/file-append.md): Writes stdin to disk - appending contents if file already exists -* [`[ ..Range ]`](../parser/range.md): - Outputs a ranged subset of data from stdin -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block
diff --git a/docs/changelog/v3.0.md b/docs/changelog/v3.0.md index 8ba5f848a..169116477 100644 --- a/docs/changelog/v3.0.md +++ b/docs/changelog/v3.0.md @@ -98,34 +98,34 @@ Published: 31.12.2022 at 08:10 ## See Also -* [`[ ..Range ]`](../parser/range.md): - Outputs a ranged subset of data from stdin -* [`break`](../commands/break.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Download File (`getfile`)](../commands/getfile.md): + Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`continue`](../commands/continue.md): - Terminate process of a block within a caller function -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators -* [`foreach`](../commands/foreach.md): +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [`murex-docs`](../commands/murex-docs.md): +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [index](../parser/item-index.md): - Outputs an element from an array, map or table -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Next Iteration (`continue`)](../commands/continue.md): + Terminate process of a block within a caller function +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators +* [index](../parser/item-index.md): + Outputs an element from an array, map or table
diff --git a/docs/changelog/v3.1.md b/docs/changelog/v3.1.md index dd8ff6297..847cc4945 100644 --- a/docs/changelog/v3.1.md +++ b/docs/changelog/v3.1.md @@ -52,7 +52,7 @@ Published: 12.02.2023 at 21:22 * [Rosetta Stone](../user-guide/rosetta-stone.md): A tabulated list of Bashism's and their equivalent Murex syntax -* [`switch`](../commands/switch.md): +* [Switch Conditional (`switch`)](../commands/switch.md): Blocks of cascading conditionals
diff --git a/docs/changelog/v4.0.md b/docs/changelog/v4.0.md index 36508467d..c9e823856 100644 --- a/docs/changelog/v4.0.md +++ b/docs/changelog/v4.0.md @@ -74,8 +74,12 @@ Published: 26.03.2023 at 17:50 ## See Also +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`%[]` Array Builder](../parser/create-array.md): @@ -88,10 +92,6 @@ Published: 26.03.2023 at 17:50 Structured array for working with `$PATH` style data * [`string` (stringing)](../types/str.md): string (primitive) -* [shell.function](../commands/function.md): - Define a function block -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/changelog/v4.2.md b/docs/changelog/v4.2.md index 5db4fbd56..b0a256537 100644 --- a/docs/changelog/v4.2.md +++ b/docs/changelog/v4.2.md @@ -68,28 +68,28 @@ Published: 19.06.2023 at 23:15 ## See Also -* [Interactive Shell](../user-guide/interactive-shell.md): - What's different about Murex's interactive shell? -* [Terminal Hotkeys](../user-guide/terminal-keys.md): - A list of all the terminal hotkeys and their uses -* [`foreach`](../commands/foreach.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`while`](../commands/while.md): +* [Interactive Shell](../user-guide/interactive-shell.md): + What's different about Murex's interactive shell? +* [Loop While (`while`)](../commands/while.md): Loop until condition false -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.method](../commands/method.md): - Define a methods supported data-types +* [Terminal Hotkeys](../user-guide/terminal-keys.md): + A list of all the terminal hotkeys and their uses
diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index 01f0ff76f..6b9ab77b3 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -28,14 +28,14 @@ Published: 02.07.2023 at 09:55 ## See Also +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`event`](../commands/event.md): Event driven programming for shell scripts * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/changelog/v4.4.md b/docs/changelog/v4.4.md index 19ed2a5ec..822678b67 100644 --- a/docs/changelog/v4.4.md +++ b/docs/changelog/v4.4.md @@ -134,8 +134,24 @@ Published: 27.07.2023 at 23:12 ## See Also +* [Exit Function (`return`)](../commands/return.md): + Exits current function scope * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where +* [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): + Parses man page files for command line flags +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Round Number (`round`)](../commands/round.md): + Round a number by a user defined precision +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): @@ -148,22 +164,6 @@ Published: 27.07.2023 at 23:12 Floating point number (primitive) * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion -* [`return`](../commands/return.md): - Exits current function scope -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [help.man.flags](../commands/man-get-flags.md): - Parses man page files for command line flags -* [num.round: `round`](../commands/round.md): - Round a number by a user defined precision -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block
diff --git a/docs/changelog/v5.0.md b/docs/changelog/v5.0.md index 0ddbfa6b6..3a9330d1c 100644 --- a/docs/changelog/v5.0.md +++ b/docs/changelog/v5.0.md @@ -85,10 +85,22 @@ Published: 07.09.2023 at 00:12 ## See Also +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where +* [Location Of Command (`which`)](../commands/which.md): + Locate command origin * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): + Murex's package manager +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope * [`COLUMNS` (int)](../variables/columns.md): @@ -103,22 +115,10 @@ Published: 07.09.2023 at 00:12 Event driven programming for shell scripts * [`float` (floating point number)](../types/float.md): Floating point number (primitive) -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins * [`onSignalReceived`](../events/onsignalreceived.md): Trap OS signals * [`signal`](../commands/signal.md): Sends a signal RPC -* [`which`](../commands/which.md): - Locate command origin -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.packages (`murex-package`)](../commands/murex-package.md): - Murex's package manager
diff --git a/docs/changelog/v5.1.md b/docs/changelog/v5.1.md index b0a5aa00d..32b5fab84 100644 --- a/docs/changelog/v5.1.md +++ b/docs/changelog/v5.1.md @@ -48,7 +48,7 @@ Published: 09.10.2023 at 22:13 ## See Also -* [shell.debug](../commands/debug.md): +* [Debugging Mode (`debug`)](../commands/debug.md): Debugging information
diff --git a/docs/changelog/v5.2.md b/docs/changelog/v5.2.md index 045e27f07..bcd227086 100644 --- a/docs/changelog/v5.2.md +++ b/docs/changelog/v5.2.md @@ -78,8 +78,16 @@ Published: 18.11.2023 at 20:59 ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground * [Install](../Murex/INSTALL.md): Installation instructions * [Job Control](../user-guide/job-control.md): @@ -88,14 +96,6 @@ Published: 18.11.2023 at 20:59 A list of all the terminal hotkeys and their uses * [`[{ Lambda }]`](../parser/lambda.md): Iterate through structured data -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [shell.debug](../commands/debug.md): - Debugging information -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/changelog/v5.3.md b/docs/changelog/v5.3.md index 4e605ded5..188600191 100644 --- a/docs/changelog/v5.3.md +++ b/docs/changelog/v5.3.md @@ -91,16 +91,16 @@ Published: 02.01.2024 at 15:45 * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex -* [`is-null`](../commands/is-null.md): +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v6.0.md b/docs/changelog/v6.0.md index dc0037f80..2dd38426c 100644 --- a/docs/changelog/v6.0.md +++ b/docs/changelog/v6.0.md @@ -46,16 +46,16 @@ Published: 17.02.2024 at 20:47 * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex -* [`is-null`](../commands/is-null.md): +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line
diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index 31b070796..6a239c598 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -148,14 +148,28 @@ Published: 17.06.2024 at 22:54 How to enable ChatGPT hints * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Get Request (`get`)](../commands/get.md): + Makes a standard HTTP request and returns the result as a JSON object * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Man-Page Summary (`man-summary`)](../commands/man-summary.md): + Outputs a man page summary of a command +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object * [`key-code`](../commands/key-code.md): Returns character sequences for any key pressed (ie sent from the terminal) * [`onKeyPress`](../events/onkeypress.md): @@ -164,20 +178,6 @@ Published: 17.06.2024 at 22:54 Full screen previews for files and command documentation * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [help.man.summary](../commands/man-summary.md): - Outputs a man page summary of a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.debug](../commands/debug.md): - Debugging information -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values)
diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 310f3f161..2c9a36354 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -88,16 +88,16 @@ Published: 19.07.2024 at 08:54 How to enable ChatGPT hints * [Contributing](../Murex/CONTRIBUTING.md): Guide to contributing to Murex +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): + Murex's package manager +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [shell.packages (`murex-package`)](../commands/murex-package.md): - Murex's package manager -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value
diff --git a/docs/commands/2darray.md b/docs/commands/2darray.md index cf064ea22..85929822f 100644 --- a/docs/commands/2darray.md +++ b/docs/commands/2darray.md @@ -1,4 +1,4 @@ -# struct.new.2darray +# Create 2d Array (`2darray`) > Create a 2D JSON array from multiple input sources @@ -94,35 +94,34 @@ ## Synonyms * `2darray` -* `struct.new.2darray` ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): + Creates a map from two data sources +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [`json`](../types/json.md): - JavaScript Object Notation (JSON) -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [struct.new.map (`map`)](../commands/map.md): - Creates a map from two data sources +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`json`](../types/json.md): + JavaScript Object Notation (JSON)
diff --git a/docs/commands/README.md b/docs/commands/README.md index 66efac38d..1b4928538 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -1,4 +1,4 @@ -# Builtins Reference +# Command Reference This section is a glossary of Murex builtin commands. @@ -32,257 +32,408 @@ to return the same markdown-formatted document as those listed below. eg ``` murex-docs trypipe -``` +``` ## Pages -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`args` ](../commands/args.md): - Command line flag parser for Murex shell scripting -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`catch`](../commands/catch.md): - Handles the exception code raised by `try` or `trypipe` -* [`cd`](../commands/cd.md): - Change (working) directory -* [`continue`](../commands/continue.md): - Terminate process of a block within a caller function -* [`die`](../commands/die.md): - Terminate murex with an exit number of 1 (deprecated) -* [`event`](../commands/event.md): - Event driven programming for shell scripts -* [`exit`](../commands/exit.md): - Exit murex -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators -* [`false`](../commands/false.md): - Returns a `false` value -* [`for`](../commands/for.md): - A more familiar iteration loop to existing developers -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`formap`](../commands/formap.md): - Iterate through a map or other collection of data -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [`get-type`](../commands/get-type.md): - Returns the data-type of a variable or pipe -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [`key-code`](../commands/key-code.md): - Returns character sequences for any key pressed (ie sent from the terminal) -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [`null`](../commands/devnull.md): - null function. Similar to /dev/null -* [`or`](../commands/or.md): - Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [`rand`](../commands/rand.md): - Random field generator -* [`return`](../commands/return.md): - Exits current function scope -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`signal`](../commands/signal.md): - Sends a signal RPC -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`tabulate`](../commands/tabulate.md): - Table transformation tools -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [`time`](../commands/time.md): - Returns the execution run time of a command or block -* [`true`](../commands/true.md): - Returns a `true` value -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): - Checks state of each function in a pipeline and exits block on error -* [`type`](../commands/type.md): - Command type (function, builtin, alias, etc) -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [`which`](../commands/which.md): - Locate command origin -* [`while`](../commands/while.md): - Loop until condition false -* [escape.cli](../commands/esccli.md): - Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): - Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): - Encode or decodes text for the URL -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [fs.files (`f`)](../commands/f.md): - Lists or filters file system objects (eg files) -* [fs.glob (`g`)](../commands/g.md): + +### Input / Output Streams + +Commands for managing the flow of data between different processes and/or the terminal screen. + +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Get Pipe Status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Read User Input (`read`)](../commands/read.md): + `read` a line of input from the user and store as a variable +* [Read With Type (`tread`) (removed 7.x)](../commands/tread.md): + `read` a line of input from the user and store as a user defined *typed* variable (deprecated) +* [Render Image In Terminal (`open-image`)](../commands/open-image.md): + Renders bitmap image data on your terminal +* [`(brace quote)`](../parser/brace-quote-func.md): + Write a string to the stdout without new line (deprecated) + +### Filesystem Operations + +Commands for working with files and/or the filesystem. + +* [Create Temporary File (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.lockfile](../commands/lockfile.md): +* [List Filesystem Objects (`f`)](../commands/f.md): + Lists or filters file system objects (eg files) +* [Lock Files (`lockfile`)](../commands/lockfile.md): Create and manage lock files -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [fs.open.image](../commands/open-image.md): - Renders bitmap image data on your terminal -* [fs.regex (`rx`)](../commands/rx.md): +* [Regex Matches (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [fs.tmpfile (`tmp`)](../commands/tmp.md): - Create a temporary file and write to it -* [fs.truncate (`>`)](../commands/file-truncate.md): +* [Render Image In Terminal (`open-image`)](../commands/open-image.md): + Renders bitmap image data on your terminal +* [Truncate File (`>`)](../parser/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [help.man.flags](../commands/man-get-flags.md): - Parses man page files for command line flags -* [help.man.summary](../commands/man-summary.md): - Outputs a man page summary of a command -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [io.out](../commands/out.md): + +### Defined by POSIX + +Commands defined by POSIX. + +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Change Directory (`cd`)](../commands/cd.md): + Change (working) directory +* [Display Command Type (`type`)](../commands/type.md): + Command type (function, builtin, alias, etc) +* [False (`false`)](../commands/false.md): + Returns a `false` value +* [Location Of Command (`which`)](../commands/which.md): + Locate command origin +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [io.read](../commands/read.md): +* [Processes Execution Time (`time`)](../commands/time.md): + Returns the execution run time of a command or block +* [Read User Input (`read`)](../commands/read.md): `read` a line of input from the user and store as a variable -* [io.status (`pt`)](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [list.append](../commands/append.md): +* [True (`true`)](../commands/true.md): + Returns a `true` value +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators + +### List / Array Editing + +Commands that operate against a list or array. + +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Append To List (`append`)](../commands/append.md): Add data to the end of an array -* [list.case](../commands/list.case.md): +* [Change Text Case (`list.case`)](../commands/list.case.md): Changes the character case of a string or all elements in an array -* [list.join](../commands/mjoin.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Join Array To String (`mjoin`)](../commands/mjoin.md): Joins a list or array into a single string -* [list.left](../commands/left.md): +* [Left Sub-String (`left`)](../commands/left.md): Left substring every item in a list -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.prepend](../commands/prepend.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.right](../commands/right.md): +* [Right Sub-String (`right`)](../commands/right.md): Right substring every item in a list -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [num.round: `round`](../commands/round.md): - Round a number by a user defined precision -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.exitnum](../commands/exitnum.md): - Output the exit number of the previous process -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): - Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.builtins.exist](../commands/bexists.md): - Check which builtins exist -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.debug](../commands/debug.md): - Debugging information -* [shell.function](../commands/function.md): - Define a function block -* [shell.history](../commands/history.md): - Outputs murex's command history -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.packages (`murex-package`)](../commands/murex-package.md): - Murex's package manager -* [shell.private](../commands/private.md): - Define a private function block -* [shell.rescan.path](../commands/murex-update-exe-list.md): - Forces Murex to rescan $PATH looking for executables -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.summary](../commands/summary.md): - Defines a summary help text for a command -* [shell.version](../commands/version.md): - Get Murex version -* [str.datetime: `datetime`](../commands/datetime.md): +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) + +### String Manipulation + +Commands for working with strings. +> All list based tools also work with strings. + +* [Change Text Case (`list.case`)](../commands/list.case.md): + Changes the character case of a string or all elements in an array +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) -* [str.split](../commands/jsplit.md): +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Generate Random Sequence (`rand`)](../commands/rand.md): + Random field generator +* [Left Sub-String (`left`)](../commands/left.md): + Left substring every item in a list +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [Right Sub-String (`right`)](../commands/right.md): + Right substring every item in a list +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): + +### Numeric / Math Tools + +Commands for working with numerical data. + +* [Generate Random Sequence (`rand`)](../commands/rand.md): + Random field generator +* [Round Number (`round`)](../commands/round.md): + Round a number by a user defined precision +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators + +### Structured Data Management + +Commands for working with structured data such as maps, tables, arrays and other data formats that are present in documents such as CSV, JSON, YAML, TOML, Sexpr, CSV, etc. + +* [Alter Data Structure (`alter`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): +* [Count (`count`)](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [struct.keys](../commands/struct-keys.md): - Outputs all the keys in a structure as a file path -* [struct.new.2darray](../commands/2darray.md): +* [Create 2d Array (`2darray`)](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): +* [Create Map (`map`)](../commands/map.md): Creates a map from two data sources -* [sys.cpu.arch](../commands/cpuarch.md): +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Print Map / Structure Keys (`struct-keys`)](../commands/struct-keys.md): + Outputs all the keys in a structure as a file path +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Transformation Tools (`tabulate`)](../commands/tabulate.md): + Table transformation tools + +### Table Management + +Commands specifically for working with tabulated data. + +* [Add Heading (`addheading`)](../commands/addheading.md): + Adds headings to a table +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Transformation Tools (`tabulate`)](../commands/tabulate.md): + Table transformation tools + +### System Inspection + +Tools to inspect the host system. + +* [CPU Architecture (`cpuarch`)](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count](../commands/cpucount.md): +* [CPU Count (`cpucount`)](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os](../commands/os.md): - Output the auto-detected OS name -* [table.add.heading](../commands/addheading.md): - Adds headings to a table -* [var.env: `export`](../commands/export.md): +* [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): +* [Operating System (`os`)](../commands/os.md): + Output the auto-detected OS name + +### Shell / Murex Management + +Commands to manage the Murex shell session. + +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Command Line History (`history`)](../commands/history.md): + Outputs murex's command history +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): + Murex's package manager +* [Murex Version (`version`)](../commands/version.md): + Get Murex version +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): + Forces Murex to rescan $PATH looking for executables +* [Set Command Summary Hint (`summary`)](../commands/summary.md): + Defines a summary help text for a command +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`event`](../commands/event.md): + Event driven programming for shell scripts + +### String Escaping / Character Codes + +Commands to escape special characters in various different string formats. + +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input +* [`key-code`](../commands/key-code.md): + Returns character sequences for any key pressed (ie sent from the terminal) + +### Process Management + +Management of system processes and Murex FIDs. + +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): + Check which builtins exist +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Get Exit Code (`exitnum`)](../commands/exitnum.md): + Output the exit number of the previous process +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): + Terminate a running Murex function +* [Location Of Command (`which`)](../commands/which.md): + Locate command origin +* [Processes Execution Time (`time`)](../commands/time.md): + Returns the execution run time of a command or block +* [`signal`](../commands/signal.md): + Sends a signal RPC + +### Language And Scripting + +Various commands that enable control flow, error handling and other important characteristics that turn Murex into a functional programming language. + +* [Define Function Arguments (`args`)](../commands/args.md): + Command line flag parser for Murex shell scripting +* [Define Global (`global`)](../commands/global.md): Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [Exit Function (`return`)](../commands/return.md): + Exits current function scope +* [Exit Murex (`exit`)](../commands/exit.md): + Exit murex +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [Get Data Type (`get-type`)](../commands/get-type.md): + Returns the data-type of a variable or pipe +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): + Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Next Iteration (`continue`)](../commands/continue.md): + Terminate process of a block within a caller function +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Null (`null`)](../commands/devnull.md): + null function. Similar to /dev/null +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators + +### Error Handling + +Tools and control flow structures to handle errors. + +* [Caught Error Block (`catch`)](../commands/catch.md): + Handles the exception code raised by `try` or `trypipe` +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): + Checks state of each function in a pipeline and exits block on error +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code + +### Help and Hint Tools + +Tools for providing help and hints, useful when working inside the interactive shell. + +* [Man-Page Summary (`man-summary`)](../commands/man-summary.md): + Outputs a man page summary of a command +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): + Parses man page files for command line flags +* [Set Command Summary Hint (`summary`)](../commands/summary.md): + Defines a summary help text for a command + +### Uncategorised + +* [`murex-parser`](../commands/murex-parser.md): + Runs the Murex parser against a block of code +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated) +* [`die`](../commands/die.md): + Terminate murex with an exit number of 1 (deprecated) ## Optional Builtins +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines * [`!bz2`](../optional/bz2.md): Decompress a bz2 file * [`base64` ](../optional/base64.md): @@ -293,5 +444,3 @@ murex-docs trypipe Creates a QR code from stdin * [`sleep`](../optional/sleep.md): Suspends the shell for a number of seconds -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines diff --git a/docs/commands/a.md b/docs/commands/a.md index afed1a32f..9a753ba2e 100644 --- a/docs/commands/a.md +++ b/docs/commands/a.md @@ -1,6 +1,6 @@ -# list.new.str (`a`) +# Stream New List (`a`) -> A sophisticated yet simple way to build an array or list (mkarray) +> A sophisticated yet simple way to stream an array or list (mkarray) ## Description @@ -165,29 +165,28 @@ arrays. For more details on these please refer to the documents for each format * `a` * `mkarray` -* `list.new.str` ## See Also -* [`%[]` Array Builder](../parser/create-array.md): - Quickly generate arrays -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Reverse Array (`mtac`)](../commands/mtac.md): + Reverse the order of an array +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays * [`str` (string)](../types/str.md): string (primitive) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse (`mtac`)](../commands/mtac.md): - Reverse the order of an array -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/addheading.md b/docs/commands/addheading.md index fab8f5d2a..7b9d8bc08 100644 --- a/docs/commands/addheading.md +++ b/docs/commands/addheading.md @@ -1,4 +1,4 @@ -# table.add.heading +# Add Heading (`addheading`) > Adds headings to a table @@ -25,35 +25,34 @@ prepend to tables. ## Synonyms * `addheading` -* `table.new.heading` ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/alias.md b/docs/commands/alias.md index 98e0ebfdb..d55a28fc6 100644 --- a/docs/commands/alias.md +++ b/docs/commands/alias.md @@ -1,4 +1,4 @@ -# shell.alias +# Alias Pointer (`alias`) > Create an alias for a command @@ -119,34 +119,32 @@ You can override this order of precedence via the `fexec` and `exec` builtins. * `alias` * `!alias` -* `shell.alias` -* `!shell.alias` ## See Also -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [fs.glob (`g`)](../commands/g.md): +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [shell.function](../commands/function.md): - Define a function block -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.private](../commands/private.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Private Function (`private`)](../commands/private.md): Define a private function block -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated)
diff --git a/docs/commands/alter.md b/docs/commands/alter.md index 2fb54b7f7..f2d74fc79 100644 --- a/docs/commands/alter.md +++ b/docs/commands/alter.md @@ -1,4 +1,4 @@ -# struct.alter +# Alter Data Structure (`alter`) > Change a value within a structured data-type and pass that change along the pipeline without altering the original source input @@ -181,29 +181,28 @@ Marshallers are enabled at compile time from the `builtins/data-types` directory * `alter` * `~>` -* `struct.alter` ## See Also -* [`<~` Assign Or Merge](../parser/assign-or-merge.md): - Merges the right hand value to a variable on the left hand side (expression) -* [`[ Index ]`](../parser/item-index.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [shell.config](../commands/config.md): +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [`<~` Assign Or Merge](../parser/assign-or-merge.md): + Merges the right hand value to a variable on the left hand side (expression)
diff --git a/docs/commands/and.md b/docs/commands/and.md index f9aeee7e1..0dc15125a 100644 --- a/docs/commands/and.md +++ b/docs/commands/and.md @@ -1,4 +1,4 @@ -# `and` +# Logic And Statements (`and`) > Returns `true` or `false` depending on whether multiple conditions are met @@ -49,22 +49,26 @@ are unsuccessful. ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`false`](../commands/false.md): +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`or`](../commands/or.md): +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`true`](../commands/true.md): +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [True (`true`)](../commands/true.md): Returns a `true` value -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline +* [`&&` And Logical Operator](../parser/logical-and.md): + Continues next operation if previous operation passes +* [`||` Or Logical Operator](../parser/logical-or.md): + Continues next operation only if previous operation fails
diff --git a/docs/commands/append.md b/docs/commands/append.md index 9a349cda3..a22d8be16 100644 --- a/docs/commands/append.md +++ b/docs/commands/append.md @@ -1,4 +1,4 @@ -# list.append +# Append To List (`append`) > Add data to the end of an array @@ -43,34 +43,34 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Add Heading (`addheading`)](../commands/addheading.md): + Adds headings to a table +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [table.add.heading](../commands/addheading.md): - Adds headings to a table +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/args.md b/docs/commands/args.md index 545c4f9dd..53005479b 100644 --- a/docs/commands/args.md +++ b/docs/commands/args.md @@ -1,4 +1,4 @@ -# `args` +# Define Function Arguments (`args`) > Command line flag parser for Murex shell scripting diff --git a/docs/commands/autocomplete.md b/docs/commands/autocomplete.md index 9f4e63587..2fddece98 100644 --- a/docs/commands/autocomplete.md +++ b/docs/commands/autocomplete.md @@ -1,4 +1,4 @@ -# shell.autocomplete +# Tab Autocompletion (`autocomplete`) > Set definitions for tab-completion in the command line @@ -607,31 +607,30 @@ flags. ## Synonyms * `autocomplete` -* `shell.autocomplete` ## See Also -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`get-type`](../commands/get-type.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Get Data Type (`get-type`)](../commands/get-type.md): Returns the data-type of a variable or pipe -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [io.in (``)](../commands/stdin.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Read From Stdin (``)](../parser/stdin.md): Read the stdin belonging to the parent code block +* [Set Command Summary Hint (`summary`)](../commands/summary.md): + Defines a summary help text for a command +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block -* [shell.summary](../commands/summary.md): - Defines a summary help text for a command
diff --git a/docs/commands/bexists.md b/docs/commands/bexists.md index eeb5c4bfe..ed91c8e83 100644 --- a/docs/commands/bexists.md +++ b/docs/commands/bexists.md @@ -1,4 +1,4 @@ -# shell.builtins.exist +# Check Builtin Exists (`bexists`) > Check which builtins exist @@ -45,11 +45,11 @@ that reason alone it has been spared from the axe. ## See Also +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/bg.md b/docs/commands/bg.md index 46792ea62..013c3c084 100644 --- a/docs/commands/bg.md +++ b/docs/commands/bg.md @@ -1,4 +1,4 @@ -# proc.bg +# Background Process (`bg`) > Run processes in the background @@ -36,23 +36,22 @@ cross platform while `bg int` currently does not work on Windows nor Plan 9. ## Synonyms * `bg` -* `proc.bg` ## See Also -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): Lists all running functions within the current Murex session -* [proc.fg](../commands/fg.md): +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session
diff --git a/docs/commands/break.md b/docs/commands/break.md index 4a8d1abeb..f16f5c26f 100644 --- a/docs/commands/break.md +++ b/docs/commands/break.md @@ -1,4 +1,4 @@ -# `break` +# Exit Block (`break`) > Terminate execution of a block within your processes scope @@ -98,24 +98,24 @@ Error in `break` (7,17): no block found named `bar` within the scope of `foo` ## See Also -* [`continue`](../commands/continue.md): - Terminate process of a block within a caller function -* [`exit`](../commands/exit.md): +* [Exit Function (`return`)](../commands/return.md): + Exits current function scope +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`return`](../commands/return.md): - Exits current function scope -* [io.out](../commands/out.md): +* [Next Iteration (`continue`)](../commands/continue.md): + Terminate process of a block within a caller function +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block
diff --git a/docs/commands/cast.md b/docs/commands/cast.md index 623583589..defdb0e2b 100644 --- a/docs/commands/cast.md +++ b/docs/commands/cast.md @@ -1,4 +1,4 @@ -# `cast` +# Define Type (`cast`) > Alters the data-type of the previous function without altering its output @@ -66,14 +66,14 @@ instead. ## See Also -* [`%{}` Object Builder](../parser/create-object.md): - Quickly generate objects (dictionaries / maps) -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [`%{}` Object Builder](../parser/create-object.md): + Quickly generate objects (dictionaries / maps)
diff --git a/docs/commands/catch.md b/docs/commands/catch.md index 14bbd40ff..735bf53b9 100644 --- a/docs/commands/catch.md +++ b/docs/commands/catch.md @@ -1,4 +1,4 @@ -# `catch` +# Caught Error Block (`catch`) > Handles the exception code raised by `try` or `trypipe` @@ -48,24 +48,24 @@ catch { ## See Also +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): + Checks state of each function in a pipeline and exits block on error +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Switch Conditional (`switch`)](../commands/switch.md): Blocks of cascading conditionals -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): - Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number
diff --git a/docs/commands/cd.md b/docs/commands/cd.md index 0c69a9815..a46958dae 100644 --- a/docs/commands/cd.md +++ b/docs/commands/cd.md @@ -1,4 +1,4 @@ -# `cd` +# Change Directory (`cd`) > Change (working) directory @@ -79,10 +79,10 @@ config set shell auto-cd true ## See Also +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block
diff --git a/docs/commands/config.md b/docs/commands/config.md index 6aee2434d..40d37516f 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -1,4 +1,4 @@ -# shell.config +# Shell Configuration And Settings (`config`) > Query or define Murex runtime settings @@ -231,38 +231,36 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, * `config` * `!config` -* `shell.config` -* `!shell.config` ## See Also -* [`%{}` Object Builder](../parser/create-object.md): - Quickly generate objects (dictionaries / maps) -* [`[ Index ]`](../parser/item-index.md): +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Download File (`getfile`)](../commands/getfile.md): + Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`event`](../commands/event.md): - Event driven programming for shell scripts -* [`get`](../commands/get.md): +* [Get Request (`get`)](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.str (`match`)](../commands/match.md): +* [Match String (`match`)](../commands/match.md): Match an exact value in an array -* [shell.function](../commands/function.md): +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Public Function (`function`)](../commands/function.md): Define a function block -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [`%{}` Object Builder](../parser/create-object.md): + Quickly generate objects (dictionaries / maps) +* [`event`](../commands/event.md): + Event driven programming for shell scripts
diff --git a/docs/commands/continue.md b/docs/commands/continue.md index 7ad6e55cc..4f3d46e8a 100644 --- a/docs/commands/continue.md +++ b/docs/commands/continue.md @@ -1,4 +1,4 @@ -# `continue` +# Next Iteration (`continue`) > Terminate process of a block within a caller function @@ -76,24 +76,24 @@ Error in `continue` (7,17): no block found named `bar` within the scope of `foo` ## See Also -* [`break`](../commands/break.md): +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`exit`](../commands/exit.md): +* [Exit Function (`return`)](../commands/return.md): + Exits current function scope +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`return`](../commands/return.md): - Exits current function scope -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block
diff --git a/docs/commands/count.md b/docs/commands/count.md index 2b7dfdad7..b67a70a5f 100644 --- a/docs/commands/count.md +++ b/docs/commands/count.md @@ -1,4 +1,4 @@ -# struct.count +# Count (`count`) > Count items in a map, list or array @@ -137,39 +137,38 @@ unique count should be one less than the total count: * `count` * `len` -* `struct.count` ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): + Creates a map from two data sources +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.new.map (`map`)](../commands/map.md): - Creates a map from two data sources +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/cpuarch.md b/docs/commands/cpuarch.md index b9c484ae7..23655845e 100644 --- a/docs/commands/cpuarch.md +++ b/docs/commands/cpuarch.md @@ -1,4 +1,4 @@ -# sys.cpu.arch +# CPU Architecture (`cpuarch`) > Output the hosts CPU architecture @@ -27,9 +27,9 @@ amd64 ## See Also -* [sys.cpu.count](../commands/cpucount.md): +* [CPU Count (`cpucount`)](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os](../commands/os.md): +* [Operating System (`os`)](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/cpucount.md b/docs/commands/cpucount.md index 13f1d7cae..7e49b3d53 100644 --- a/docs/commands/cpucount.md +++ b/docs/commands/cpucount.md @@ -1,4 +1,4 @@ -# sys.cpu.count +# CPU Count (`cpucount`) > Output the number of CPU cores available on your host @@ -27,9 +27,9 @@ cpucount -> ## See Also -* [sys.cpu.arch](../commands/cpuarch.md): +* [CPU Architecture (`cpuarch`)](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.os](../commands/os.md): +* [Operating System (`os`)](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/datetime.md b/docs/commands/datetime.md index baf57d41e..a7d5e4bdb 100644 --- a/docs/commands/datetime.md +++ b/docs/commands/datetime.md @@ -1,4 +1,4 @@ -# str.datetime: `datetime` +# Date And Time Conversion (`datetime`) > A date and/or time conversion tool (like `printf` but for date and time values) @@ -89,10 +89,10 @@ required. ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/debug.md b/docs/commands/debug.md index d3a2c3b20..19ac0f660 100644 --- a/docs/commands/debug.md +++ b/docs/commands/debug.md @@ -1,4 +1,4 @@ -# shell.debug +# Debugging Mode (`debug`) > Debugging information @@ -189,15 +189,14 @@ debug panic ## Synonyms * `debug` -* `shell.debug` ## See Also -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts
diff --git a/docs/commands/devnull.md b/docs/commands/devnull.md index 91047baa3..a02e79a59 100644 --- a/docs/commands/devnull.md +++ b/docs/commands/devnull.md @@ -1,4 +1,4 @@ -# `null` +# Null (`null`) > null function. Similar to /dev/null @@ -35,12 +35,12 @@ use the named pipe property rather than piping to null: ## See Also -* [`break`](../commands/break.md): +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope +* [Exit Murex (`exit`)](../commands/exit.md): + Exit murex * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) -* [`exit`](../commands/exit.md): - Exit murex
diff --git a/docs/commands/die.md b/docs/commands/die.md index 7ece07d5c..e810628de 100644 --- a/docs/commands/die.md +++ b/docs/commands/die.md @@ -23,11 +23,11 @@ die ## See Also -* [`break`](../commands/break.md): +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`exit`](../commands/exit.md): +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [`null`](../commands/devnull.md): +* [Null (`null`)](../commands/devnull.md): null function. Similar to /dev/null
diff --git a/docs/commands/err.md b/docs/commands/err.md index afecc5f24..43ed2975b 100644 --- a/docs/commands/err.md +++ b/docs/commands/err.md @@ -1,4 +1,4 @@ -# io.err +# Error String (`err`) > Print a line to the stderr @@ -52,35 +52,34 @@ a new Murex named pipe. ## Synonyms * `err` -* `io.err` ## See Also * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences -* [`(brace quote)`](../parser/brace-quote-func.md): - Write a string to the stdout without new line (deprecated) -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe](../commands/pipe.md): +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Create Named Pipe (`pipe`)](../commands/pipe.md): Manage Murex named pipes -* [io.out](../commands/out.md): +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Get Pipe Status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [io.status (`pt`)](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [proc.bg](../commands/bg.md): - Run processes in the background -* [struct.json.pretty](../commands/pretty.md): +* [Prettify JSON](../commands/pretty.md): Prettifies JSON to make it human readable +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [`(brace quote)`](../parser/brace-quote-func.md): + Write a string to the stdout without new line (deprecated) +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/escape.md b/docs/commands/escape.md index f5db4bb8c..e441a1639 100644 --- a/docs/commands/escape.md +++ b/docs/commands/escape.md @@ -1,4 +1,4 @@ -# escape.quote +# Quote String (`escape`) > Escape or unescape input @@ -43,17 +43,15 @@ escape string to escape -> * `escape` * `!escape` -* `escape.quote` -* `!escape.quote` ## See Also -* [escape.cli](../commands/esccli.md): +* [Escape Command Line String (`esccli`)](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): +* [Escape HTML (`eschtml`)](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.url](../commands/escurl.md): +* [Escape URL (`escurl`)](../commands/escurl.md): Encode or decodes text for the URL
diff --git a/docs/commands/esccli.md b/docs/commands/esccli.md index 867ca70d0..9b09307da 100644 --- a/docs/commands/esccli.md +++ b/docs/commands/esccli.md @@ -1,4 +1,4 @@ -# escape.cli +# Escape Command Line String (`esccli`) > Escapes an array so output is valid shell code @@ -44,23 +44,22 @@ out foo\$b\@r ## Synonyms * `esccli` -* `escape.cli` ## See Also -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [escape.html](../commands/eschtml.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Escape HTML (`eschtml`)](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): +* [Escape URL (`escurl`)](../commands/escurl.md): Encode or decodes text for the URL -* [io.out](../commands/out.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.alias](../commands/alias.md): - Create an alias for a command +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input
diff --git a/docs/commands/eschtml.md b/docs/commands/eschtml.md index fdf7f31de..f622be32c 100644 --- a/docs/commands/eschtml.md +++ b/docs/commands/eschtml.md @@ -1,4 +1,4 @@ -# escape.html +# Escape HTML (`eschtml`) > Encode or decodes text for HTML @@ -48,24 +48,22 @@ eschtml string to escape -> * `eschtml` * `!eschtml` -* `escape.html` -* `!escape.html` ## See Also -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): +* [Download File (`getfile`)](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [escape.cli](../commands/esccli.md): +* [Escape Command Line String (`esccli`)](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): +* [Escape URL (`escurl`)](../commands/escurl.md): Encode or decodes text for the URL +* [Get Request (`get`)](../commands/get.md): + Makes a standard HTTP request and returns the result as a JSON object +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input
diff --git a/docs/commands/escurl.md b/docs/commands/escurl.md index 3d138d540..50fa679f4 100644 --- a/docs/commands/escurl.md +++ b/docs/commands/escurl.md @@ -1,4 +1,4 @@ -# escape.url +# Escape URL (`escurl`) > Encode or decodes text for the URL @@ -48,23 +48,21 @@ out '%21%3F%20%3C%3E%0A' -> !escurl * `escurl` * `!escurl` -* `escape.url` -* `!escape.url` ## See Also -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): +* [Download File (`getfile`)](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [escape.cli](../commands/esccli.md): +* [Escape Command Line String (`esccli`)](../commands/esccli.md): Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): +* [Escape HTML (`eschtml`)](../commands/eschtml.md): Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): +* [Get Request (`get`)](../commands/get.md): + Makes a standard HTTP request and returns the result as a JSON object +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Quote String (`escape`)](../commands/escape.md): Escape or unescape input
diff --git a/docs/commands/event.md b/docs/commands/event.md index e6fde8f73..daaea2732 100644 --- a/docs/commands/event.md +++ b/docs/commands/event.md @@ -6,7 +6,7 @@ Create or destroy an event interrupt, -Each event will have subtilty different behaviour depending on the event itself +Each event will have subtly different behaviour depending on the event itself due to the differing roles of each event system. Therefore it is recommended that you read the docs on each event to understand its behaviour. @@ -105,15 +105,15 @@ onSecondsElapsed ## See Also -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block -* [shell.runtime](../commands/runtime.md): +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/exec.md b/docs/commands/exec.md index db5e5c4aa..bd19fc9db 100644 --- a/docs/commands/exec.md +++ b/docs/commands/exec.md @@ -1,4 +1,4 @@ -# exec.file: `exec` +# Execute External Command (`exec`) > Runs an executable @@ -75,28 +75,28 @@ alias for `exec`. ## See Also -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [proc.fg](../commands/fg.md): +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): + Check which builtins exist +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.builtins.exist](../commands/bexists.md): - Check which builtins exist -* [shell.rescan.path](../commands/murex-update-exe-list.md): +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/exit.md b/docs/commands/exit.md index 0a8c089dd..f972ea20e 100644 --- a/docs/commands/exit.md +++ b/docs/commands/exit.md @@ -1,4 +1,4 @@ -# `exit` +# Exit Murex (`exit`) > Exit murex @@ -30,12 +30,12 @@ exit number ## See Also -* [`break`](../commands/break.md): +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope +* [Null (`null`)](../commands/devnull.md): + null function. Similar to /dev/null * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) -* [`null`](../commands/devnull.md): - null function. Similar to /dev/null
diff --git a/docs/commands/exitnum.md b/docs/commands/exitnum.md index feec42118..771714a61 100644 --- a/docs/commands/exitnum.md +++ b/docs/commands/exitnum.md @@ -1,4 +1,4 @@ -# proc.exitnum +# Get Exit Code (`exitnum`) > Output the exit number of the previous process @@ -22,15 +22,14 @@ exitnum -> ## Synonyms * `exitnum` -* `proc.exitnum` ## See Also -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts
diff --git a/docs/commands/export.md b/docs/commands/export.md index 44c91ccc0..e3d85d435 100644 --- a/docs/commands/export.md +++ b/docs/commands/export.md @@ -1,4 +1,4 @@ -# var.env: `export` +# Define Environmental Variable (`export`) > Define an environmental variable and set it's value @@ -271,6 +271,12 @@ bar ## See Also +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): @@ -281,12 +287,6 @@ bar Returns the right operand if the left operand is empty / undefined (expression) * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/expr.md b/docs/commands/expr.md index c8c31db4b..069a2afb6 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -14,7 +14,7 @@ underlying builtin: # idiomatic expressions 1 + 2 -# non-idiotmatic expressions +# non-idiomatic expressions expr 1 + 2 ``` @@ -310,6 +310,10 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { * [( expression )](../parser/expr-inlined.md): Inline expressions +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Strict Types In Expressions](../user-guide/strict-types.md): Expressions can auto-convert types or strictly honour data types * [`%[]` Array Builder](../parser/create-array.md): @@ -338,10 +342,6 @@ func executeExpression(tree *ParserT, order symbols.Exp) (err error) { Returns the right operand if the left operand is falsy (expression) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/f.md b/docs/commands/f.md index 8e5255029..c9be6e65a 100644 --- a/docs/commands/f.md +++ b/docs/commands/f.md @@ -1,4 +1,4 @@ -# fs.files (`f`) +# List Filesystem Objects (`f`) > Lists or filters file system objects (eg files) @@ -113,17 +113,16 @@ any matches from the `+` flags. ## Synonyms * `f` -* `fs.files` ## See Also -* [`json`](../types/json.md): - JavaScript Object Notation (JSON) -* [fs.glob (`g`)](../commands/g.md): +* [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [fs.regex (`rx`)](../commands/rx.md): +* [Regex Matches (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [`json`](../types/json.md): + JavaScript Object Notation (JSON)
diff --git a/docs/commands/false.md b/docs/commands/false.md index 09a5a6068..1c69d7842 100644 --- a/docs/commands/false.md +++ b/docs/commands/false.md @@ -1,4 +1,4 @@ -# `false` +# False (`false`) > Returns a `false` value @@ -38,15 +38,15 @@ You can suppress that with the silent flag: ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`or`](../commands/or.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`true`](../commands/true.md): +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [True (`true`)](../commands/true.md): Returns a `true` value
diff --git a/docs/commands/fexec.md b/docs/commands/fexec.md index 62e567c23..225e6c2f3 100644 --- a/docs/commands/fexec.md +++ b/docs/commands/fexec.md @@ -1,4 +1,4 @@ -# exec.* (`fexec`) +# Execute Shell Function or Builtin (`fexec`) > Execute a command or function, bypassing the usual order of precedence. @@ -80,30 +80,30 @@ alias to `fexec builtin` ## See Also -* [`event`](../commands/event.md): - Event driven programming for shell scripts -* [exec.file: `exec`](../commands/exec.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [exec.include (`source`)](../commands/source.md): +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`event`](../commands/event.md): + Event driven programming for shell scripts
diff --git a/docs/commands/fg.md b/docs/commands/fg.md index 01931d88b..096556614 100644 --- a/docs/commands/fg.md +++ b/docs/commands/fg.md @@ -1,4 +1,4 @@ -# proc.fg +# Foreground Process (`fg`) > Sends a background process into the foreground @@ -22,23 +22,22 @@ for Windows (due to the kernel not supporting the right signals) nor Plan 9. ## Synonyms * `fg` -* `proc.fg` ## See Also -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [proc.kill](../commands/fid-kill.md): - Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): + Terminate a running Murex function
diff --git a/docs/commands/fid-kill.md b/docs/commands/fid-kill.md index 38097aff7..96d6a220e 100644 --- a/docs/commands/fid-kill.md +++ b/docs/commands/fid-kill.md @@ -1,4 +1,4 @@ -# proc.kill +# Kill Function (`fid-kill`) > Terminate a running Murex function @@ -27,31 +27,30 @@ PID (process ID). You can obtain a FID from `fid-list`. ## Synonyms * `fid-kill` -* `proc.kill` ## See Also -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.builtins.exist](../commands/bexists.md): +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): Check which builtins exist -* [shell.rescan.path](../commands/murex-update-exe-list.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/fid-killall.md b/docs/commands/fid-killall.md index 73d8d3a59..1837c2e03 100644 --- a/docs/commands/fid-killall.md +++ b/docs/commands/fid-killall.md @@ -1,10 +1,11 @@ -# proc.kill.all +# Kill All In Session (`fid-killall`) -> Terminate _all_ running Murex functions +> Terminate all running Murex functions in current session ## Description -`fid-killall` will terminate _all_ running Murex functions. +`fid-killall` will terminate **all** processes and Murex functions in the +current session. ## Usage @@ -28,31 +29,30 @@ PID (process ID). You can obtain a FID from `fid-list`. ## Synonyms * `fid-killall` -* `proc.kill.all` ## See Also -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [proc.fg](../commands/fg.md): +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): + Check which builtins exist +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.builtins.exist](../commands/bexists.md): - Check which builtins exist -* [shell.rescan.path](../commands/murex-update-exe-list.md): +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex
diff --git a/docs/commands/fid-list.md b/docs/commands/fid-list.md index 593d2e31b..94733b563 100644 --- a/docs/commands/fid-list.md +++ b/docs/commands/fid-list.md @@ -1,4 +1,4 @@ -# proc.list +# Display Running Functions (`fid-list`) > Lists all running functions within the current Murex session @@ -60,38 +60,36 @@ include: * `fid-list` * `jobs` -* `proc.list` -* `proc.jobs` ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): + Check which builtins exist +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): + Terminate a running Murex function +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): + Forces Murex to rescan $PATH looking for executables +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`*` (generic)](../types/generic.md): generic (primitive) * [`csv`](../types/csv.md): CSV files (and other character delimited tables) * [`jsonl`](../types/jsonl.md): JSON Lines -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): - Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.builtins.exist](../commands/bexists.md): - Check which builtins exist -* [shell.rescan.path](../commands/murex-update-exe-list.md): - Forces Murex to rescan $PATH looking for executables
diff --git a/docs/commands/for.md b/docs/commands/for.md index 59ddd5135..bed008041 100644 --- a/docs/commands/for.md +++ b/docs/commands/for.md @@ -1,4 +1,4 @@ -# `for` +# For Loop (`for`) > A more familiar iteration loop to existing developers @@ -191,24 +191,24 @@ jsonl ## See Also -* [`break`](../commands/break.md): +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`while`](../commands/while.md): - Loop until condition false -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/foreach.md b/docs/commands/foreach.md index b898de682..59e56a4c4 100644 --- a/docs/commands/foreach.md +++ b/docs/commands/foreach.md @@ -1,4 +1,4 @@ -# `foreach` +# For Each In List (`foreach`) > Iterate through an array @@ -320,40 +320,40 @@ jsonl ## See Also -* [`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): - Read from a data type one array element at a time and return the elements contents and data type -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`cast`](../commands/cast.md): +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`for`](../commands/for.md): - A more familiar iteration loop to existing developers -* [`formap`](../commands/formap.md): +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [`if`](../commands/if.md): +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Left Sub-String (`left`)](../commands/left.md): + Left substring every item in a list +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md): + Read from a data type one array element at a time and return the elements contents and data type * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [`while`](../commands/while.md): - Loop until condition false * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [list.left](../commands/left.md): - Left substring every item in a list -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [shell.debug](../commands/debug.md): - Debugging information
diff --git a/docs/commands/formap.md b/docs/commands/formap.md index e8231a001..bd112018b 100644 --- a/docs/commands/formap.md +++ b/docs/commands/formap.md @@ -1,4 +1,4 @@ -# `formap` +# For Each In Map (`formap`) > Iterate through a map or other collection of data @@ -104,22 +104,22 @@ The following meta values are defined: ## See Also -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`break`](../commands/break.md): +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`for`](../commands/for.md): - A more familiar iteration loop to existing developers -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Transformation Tools (`tabulate`)](../commands/tabulate.md): + Table transformation tools * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`tabulate`](../commands/tabulate.md): - Table transformation tools -* [`while`](../commands/while.md): - Loop until condition false -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/format.md b/docs/commands/format.md index ac5c82aac..706859534 100644 --- a/docs/commands/format.md +++ b/docs/commands/format.md @@ -1,4 +1,4 @@ -# `format` +# Reformat Data type (`format`) > Reformat one data-type into another data-type @@ -24,14 +24,14 @@ Two: 2 ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type * [`Marshal()` (type)](../apis/Marshal.md): Converts structured memory into a structured file format (eg for stdio) * [`Unmarshal()` (type)](../apis/Unmarshal.md): Converts a structured file format into structured memory -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type
diff --git a/docs/commands/function.md b/docs/commands/function.md index 72f0db626..9adc2ce88 100644 --- a/docs/commands/function.md +++ b/docs/commands/function.md @@ -1,4 +1,4 @@ -# shell.function +# Public Function (`function`) > Define a function block @@ -240,42 +240,40 @@ You can override this order of precedence via the `fexec` and `exec` builtins. * `function` * `!function` -* `shell.function` -* `!shell.function` ## See Also -* [Reserved Variables](../user-guide/reserved-vars.md): - Special variables reserved by Murex -* [`args` ](../commands/args.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Function Arguments (`args`)](../commands/args.md): Command line flag parser for Murex shell scripting -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [fs.glob (`g`)](../commands/g.md): +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.private](../commands/private.md): - Define a private function block -* [shell.version](../commands/version.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Murex Version (`version`)](../commands/version.md): Get Murex version -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated)
diff --git a/docs/commands/g.md b/docs/commands/g.md index 4b9632552..35c13460d 100644 --- a/docs/commands/g.md +++ b/docs/commands/g.md @@ -1,4 +1,4 @@ -# fs.glob (`g`) +# Globbing (`g`) > Glob pattern matching for file system objects (eg `*.txt`) @@ -132,20 +132,18 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. * `g` * `!g` -* `fs.glob` -* `!fs.glob` ## See Also -* [fs.files (`f`)](../commands/f.md): +* [List Filesystem Objects (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.regex (`rx`)](../commands/rx.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Regex Matches (`rx`)](../commands/rx.md): Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [list.regex](../commands/regexp.md): +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array
diff --git a/docs/commands/get-type.md b/docs/commands/get-type.md index 0ce8b5e38..1d67f2c05 100644 --- a/docs/commands/get-type.md +++ b/docs/commands/get-type.md @@ -1,4 +1,4 @@ -# `get-type` +# Get Data Type (`get-type`) > Returns the data-type of a variable or pipe @@ -51,22 +51,22 @@ json ## See Also -* [Reserved Variables](../user-guide/reserved-vars.md): - Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): - How scoping works within Murex -* [io.new.pipe](../commands/pipe.md): +* [Create Named Pipe (`pipe`)](../commands/pipe.md): Manage Murex named pipes -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [shell.debug](../commands/debug.md): +* [Debugging Mode (`debug`)](../commands/debug.md): Debugging information -* [shell.function](../commands/function.md): +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [Public Function (`function`)](../commands/function.md): Define a function block -* [shell.runtime](../commands/runtime.md): +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Variable and Config Scoping](../user-guide/scoping.md): + How scoping works within Murex
diff --git a/docs/commands/get.md b/docs/commands/get.md index 7fd11c3f6..19e24a7b4 100644 --- a/docs/commands/get.md +++ b/docs/commands/get.md @@ -1,4 +1,4 @@ -# `get` +# Get Request (`get`) > Makes a standard HTTP request and returns the result as a JSON object @@ -95,15 +95,15 @@ This enables sane, repeatable and readable defaults. Read the documents on ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Download File (`getfile`)](../commands/getfile.md): + Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): +* [Post Request (`post`)](../commands/post.md): HTTP POST request with a JSON-parsable return -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/getfile.md b/docs/commands/getfile.md index 94626a7f5..bda1640f4 100644 --- a/docs/commands/getfile.md +++ b/docs/commands/getfile.md @@ -1,4 +1,4 @@ -# `getfile` +# Download File (`getfile`) > Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. @@ -76,13 +76,13 @@ This enables sane, repeatable and readable defaults. Read the documents on ## See Also -* [`get`](../commands/get.md): +* [Get Request (`get`)](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [shell.config](../commands/config.md): +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/global.md b/docs/commands/global.md index 92a718f4e..a5b55a60c 100644 --- a/docs/commands/global.md +++ b/docs/commands/global.md @@ -1,4 +1,4 @@ -# var.global: `global` +# Define Global (`global`) > Define a global variable and set it's value @@ -249,12 +249,20 @@ bar * `global` * `!global` -* `var.global` -* `!var.global` ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): @@ -263,18 +271,8 @@ bar Initiates or terminates a string (variables expanded) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/history.md b/docs/commands/history.md index 300a1ffbb..d0dee5b6e 100644 --- a/docs/commands/history.md +++ b/docs/commands/history.md @@ -1,4 +1,4 @@ -# shell.history +# Command Line History (`history`) > Outputs murex's command history @@ -42,14 +42,13 @@ The history file is typically located on disk in a file called `~/.murex.history ## Synonyms * `history` -* `shell.history` ## See Also -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/if.md b/docs/commands/if.md index da170f73d..06ff1cfd6 100644 --- a/docs/commands/if.md +++ b/docs/commands/if.md @@ -1,4 +1,4 @@ -# `if` +# If Conditional (`if`) > Conditional statement to execute different blocks of code depending on the result of the condition @@ -127,28 +127,28 @@ code block as false. Otherwise, it will be considered true. ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`false`](../commands/false.md): +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`or`](../commands/or.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`test`](../commands/test.md): +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [Shell Script Tests (`test`)](../commands/test.md): Murex's test framework - define tests, run tests and debug shell scripts -* [`true`](../commands/true.md): +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [True (`true`)](../commands/true.md): Returns a `true` value -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [shell.debug](../commands/debug.md): - Debugging information
diff --git a/docs/commands/is-null.md b/docs/commands/is-null.md index 5d3d7e224..27792738d 100644 --- a/docs/commands/is-null.md +++ b/docs/commands/is-null.md @@ -1,4 +1,4 @@ -# `is-null` +# Is Value Null (`is-null`) > Checks if a variable is null or undefined @@ -51,18 +51,18 @@ if { is-null foobar } then { ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/ja.md b/docs/commands/ja.md index 55a16ba9d..abece79a7 100644 --- a/docs/commands/ja.md +++ b/docs/commands/ja.md @@ -1,4 +1,4 @@ -# `ja` (mkarray) +# Create JSON Array (`ja`) > A sophisticated yet simply way to build a JSON array @@ -56,24 +56,24 @@ Please read the documentation on `a` for a more detailed breakdown on of ## See Also -* [`%[]` Array Builder](../parser/create-array.md): - Quickly generate arrays -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure +* [Reverse Array (`mtac`)](../commands/mtac.md): + Reverse the order of an array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse (`mtac`)](../commands/mtac.md): - Reverse the order of an array -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/jsplit.md b/docs/commands/jsplit.md index 2b39d667c..a223873d7 100644 --- a/docs/commands/jsplit.md +++ b/docs/commands/jsplit.md @@ -1,4 +1,4 @@ -# str.split +# Split String (`jsplit`) > Splits stdin into a JSON array based on a regex parameter @@ -43,30 +43,30 @@ unwanted "noise" is stripped from the output. ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create 2d Array (`2darray`)](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): + Creates a map from two data sources +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [struct.new.2darray](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): - Creates a map from two data sources +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/key-code.md b/docs/commands/key-code.md index 07ced729b..68b5f83af 100644 --- a/docs/commands/key-code.md +++ b/docs/commands/key-code.md @@ -59,12 +59,12 @@ event onKeyPress close=$key { * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type * [`event`](../commands/event.md): Event driven programming for shell scripts * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type
diff --git a/docs/commands/left.md b/docs/commands/left.md index aad353e80..9067d1c0b 100644 --- a/docs/commands/left.md +++ b/docs/commands/left.md @@ -1,4 +1,4 @@ -# list.left +# Left Sub-String (`left`) > Left substring every item in a list @@ -56,24 +56,24 @@ runtime --unmarshallers ## See Also -* [`ja` (mkarray)](../commands/ja.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): A sophisticated yet simply way to build a JSON array +* [Right Sub-String (`right`)](../commands/right.md): + Right substring every item in a list +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.right](../commands/right.md): - Right substring every item in a list -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/let.md b/docs/commands/let.md index 6dce65d0d..de9413cb2 100644 --- a/docs/commands/let.md +++ b/docs/commands/let.md @@ -395,6 +395,18 @@ bar ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): @@ -403,20 +415,8 @@ bar Initiates or terminates a string (variables expanded) * [`=` (arithmetic evaluation)](../parser/equ.md): Evaluate a mathematical function (deprecated) -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/list.case.md b/docs/commands/list.case.md index 347073cf4..fb4c83df2 100644 --- a/docs/commands/list.case.md +++ b/docs/commands/list.case.md @@ -1,4 +1,4 @@ -# list.case +# Change Text Case (`list.case`) > Changes the character case of a string or all elements in an array diff --git a/docs/commands/lockfile.md b/docs/commands/lockfile.md index 95a192a56..8e3b8ce7d 100644 --- a/docs/commands/lockfile.md +++ b/docs/commands/lockfile.md @@ -1,4 +1,4 @@ -# fs.lockfile +# Lock Files (`lockfile`) > Create and manage lock files @@ -51,15 +51,14 @@ out "lock file gone!" ## Synonyms * `lockfile` -* `fs.lockfile` ## See Also -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character
diff --git a/docs/commands/man-get-flags.md b/docs/commands/man-get-flags.md index 2bb7bc8f1..f353f322b 100644 --- a/docs/commands/man-get-flags.md +++ b/docs/commands/man-get-flags.md @@ -1,4 +1,4 @@ -# help.man.flags +# Parse Man-Page For Flags (`man-get-flags`) > Parses man page files for command line flags @@ -55,16 +55,15 @@ requirement is that flags are hyphen prefixed, eg `--flag`. ## Synonyms * `man-get-flags` -* `help.man.flags` ## See Also -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [help.man.summary](../commands/man-summary.md): +* [Man-Page Summary (`man-summary`)](../commands/man-summary.md): Outputs a man page summary of a command -* [shell.summary](../commands/summary.md): +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Set Command Summary Hint (`summary`)](../commands/summary.md): Defines a summary help text for a command
diff --git a/docs/commands/man-summary.md b/docs/commands/man-summary.md index 70207f80b..3ac5284e9 100644 --- a/docs/commands/man-summary.md +++ b/docs/commands/man-summary.md @@ -1,4 +1,4 @@ -# help.man.summary +# Man-Page Summary (`man-summary`) > Outputs a man page summary of a command @@ -46,14 +46,14 @@ ae - no man page exists ## See Also -* [`murex-docs`](../commands/murex-docs.md): +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [help.man.flags](../commands/man-get-flags.md): +* [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): Parses man page files for command line flags -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.summary](../commands/summary.md): +* [Set Command Summary Hint (`summary`)](../commands/summary.md): Defines a summary help text for a command +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings
diff --git a/docs/commands/map.md b/docs/commands/map.md index fd66ad493..207766673 100644 --- a/docs/commands/map.md +++ b/docs/commands/map.md @@ -1,4 +1,4 @@ -# struct.new.map (`map`) +# Create Map (`map`) > Creates a map from two data sources @@ -28,31 +28,30 @@ map { code-block } { code-block } -> ## Synonyms * `map` -* `struct.new.map` ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/match.md b/docs/commands/match.md index 825cf819b..c5465b0a0 100644 --- a/docs/commands/match.md +++ b/docs/commands/match.md @@ -1,4 +1,4 @@ -# list.str (`match`) +# Match String (`match`) > Match an exact value in an array @@ -76,34 +76,34 @@ same data-type. ## See Also -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Append To List (`append`)](../commands/append.md): Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create 2d Array (`2darray`)](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): + Creates a map from two data sources +* [Create New Array (`ta`)](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [struct.new.2darray](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): - Creates a map from two data sources +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/method.md b/docs/commands/method.md index e26fabe09..cae9fcde8 100644 --- a/docs/commands/method.md +++ b/docs/commands/method.md @@ -1,4 +1,4 @@ -# shell.method +# Define Method Relationships (`method`) > Define a methods supported data-types @@ -67,25 +67,24 @@ var GroupMath = []string{ ## Synonyms * `method` -* `shell.method` ## See Also +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? -* [`->` Arrow Pipe](../parser/pipe-arrow.md): - Pipes stdout from the left hand command to stdin of the right hand command -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block -* [shell.runtime](../commands/runtime.md): +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`->` Arrow Pipe](../parser/pipe-arrow.md): + Pipes stdout from the left hand command to stdin of the right hand command
diff --git a/docs/commands/mjoin.md b/docs/commands/mjoin.md index e49164c77..2519ea492 100644 --- a/docs/commands/mjoin.md +++ b/docs/commands/mjoin.md @@ -1,4 +1,4 @@ -# list.join +# Join Array To String (`mjoin`) > Joins a list or array into a single string @@ -41,12 +41,12 @@ Monday!Tuesday!Wednesday!Thursday!Friday ## See Also +* [Split String (`jsplit`)](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [str.split](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter
diff --git a/docs/commands/msort.md b/docs/commands/msort.md index bf0f99b37..9fa0568b0 100644 --- a/docs/commands/msort.md +++ b/docs/commands/msort.md @@ -1,4 +1,4 @@ -# list.sort +# Sort Array (`msort`) > Sorts an array - data type agnostic @@ -54,28 +54,28 @@ output of `msort` into another builtin: ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/mtac.md b/docs/commands/mtac.md index dc4424d28..d19541c06 100644 --- a/docs/commands/mtac.md +++ b/docs/commands/mtac.md @@ -1,4 +1,4 @@ -# list.reverse (`mtac`) +# Reverse Array (`mtac`) > Reverse the order of an array @@ -60,32 +60,32 @@ stdin is a long running process or non-standard stream (eg network pipe). ## See Also -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix](../commands/prefix.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend](../commands/prepend.md): - Add data to the start of an array -* [list.sort](../commands/msort.md): - Sorts an array - data type agnostic -* [list.suffix](../commands/suffix.md): +* [Add Suffix (`suffix`)](../commands/suffix.md): Prefix a string to every item in a list -* [str.split](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [struct.count](../commands/count.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [struct.new.2darray](../commands/2darray.md): +* [Create 2d Array (`2darray`)](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): Creates a map from two data sources +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Prepend To List (`prepend`)](../commands/prepend.md): + Add data to the start of an array +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Sort Array (`msort`)](../commands/msort.md): + Sorts an array - data type agnostic +* [Split String (`jsplit`)](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/murex-docs.md b/docs/commands/murex-docs.md index 06dd7226b..6574d3c6c 100644 --- a/docs/commands/murex-docs.md +++ b/docs/commands/murex-docs.md @@ -1,4 +1,4 @@ -# `murex-docs` +# Murex's Offline Documentation (`murex-docs`) > Displays the man pages for Murex builtins @@ -38,24 +38,24 @@ These man pages are compiled into the Murex executable. ## See Also -* [`(brace quote)`](../parser/brace-quote-func.md): - Write a string to the stdout without new line (deprecated) -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../deprecated/tread.md): - `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [help.man.flags](../commands/man-get-flags.md): - Parses man page files for command line flags -* [io.err](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type +* [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): + Parses man page files for command line flags +* [Read With Type (`tread`) (removed 7.x)](../commands/tread.md): + `read` a line of input from the user and store as a user defined *typed* variable (deprecated) +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [`(brace quote)`](../parser/brace-quote-func.md): + Write a string to the stdout without new line (deprecated) +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/murex-package.md b/docs/commands/murex-package.md index 860b144e0..0894f4797 100644 --- a/docs/commands/murex-package.md +++ b/docs/commands/murex-package.md @@ -1,4 +1,4 @@ -# shell.packages (`murex-package`) +# Murex Package Management (`murex-package`) > Murex's package manager @@ -114,26 +114,25 @@ If you wish to view what modules are loaded in a current session then use ## Synonyms * `murex-package` -* `shell.packages` ## See Also +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Private Function (`private`)](../commands/private.md): + Define a private function block * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): +* [Public Function (`function`)](../commands/function.md): Define a function block -* [shell.private](../commands/private.md): - Define a private function block -* [shell.runtime](../commands/runtime.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/murex-parser.md b/docs/commands/murex-parser.md index 560501947..a32c406c2 100644 --- a/docs/commands/murex-parser.md +++ b/docs/commands/murex-parser.md @@ -1,4 +1,4 @@ -# `murex-parser` +# `murex-parser` > Runs the Murex parser against a block of code @@ -20,11 +20,11 @@ Please note this command is still very much in beta and is likely to change in i ## See Also -* [`murex-docs`](../commands/murex-docs.md): +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins -* [shell.config: `config`](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.runtime: `runtime`](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/murex-update-exe-list.md b/docs/commands/murex-update-exe-list.md index 7e73ec356..3d94562d4 100644 --- a/docs/commands/murex-update-exe-list.md +++ b/docs/commands/murex-update-exe-list.md @@ -1,4 +1,4 @@ -# shell.rescan.path +# Re-Scan $PATH For Executables > Forces Murex to rescan $PATH looking for executables @@ -29,16 +29,15 @@ invoked for command name completion via the REPL shell. ## Synonyms * `murex-update-exe-list` -* `shell.rescan.path` ## See Also -* [sys.cpu.arch](../commands/cpuarch.md): +* [CPU Architecture (`cpuarch`)](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count](../commands/cpucount.md): +* [CPU Count (`cpucount`)](../commands/cpucount.md): Output the number of CPU cores available on your host -* [sys.os](../commands/os.md): +* [Operating System (`os`)](../commands/os.md): Output the auto-detected OS name
diff --git a/docs/commands/not-func.md b/docs/commands/not-func.md index 3f1a1e13b..466174b75 100644 --- a/docs/commands/not-func.md +++ b/docs/commands/not-func.md @@ -1,4 +1,4 @@ -# `!` (not) +# Not (`!`) > Reads the stdin and exit number from previous process and not's it's condition @@ -36,15 +36,15 @@ true ## See Also -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`false`](../commands/false.md): +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`or`](../commands/or.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`true`](../commands/true.md): +* [True (`true`)](../commands/true.md): Returns a `true` value
diff --git a/docs/commands/open-image.md b/docs/commands/open-image.md index b4789a436..e52b06de6 100644 --- a/docs/commands/open-image.md +++ b/docs/commands/open-image.md @@ -1,4 +1,4 @@ -# fs.open.image +# Render Image In Terminal (`open-image`) > Renders bitmap image data on your terminal @@ -37,15 +37,14 @@ open-image file-path -> ## Synonyms * `open-image` -* `fs.open.image` ## See Also +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler * [`qr`](../optional/qr.md): Creates a QR code from stdin -* [fs.open](../commands/open.md): - Open a file with a preferred handler
diff --git a/docs/commands/open.md b/docs/commands/open.md index 4788acef1..8d530062d 100644 --- a/docs/commands/open.md +++ b/docs/commands/open.md @@ -1,4 +1,4 @@ -# fs.open +# Open File (`open`) > Open a file with a preferred handler @@ -215,31 +215,30 @@ exec open --flags filename ## Synonyms * `open` -* `fs.open` ## See Also -* [`*` (generic)](../types/generic.md): - generic (primitive) -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Download File (`getfile`)](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [io.out](../commands/out.md): +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Get Request (`get`)](../commands/get.md): + Makes a standard HTTP request and returns the result as a JSON object +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.config](../commands/config.md): +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` +* [`*` (generic)](../types/generic.md): + generic (primitive)
diff --git a/docs/commands/openagent.md b/docs/commands/openagent.md index 7c2345694..5383195ac 100644 --- a/docs/commands/openagent.md +++ b/docs/commands/openagent.md @@ -1,4 +1,4 @@ -# shell.open: `openagent` +# Define Handlers For "`open`" (`openagent`) > Creates a handler function for `open` @@ -38,21 +38,19 @@ handler by checking `runtime --open-agents` and checking it's **FileRef**. * `openagent` * `!openagent` -* `shell.open` -* `!shell.open` ## See Also +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/or.md b/docs/commands/or.md index 749d23ca0..3da764d72 100644 --- a/docs/commands/or.md +++ b/docs/commands/or.md @@ -1,4 +1,4 @@ -# `or` +# Logic Or Statements (`or`) > Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. @@ -49,22 +49,26 @@ code-blocks are unsuccessful (ie the opposite of `or`). ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`false`](../commands/false.md): +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`true`](../commands/true.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [True (`true`)](../commands/true.md): Returns a `true` value -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline +* [`&&` And Logical Operator](../parser/logical-and.md): + Continues next operation if previous operation passes +* [`||` Or Logical Operator](../parser/logical-or.md): + Continues next operation only if previous operation fails
diff --git a/docs/commands/os.md b/docs/commands/os.md index 2eda38c5a..7afa147c1 100644 --- a/docs/commands/os.md +++ b/docs/commands/os.md @@ -1,4 +1,4 @@ -# sys.os +# Operating System (`os`) > Output the auto-detected OS name @@ -77,9 +77,9 @@ then please write it as `os posix plan9`. ## See Also -* [sys.cpu.arch](../commands/cpuarch.md): +* [CPU Architecture (`cpuarch`)](../commands/cpuarch.md): Output the hosts CPU architecture -* [sys.cpu.count](../commands/cpucount.md): +* [CPU Count (`cpucount`)](../commands/cpucount.md): Output the number of CPU cores available on your host
diff --git a/docs/commands/out.md b/docs/commands/out.md index db41d1d8a..25e22cad3 100644 --- a/docs/commands/out.md +++ b/docs/commands/out.md @@ -1,4 +1,4 @@ -# io.out +# Output String (`out`) > Print a string to the stdout with a trailing new line character @@ -23,7 +23,7 @@ Hello, World! ### echo -For compatibility with other shells, `echo` is also supported: +For compatibility with other shells (and POSIX), `echo` is also supported: ``` » echo Hello, World! @@ -42,7 +42,6 @@ Hello, World! ## Synonyms * `out` -* `io.out` * `echo` @@ -50,24 +49,24 @@ Hello, World! * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences -* [`(brace quote)`](../parser/brace-quote-func.md): - Write a string to the stdout without new line (deprecated) -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../deprecated/tread.md): - `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [io.err](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.out.type (`tout`)](../commands/tout.md): +* [Get Pipe Status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [io.read](../commands/read.md): +* [Read User Input (`read`)](../commands/read.md): `read` a line of input from the user and store as a variable -* [io.status (`pt`)](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written +* [Read With Type (`tread`) (removed 7.x)](../commands/tread.md): + `read` a line of input from the user and store as a user defined *typed* variable (deprecated) +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [`(brace quote)`](../parser/brace-quote-func.md): + Write a string to the stdout without new line (deprecated) +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/pipe.md b/docs/commands/pipe.md index 4dc7289ac..32c58e024 100644 --- a/docs/commands/pipe.md +++ b/docs/commands/pipe.md @@ -1,4 +1,4 @@ -# io.new.pipe +# Create Named Pipe (`pipe`) > Manage Murex named pipes @@ -120,30 +120,28 @@ that pipes created in modules should be prefixed with the name of its package. * `pipe` * `!pipe` -* `io.new.pipe` -* `!io.new.pipe` ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): Reads from a Murex named pipe -* [io.pipe (``)](../commands/namedpipe.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): Reads from a Murex named pipe -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [proc.bg](../commands/bg.md): - Run processes in the background -* [shell.runtime](../commands/runtime.md): +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts
diff --git a/docs/commands/post.md b/docs/commands/post.md index b1c00ce45..c6d6d221e 100644 --- a/docs/commands/post.md +++ b/docs/commands/post.md @@ -1,4 +1,4 @@ -# `post` +# Post Request (`post`) > HTTP POST request with a JSON-parsable return @@ -97,15 +97,15 @@ This enables sane, repeatable and readable defaults. Read the documents on ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Download File (`getfile`)](../commands/getfile.md): + Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`get`](../commands/get.md): +* [Get Request (`get`)](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/prefix.md b/docs/commands/prefix.md index 332eb4b83..87049c5bf 100644 --- a/docs/commands/prefix.md +++ b/docs/commands/prefix.md @@ -1,4 +1,4 @@ -# list.prefix +# Add Prefix (`prefix`) > Prefix a string to every item in a list @@ -40,24 +40,24 @@ runtime --unmarshallers ## See Also -* [`ja` (mkarray)](../commands/ja.md): +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): A sophisticated yet simply way to build a JSON array +* [Left Sub-String (`left`)](../commands/left.md): + Left substring every item in a list +* [Right Sub-String (`right`)](../commands/right.md): + Right substring every item in a list +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.left](../commands/left.md): - Left substring every item in a list -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.right](../commands/right.md): - Right substring every item in a list -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/prepend.md b/docs/commands/prepend.md index f1d7964a8..d31b5cf48 100644 --- a/docs/commands/prepend.md +++ b/docs/commands/prepend.md @@ -1,4 +1,4 @@ -# list.prepend +# Prepend To List (`prepend`) > Add data to the start of an array @@ -48,30 +48,30 @@ Error in `append` (1,22): cannot convert 'bob' to a floating point number: strco ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Add Heading (`addheading`)](../commands/addheading.md): + Adds headings to a table +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.regex](../commands/regexp.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.sort](../commands/msort.md): +* [Sort Array (`msort`)](../commands/msort.md): Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [table.add.heading](../commands/addheading.md): - Adds headings to a table +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/pretty.md b/docs/commands/pretty.md index 8e1560737..b8b5c56af 100644 --- a/docs/commands/pretty.md +++ b/docs/commands/pretty.md @@ -1,4 +1,4 @@ -# struct.json.pretty +# Prettify JSON > Prettifies JSON to make it human readable @@ -33,17 +33,16 @@ outputs that to stdout. ## Synonyms * `pretty` -* `struct.json.pretty` ## See Also -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type
diff --git a/docs/commands/private.md b/docs/commands/private.md index f58a83607..464d6b589 100644 --- a/docs/commands/private.md +++ b/docs/commands/private.md @@ -1,4 +1,4 @@ -# shell.private +# Private Function (`private`) > Define a private function block @@ -93,35 +93,34 @@ You can override this order of precedence via the `fexec` and `exec` builtins. ## Synonyms * `private` -* `shell.private` ## See Also -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [fs.glob (`g`)](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [shell.alias](../commands/alias.md): +* [Alias Pointer (`alias`)](../commands/alias.md): Create an alias for a command -* [shell.function](../commands/function.md): - Define a function block -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [var.env: `export`](../commands/export.md): +* [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): +* [Define Global (`global`)](../commands/global.md): Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [Globbing (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated)
diff --git a/docs/commands/pt.md b/docs/commands/pt.md index d8eda4941..71d8eadcb 100644 --- a/docs/commands/pt.md +++ b/docs/commands/pt.md @@ -1,4 +1,4 @@ -# io.status (`pt`) +# Get Pipe Status (`pt`) > Pipe telemetry. Writes data-types and bytes written @@ -25,21 +25,20 @@ curl -s https://example.com/bigfile.bin -> pt |> bigfile.bin ## Synonyms * `pt` -* `fs.status` ## See Also -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`get`](../commands/get.md): - Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): +* [Download File (`getfile`)](../commands/getfile.md): Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`post`](../commands/post.md): +* [Get Request (`get`)](../commands/get.md): + Makes a standard HTTP request and returns the result as a JSON object +* [Post Request (`post`)](../commands/post.md): HTTP POST request with a JSON-parsable return -* [fs.truncate (`>`)](../commands/file-truncate.md): +* [Truncate File (`>`)](../parser/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/rand.md b/docs/commands/rand.md index f5ba71b56..2de9cf303 100644 --- a/docs/commands/rand.md +++ b/docs/commands/rand.md @@ -1,4 +1,4 @@ -# `rand` +# Generate Random Sequence (`rand`) > Random field generator @@ -67,12 +67,12 @@ cryptographically secure. ## See Also -* [`format`](../commands/format.md): +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/read.md b/docs/commands/read.md index 127547b5f..3c3fd9a5d 100644 --- a/docs/commands/read.md +++ b/docs/commands/read.md @@ -1,4 +1,4 @@ -# io.read +# Read User Input (`read`) > `read` a line of input from the user and store as a variable @@ -88,27 +88,26 @@ with the `--datatype` flag as per the **script usage**. ## Synonyms * `read` -* `io.input` ## See Also -* [`%(Brace Quote)`](../parser/brace-quote.md): - Initiates or terminates a string (variables expanded) -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`tread`](../deprecated/tread.md): - `read` a line of input from the user and store as a user defined *typed* variable (deprecated) -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [io.err](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type +* [Read With Type (`tread`) (removed 7.x)](../commands/tread.md): + `read` a line of input from the user and store as a user defined *typed* variable (deprecated) +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [`%(Brace Quote)`](../parser/brace-quote.md): + Initiates or terminates a string (variables expanded) +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 052894efa..a2823dd51 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -1,4 +1,4 @@ -# list.regex +# Regex Operations (`regexp`) > Regexp tools for arrays / lists of strings @@ -95,34 +95,34 @@ same data-type. ## See Also -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix](../commands/prefix.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): Prefix a string to every item in a list -* [list.prepend](../commands/prepend.md): - Add data to the start of an array -* [list.sort](../commands/msort.md): - Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [list.suffix](../commands/suffix.md): +* [Add Suffix (`suffix`)](../commands/suffix.md): Prefix a string to every item in a list -* [str.split](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [struct.count](../commands/count.md): +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): Count items in a map, list or array -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [struct.new.2darray](../commands/2darray.md): +* [Create 2d Array (`2darray`)](../commands/2darray.md): Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): Creates a map from two data sources +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Prepend To List (`prepend`)](../commands/prepend.md): + Add data to the start of an array +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Sort Array (`msort`)](../commands/msort.md): + Sorts an array - data type agnostic +* [Split String (`jsplit`)](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/commands/return.md b/docs/commands/return.md index 3fc4ccb80..2024496f1 100644 --- a/docs/commands/return.md +++ b/docs/commands/return.md @@ -1,4 +1,4 @@ -# `return` +# Exit Function (`return`) > Exits current function scope @@ -56,20 +56,20 @@ was passed). ## See Also -* [`break`](../commands/break.md): +* [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope -* [`continue`](../commands/continue.md): - Terminate process of a block within a caller function -* [`exit`](../commands/exit.md): +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [proc.exitnum](../commands/exitnum.md): +* [Get Exit Code (`exitnum`)](../commands/exitnum.md): Output the exit number of the previous process -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Next Iteration (`continue`)](../commands/continue.md): + Terminate process of a block within a caller function +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Private Function (`private`)](../commands/private.md): Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block
diff --git a/docs/commands/right.md b/docs/commands/right.md index bbd993ecb..313953636 100644 --- a/docs/commands/right.md +++ b/docs/commands/right.md @@ -1,4 +1,4 @@ -# list.right +# Right Sub-String (`right`) > Right substring every item in a list @@ -56,24 +56,24 @@ runtime --unmarshallers ## See Also -* [`ja` (mkarray)](../commands/ja.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): A sophisticated yet simply way to build a JSON array +* [Right Sub-String (`right`)](../commands/right.md): + Right substring every item in a list +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.right](../commands/right.md): - Right substring every item in a list -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/round.md b/docs/commands/round.md index 16dda7e1c..165f2ef81 100644 --- a/docs/commands/round.md +++ b/docs/commands/round.md @@ -1,4 +1,4 @@ -# num.round: `round` +# Round Number (`round`) > Round a number by a user defined precision diff --git a/docs/commands/runmode.md b/docs/commands/runmode.md index 8267b3c14..074b47613 100644 --- a/docs/commands/runmode.md +++ b/docs/commands/runmode.md @@ -1,4 +1,4 @@ -# `runmode` +# Function / Module Defaults (`runmode`) > Alter the scheduler's behaviour at higher scoping level @@ -83,36 +83,36 @@ if `runmode ... module` is set. ## See Also +* [Caught Error Block (`catch`)](../commands/catch.md): + Handles the exception code raised by `try` or `trypipe` +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Read User Input (`read`)](../commands/read.md): + `read` a line of input from the user and store as a variable * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): - Handles the exception code raised by `try` or `trypipe` -* [`event`](../commands/event.md): - Event driven programming for shell scripts -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.read](../commands/read.md): - `read` a line of input from the user and store as a variable -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.autocomplete](../commands/autocomplete.md): +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code +* [`event`](../commands/event.md): + Event driven programming for shell scripts
diff --git a/docs/commands/runtime.md b/docs/commands/runtime.md index 2fae3a86b..9a076fb9a 100644 --- a/docs/commands/runtime.md +++ b/docs/commands/runtime.md @@ -1,4 +1,4 @@ -# shell.runtime +# Shell Runtime (`runtime`) > Returns runtime information on the internal state of Murex @@ -286,52 +286,52 @@ functions. ## See Also +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block * [Integrations](../user-guide/integrations.md): Default integrations shipped with Murex -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`formap`](../commands/formap.md): - Iterate through a map or other collection of data -* [`format`](../commands/format.md): - Reformat one data-type into another data-type * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.debug](../commands/debug.md): - Debugging information -* [shell.function](../commands/function.md): - Define a function block -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.private](../commands/private.md): - Define a private function block -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/rx.md b/docs/commands/rx.md index 143452ff4..e0b5906f7 100644 --- a/docs/commands/rx.md +++ b/docs/commands/rx.md @@ -1,4 +1,4 @@ -# fs.regex (`rx`) +# Regex Matches (`rx`) > Regexp pattern matching for file system objects (eg `.*\\.txt`) @@ -114,20 +114,18 @@ The reason for this behavior is to separate this from `!regexp` and `!match`. * `rx` * `!rx` -* `fs.regex` -* `!fs.regex` ## See Also -* [fs.files (`f`)](../commands/f.md): - Lists or filters file system objects (eg files) -* [fs.glob (`g`)](../commands/g.md): +* [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) -* [list.regex](../commands/regexp.md): - Regexp tools for arrays / lists of strings -* [list.str (`match`)](../commands/match.md): +* [List Filesystem Objects (`f`)](../commands/f.md): + Lists or filters file system objects (eg files) +* [Match String (`match`)](../commands/match.md): Match an exact value in an array +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings
diff --git a/docs/commands/set.md b/docs/commands/set.md index 680da53aa..ecb643770 100644 --- a/docs/commands/set.md +++ b/docs/commands/set.md @@ -1,10 +1,11 @@ -# var.set: `set` +# Define Variable (`set`) -> Define a local variable and set it's value +> Define a variable (typically local) and set it's value ## Description -Defines, updates or deallocates a local variable. +Defines, updates or deallocates a variable. By default that variable will be +local. ## Usage @@ -248,12 +249,22 @@ bar * `set` * `!set` -* `var.set` -* `!var.set` ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): @@ -262,20 +273,8 @@ bar Initiates or terminates a string (variables expanded) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value
diff --git a/docs/commands/signal.md b/docs/commands/signal.md index d56aed06b..5ba4c9d12 100644 --- a/docs/commands/signal.md +++ b/docs/commands/signal.md @@ -160,20 +160,20 @@ Signals can be caught (often referred to as "trapped") in Murex with an event: ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [MUREX_EXE](../variables/murex_exe.md): Absolute path to running shell +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character * [onSignalReceived](../events/onsignalreceived.md): Trap OS signals -* [proc.bg](../commands/bg.md): - Run processes in the background
diff --git a/docs/commands/source.md b/docs/commands/source.md index a0ac74be5..f50d8f40c 100644 --- a/docs/commands/source.md +++ b/docs/commands/source.md @@ -1,4 +1,4 @@ -# exec.include (`source`) +# Include / Evaluate Murex Code (`source`) > Import Murex code from another file or code block @@ -56,31 +56,30 @@ Hello, world! * `source` * `.` -* `exec.include` ## See Also -* [`args` ](../commands/args.md): +* [Define Function Arguments (`args`)](../commands/args.md): Command line flag parser for Murex shell scripting -* [`murex-parser` ](../deprecated/murex-parser.md): - Runs the Murex parser against a block of code -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Murex Version (`version`)](../commands/version.md): + Get Murex version +* [Private Function (`private`)](../commands/private.md): Define a private function block -* [shell.runtime](../commands/runtime.md): +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.version](../commands/version.md): - Get Murex version +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`murex-parser`](../commands/murex-parser.md): + Runs the Murex parser against a block of code
diff --git a/docs/commands/struct-keys.md b/docs/commands/struct-keys.md index 69a234b38..53275a6b0 100644 --- a/docs/commands/struct-keys.md +++ b/docs/commands/struct-keys.md @@ -1,4 +1,4 @@ -# struct.keys +# Print Map / Structure Keys (`struct-keys`) > Outputs all the keys in a structure as a file path @@ -159,19 +159,18 @@ Separator can also be multiple characters: ## Synonyms * `struct-keys` -* `struct.keys` ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`formap`](../commands/formap.md): - Iterate through a map or other collection of data -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/suffix.md b/docs/commands/suffix.md index d3481b41c..bff9ad6e3 100644 --- a/docs/commands/suffix.md +++ b/docs/commands/suffix.md @@ -1,4 +1,4 @@ -# list.suffix +# Add Suffix (`suffix`) > Prefix a string to every item in a list @@ -40,24 +40,24 @@ runtime --unmarshallers ## See Also -* [`ja` (mkarray)](../commands/ja.md): +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): A sophisticated yet simply way to build a JSON array +* [Left Sub-String (`left`)](../commands/left.md): + Left substring every item in a list +* [Right Sub-String (`right`)](../commands/right.md): + Right substring every item in a list +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`lang.MarshalData()` (system API)](../apis/lang.MarshalData.md): Converts structured memory into a Murex data-type (eg for stdio) * [`lang.UnmarshalData()` (system API)](../apis/lang.UnmarshalData.md): Converts a Murex data-type into structured memory -* [list.left](../commands/left.md): - Left substring every item in a list -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.right](../commands/right.md): - Right substring every item in a list -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/commands/summary.md b/docs/commands/summary.md index 65b34f524..b782855cd 100644 --- a/docs/commands/summary.md +++ b/docs/commands/summary.md @@ -1,4 +1,4 @@ -# shell.summary +# Set Command Summary Hint (`summary`) > Defines a summary help text for a command @@ -45,27 +45,25 @@ Hello, world! * `summary` * `!summary` -* `shell.summary` -* `!shell.summary` ## See Also -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.builtins](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [shell.builtins.exist](../commands/bexists.md): +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): Check which builtins exist -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.rescan.path](../commands/murex-update-exe-list.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): Forces Murex to rescan $PATH looking for executables -* [shell.runtime](../commands/runtime.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`builtins`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/commands/switch.md b/docs/commands/switch.md index 3156cab81..00f1a796c 100644 --- a/docs/commands/switch.md +++ b/docs/commands/switch.md @@ -1,4 +1,4 @@ -# `switch` +# Switch Conditional (`switch`) > Blocks of cascading conditionals @@ -203,32 +203,32 @@ switch { ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`false`](../commands/false.md): +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [`or`](../commands/or.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`true`](../commands/true.md): +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [True (`true`)](../commands/true.md): Returns a `true` value -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`while`](../commands/while.md): - Loop until condition false -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated)
diff --git a/docs/commands/ta.md b/docs/commands/ta.md index 3cbbc356e..1efdd52fa 100644 --- a/docs/commands/ta.md +++ b/docs/commands/ta.md @@ -1,4 +1,4 @@ -# list.new.type: `ta` +# Create New Array (`ta`) > A sophisticated yet simple way to build an array of a user defined data-type @@ -55,27 +55,26 @@ Please read the documentation on `a` for a more detailed breakdown on of ## Synonyms * `ta` -* `list.new.type` ## See Also -* [`%[]` Array Builder](../parser/create-array.md): - Quickly generate arrays -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays
diff --git a/docs/commands/tabulate.md b/docs/commands/tabulate.md index 5d3317a82..517fc8e40 100644 --- a/docs/commands/tabulate.md +++ b/docs/commands/tabulate.md @@ -1,4 +1,4 @@ -# `tabulate` +# Transformation Tools (`tabulate`) > Table transformation tools @@ -55,15 +55,15 @@ rsync --help # print rsync help ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [For Each In Map (`formap`)](../commands/formap.md): + Iterate through a map or other collection of data +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`formap`](../commands/formap.md): - Iterate through a map or other collection of data -* [`format`](../commands/format.md): +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type -* [shell.autocomplete](../commands/autocomplete.md): +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line
diff --git a/docs/commands/test.md b/docs/commands/test.md index 2d5c136df..3d8cceeb3 100644 --- a/docs/commands/test.md +++ b/docs/commands/test.md @@ -1,4 +1,4 @@ -# `test` +# Shell Script Tests (`test`) > Murex's test framework - define tests, run tests and debug shell scripts @@ -114,9 +114,9 @@ flushes the table of pending reports. ## See Also -* [io.pipe (``)](../commands/namedpipe.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): Reads from a Murex named pipe -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/commands/time.md b/docs/commands/time.md index 8156badfd..abfd767f9 100644 --- a/docs/commands/time.md +++ b/docs/commands/time.md @@ -1,4 +1,4 @@ -# `time` +# Processes Execution Time (`time`) > Returns the execution run time of a command or block @@ -41,12 +41,12 @@ and stderr as usual. ## See Also -* [`sleep`](../optional/sleep.md): - Suspends the shell for a number of seconds -* [exec.file: `exec`](../commands/exec.md): +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block +* [`sleep`](../optional/sleep.md): + Suspends the shell for a number of seconds
diff --git a/docs/commands/tmp.md b/docs/commands/tmp.md index a3720aa61..67c92c7d4 100644 --- a/docs/commands/tmp.md +++ b/docs/commands/tmp.md @@ -1,4 +1,4 @@ -# fs.tmpfile (`tmp`) +# Create Temporary File (`tmp`) > Create a temporary file and write to it @@ -99,19 +99,18 @@ which itself is located in the appropriate temp directory for the host OS (eg ## Synonyms * `tmp` -* `fs.new.tmpfile` ## See Also -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [fs.open](../commands/open.md): +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [fs.truncate (`>`)](../commands/file-truncate.md): +* [Truncate File (`>`)](../parser/file-truncate.md): Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/commands/tout.md b/docs/commands/tout.md index aaa5759b3..42a916d2a 100644 --- a/docs/commands/tout.md +++ b/docs/commands/tout.md @@ -1,4 +1,4 @@ -# io.out.type (`tout`) +# Output With Type Annotation (`tout`) > Print a string to the stdout and set it's data-type @@ -32,25 +32,24 @@ Unlike `out`, `tout` does not append a carriage return / line feed. ## Synonyms * `tout` -* `io.out.type` ## See Also * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences -* [`(brace quote)`](../parser/brace-quote-func.md): - Write a string to the stdout without new line (deprecated) -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [io.err](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [struct.json.pretty](../commands/pretty.md): +* [Prettify JSON](../commands/pretty.md): Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [`(brace quote)`](../parser/brace-quote-func.md): + Write a string to the stdout without new line (deprecated)
diff --git a/docs/commands/tread.md b/docs/commands/tread.md index 31e85161c..eb8215e35 100644 --- a/docs/commands/tread.md +++ b/docs/commands/tread.md @@ -1,4 +1,4 @@ -# `tread` +# Read With Type (`tread`) (removed 7.x) > `read` a line of input from the user and store as a user defined *typed* variable (deprecated) @@ -42,22 +42,22 @@ variable. ## See Also -* [`%(Brace Quote)`](../parser/brace-quote.md): - Initiates or terminates a string (variables expanded) -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [io.err: `err`](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.input: `read`](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.out.type: `tout`](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [io.out: `out`](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [struct.json.pretty: `pretty`](../commands/pretty.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type +* [Prettify JSON](../commands/pretty.md): Prettifies JSON to make it human readable +* [Read User Input (`read`)](../commands/read.md): + `read` a line of input from the user and store as a variable +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [`%(Brace Quote)`](../parser/brace-quote.md): + Initiates or terminates a string (variables expanded)
diff --git a/docs/commands/true.md b/docs/commands/true.md index 0dc2b8872..105634f4e 100644 --- a/docs/commands/true.md +++ b/docs/commands/true.md @@ -1,4 +1,4 @@ -# `true` +# True (`true`) > Returns a `true` value @@ -38,16 +38,16 @@ You can suppress that with the silent flag: ## See Also -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`false`](../commands/false.md): +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`if`](../commands/if.md): +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`or`](../commands/or.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition
diff --git a/docs/commands/try.md b/docs/commands/try.md index 0461a97cc..4f6008ecc 100644 --- a/docs/commands/try.md +++ b/docs/commands/try.md @@ -1,4 +1,4 @@ -# `try` +# Try Block (`try`) > Handles non-zero exits inside a block of code @@ -43,26 +43,26 @@ command. ## See Also -* [Schedulers](../user-guide/schedulers.md): - Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): +* [Schedulers](../user-guide/schedulers.md): + Overview of the different schedulers (or 'run modes') in Murex +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals
diff --git a/docs/commands/tryerr.md b/docs/commands/tryerr.md index 2b04f82d1..e551ef409 100644 --- a/docs/commands/tryerr.md +++ b/docs/commands/tryerr.md @@ -1,4 +1,4 @@ -# `tryerr` +# Stderr Checking In TTY (`tryerr`) > Handles errors inside a block of code @@ -44,26 +44,26 @@ command. ## See Also -* [Schedulers](../user-guide/schedulers.md): - Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): +* [Schedulers](../user-guide/schedulers.md): + Overview of the different schedulers (or 'run modes') in Murex +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code
diff --git a/docs/commands/trypipe.md b/docs/commands/trypipe.md index e0ab61861..bdefe37f9 100644 --- a/docs/commands/trypipe.md +++ b/docs/commands/trypipe.md @@ -1,4 +1,4 @@ -# `trypipe` +# Pipe Fail (`trypipe`) > Checks for non-zero exits of each function in a pipeline @@ -46,26 +46,26 @@ command. ## See Also -* [Schedulers](../user-guide/schedulers.md): - Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Schedulers](../user-guide/schedulers.md): + Overview of the different schedulers (or 'run modes') in Murex +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): + Checks state of each function in a pipeline and exits block on error +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Switch Conditional (`switch`)](../commands/switch.md): Blocks of cascading conditionals -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipeerr`](../commands/trypipeerr.md): - Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session
diff --git a/docs/commands/trypipeerr.md b/docs/commands/trypipeerr.md index c15acca5d..856c9058e 100644 --- a/docs/commands/trypipeerr.md +++ b/docs/commands/trypipeerr.md @@ -1,4 +1,4 @@ -# `trypipeerr` +# Stderr Checking In Pipes (`trypipeerr`) > Checks state of each function in a pipeline and exits block on error @@ -47,26 +47,26 @@ command. ## See Also -* [Schedulers](../user-guide/schedulers.md): - Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [Schedulers](../user-guide/schedulers.md): + Overview of the different schedulers (or 'run modes') in Murex +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Switch Conditional (`switch`)](../commands/switch.md): Blocks of cascading conditionals -* [`try`](../commands/try.md): +* [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session
diff --git a/docs/commands/type.md b/docs/commands/type.md index 1f1ac7c5a..58734935e 100644 --- a/docs/commands/type.md +++ b/docs/commands/type.md @@ -1,4 +1,4 @@ -# `type` +# Display Command Type (`type`) > Command type (function, builtin, alias, etc) @@ -69,19 +69,19 @@ In `type`, it is represented by the term **executable**. ## See Also -* [`exit`](../commands/exit.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [`which`](../commands/which.md): +* [Location Of Command (`which`)](../commands/which.md): Locate command origin -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [io.out](../commands/out.md): +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.function](../commands/function.md): +* [Public Function (`function`)](../commands/function.md): Define a function block
diff --git a/docs/commands/unsafe.md b/docs/commands/unsafe.md index 2e95a01ac..7844da364 100644 --- a/docs/commands/unsafe.md +++ b/docs/commands/unsafe.md @@ -1,4 +1,4 @@ -# `unsafe` +# Disable Error Handling In Block (`unsafe`) > Execute a block of code, always returning a zero exit number @@ -28,26 +28,26 @@ try { ## See Also -* [Schedulers](../user-guide/schedulers.md): - Overview of the different schedulers (or 'run modes') in Murex -* [`catch`](../commands/catch.md): +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition -* [`runmode`](../commands/runmode.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): Alter the scheduler's behaviour at higher scoping level -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): +* [Schedulers](../user-guide/schedulers.md): + Overview of the different schedulers (or 'run modes') in Murex +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): Checks state of each function in a pipeline and exits block on error -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code
diff --git a/docs/commands/version.md b/docs/commands/version.md index 9b35899d2..e89937b15 100644 --- a/docs/commands/version.md +++ b/docs/commands/version.md @@ -1,4 +1,4 @@ -# shell.version +# Murex Version (`version`) > Get Murex version @@ -45,27 +45,26 @@ murex: 0.51.1200 BETA ## Synonyms * `version` -* `shell.version` ## See Also -* [`args` ](../commands/args.md): +* [Define Function Arguments (`args`)](../commands/args.md): Command line flag parser for Murex shell scripting -* [`murex-parser` ](../deprecated/murex-parser.md): - Runs the Murex parser against a block of code -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block -* [shell.runtime](../commands/runtime.md): +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [`murex-parser`](../commands/murex-parser.md): + Runs the Murex parser against a block of code
diff --git a/docs/commands/which.md b/docs/commands/which.md index b51ddd512..a25f1131a 100644 --- a/docs/commands/which.md +++ b/docs/commands/which.md @@ -1,4 +1,4 @@ -# `which` +# Location Of Command (`which`) > Locate command origin @@ -75,19 +75,19 @@ In `type`, it is represented by the term **executable**. ## See Also -* [`exit`](../commands/exit.md): - Exit murex -* [`type`](../commands/type.md): +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Display Command Type (`type`)](../commands/type.md): Command type (function, builtin, alias, etc) -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [io.out](../commands/out.md): +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Exit Murex (`exit`)](../commands/exit.md): + Exit murex +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.function](../commands/function.md): +* [Public Function (`function`)](../commands/function.md): Define a function block
diff --git a/docs/commands/while.md b/docs/commands/while.md index f09fe049d..cec0ffd60 100644 --- a/docs/commands/while.md +++ b/docs/commands/while.md @@ -1,4 +1,4 @@ -# `while` +# Loop While (`while`) > Loop until condition false @@ -96,22 +96,22 @@ The following meta values are defined: ## See Also -* [`for`](../commands/for.md): - A more familiar iteration loop to existing developers -* [`foreach`](../commands/foreach.md): +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/events/oncommandcompletion.md b/docs/events/oncommandcompletion.md index ddc5e18a7..9575f2d47 100644 --- a/docs/events/oncommandcompletion.md +++ b/docs/events/oncommandcompletion.md @@ -117,28 +117,28 @@ Stdout and stderr are both written to the terminal's stderr. ## See Also +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition * [Named Pipes](../user-guide/namedpipes.md): A detailed breakdown of named pipes in Murex +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [list.regex](../commands/regexp.md): - Regexp tools for arrays / lists of strings -* [read-named-pipe](../commands/namedpipe.md): +* [read-named-pipe](../parser/namedpipe.md): Reads from a Murex named pipe -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block
diff --git a/docs/events/onfilesystemchange.md b/docs/events/onfilesystemchange.md index 1c847274a..f25f8a6c3 100644 --- a/docs/events/onfilesystemchange.md +++ b/docs/events/onfilesystemchange.md @@ -89,10 +89,10 @@ event to Linux, macOS and UNIX systems instead. ## See Also +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/events/onkeypress.md b/docs/events/onkeypress.md index 14a1f1a52..6c5f7e531 100644 --- a/docs/events/onkeypress.md +++ b/docs/events/onkeypress.md @@ -253,6 +253,8 @@ from different interrupts). * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): @@ -263,8 +265,6 @@ from different interrupts). Full screen previews for files and command documentation * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/events/onpreview.md b/docs/events/onpreview.md index 08a062d98..76b08e4cb 100644 --- a/docs/events/onpreview.md +++ b/docs/events/onpreview.md @@ -166,22 +166,22 @@ from different interrupts). What's different about Murex's interactive shell? * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block
diff --git a/docs/events/onprompt.md b/docs/events/onprompt.md index 1ef9815bf..27259a286 100644 --- a/docs/events/onprompt.md +++ b/docs/events/onprompt.md @@ -125,6 +125,8 @@ from different interrupts). * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): @@ -135,8 +137,6 @@ from different interrupts). Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/events/onsecondselapsed.md b/docs/events/onsecondselapsed.md index d51e31aa2..441f6683a 100644 --- a/docs/events/onsecondselapsed.md +++ b/docs/events/onsecondselapsed.md @@ -58,10 +58,10 @@ Stdout and stderr are both written to the terminal. ## See Also +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`event`](../commands/event.md): Event driven programming for shell scripts -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/integrations/chatgpt.md b/docs/integrations/chatgpt.md index 0801bb343..70180af0f 100644 --- a/docs/integrations/chatgpt.md +++ b/docs/integrations/chatgpt.md @@ -127,20 +127,20 @@ under `/integrations`. * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh -* [shell.config](../commands/config.md): - Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/cheatsh.md b/docs/integrations/cheatsh.md index 21f621271..4d8d54f23 100644 --- a/docs/integrations/cheatsh.md +++ b/docs/integrations/cheatsh.md @@ -32,18 +32,18 @@ under `/integrations`. How to enable ChatGPT hints * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.config](../commands/config.md): - Query or define Murex runtime settings ## Other Integrations diff --git a/docs/integrations/direnv.md b/docs/integrations/direnv.md index a3354a816..17b3af4f4 100644 --- a/docs/integrations/direnv.md +++ b/docs/integrations/direnv.md @@ -18,10 +18,10 @@ document. ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value ## Other Integrations diff --git a/docs/integrations/iterm2.md b/docs/integrations/iterm2.md index 277531cc4..e90c3cca7 100644 --- a/docs/integrations/iterm2.md +++ b/docs/integrations/iterm2.md @@ -26,14 +26,14 @@ open https://murex.rocks/git-autocomplete.png ## See Also +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` * [Kitty Integrations](../integrations/kitty.md): Get more out of Kitty terminal emulator +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/kitty.md b/docs/integrations/kitty.md index fc5347931..a7e7fa35a 100644 --- a/docs/integrations/kitty.md +++ b/docs/integrations/kitty.md @@ -22,14 +22,14 @@ to Kitty's ANSI escape sequences to render those images beautifully. ## See Also +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler * [Terminology Integrations](../integrations/terminology.md): Get more out of Terminology terminal emulator -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/make.md b/docs/integrations/make.md index 3d8024898..2c43b4182 100644 --- a/docs/integrations/make.md +++ b/docs/integrations/make.md @@ -26,12 +26,12 @@ under `/integrations`. ## See Also +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/man-pages.md b/docs/integrations/man-pages.md index 4ddb9d503..0e4d6e5db 100644 --- a/docs/integrations/man-pages.md +++ b/docs/integrations/man-pages.md @@ -44,18 +44,18 @@ That command will generally be pulled from its accompanying `man` page. * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): Cheatsheets provided by cheat.sh -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/integrations/spellcheck.md b/docs/integrations/spellcheck.md index c781b6a1b..6bcc8325f 100644 --- a/docs/integrations/spellcheck.md +++ b/docs/integrations/spellcheck.md @@ -157,26 +157,26 @@ and what the package names are for `aspell` and its corresponding dictionaries. * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array * [Code Block Parsing](../user-guide/code-block.md): Overview of how code blocks are parsed +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Split String (`jsplit`)](../commands/jsplit.md): + Splits stdin into a JSON array based on a regex parameter * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block -* [list.append](../commands/append.md): - Add data to the end of an array -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [str.split](../commands/jsplit.md): - Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value ## Other Integrations diff --git a/docs/integrations/terminology.md b/docs/integrations/terminology.md index 2a9604e0d..bdbda036c 100644 --- a/docs/integrations/terminology.md +++ b/docs/integrations/terminology.md @@ -23,14 +23,14 @@ beautifully. ## See Also +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` * [Kitty Integrations](../integrations/kitty.md): Get more out of Kitty terminal emulator -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` ## Other Integrations diff --git a/docs/integrations/yarn.md b/docs/integrations/yarn.md index 44be243a2..a3df5c9ce 100644 --- a/docs/integrations/yarn.md +++ b/docs/integrations/yarn.md @@ -23,12 +23,12 @@ under `/integrations`. ## See Also +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line ## Other Integrations diff --git a/docs/mkarray/character.md b/docs/mkarray/character.md index ca5de3148..bbb817275 100644 --- a/docs/mkarray/character.md +++ b/docs/mkarray/character.md @@ -56,24 +56,24 @@ a ## See Also +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type * [Decimal Ranges](../mkarray/decimal.md): Create arrays of decimal integers -* [Non-Decimal Ranges](../mkarray/non-decimal.md): - Create arrays of integers from non-decimal number bases -* [`[ ..Range ]`](../parser/range.md): +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Non-Decimal Ranges](../mkarray/non-decimal.md): + Create arrays of integers from non-decimal number bases +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/mkarray/date.md b/docs/mkarray/date.md index b3e5be3c2..d561caf8a 100644 --- a/docs/mkarray/date.md +++ b/docs/mkarray/date.md @@ -193,26 +193,26 @@ Friday, 03 January ## See Also -* [Special Ranges](../mkarray/special.md): - Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Reverse Array (`mtac`)](../commands/mtac.md): + Reverse the order of an array +* [Special Ranges](../mkarray/special.md): + Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse (`mtac`)](../commands/mtac.md): - Reverse the order of an array -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/mkarray/decimal.md b/docs/mkarray/decimal.md index 11c60176f..615afc3a1 100644 --- a/docs/mkarray/decimal.md +++ b/docs/mkarray/decimal.md @@ -112,22 +112,22 @@ arrays such as JSON (`ja`). * [Character arrays](../mkarray/character.md): Making character arrays (a to z) -* [Non-Decimal Ranges](../mkarray/non-decimal.md): - Create arrays of integers from non-decimal number bases -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Non-Decimal Ranges](../mkarray/non-decimal.md): + Create arrays of integers from non-decimal number bases +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/mkarray/non-decimal.md b/docs/mkarray/non-decimal.md index 83b28892a..968c2aa20 100644 --- a/docs/mkarray/non-decimal.md +++ b/docs/mkarray/non-decimal.md @@ -125,22 +125,22 @@ arrays such as JSON (`ja`). * [Character arrays](../mkarray/character.md): Making character arrays (a to z) +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type * [Decimal Ranges](../mkarray/decimal.md): Create arrays of decimal integers -* [`[ ..Range ]`](../parser/range.md): +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/mkarray/special.md b/docs/mkarray/special.md index afa08aea2..89b3567d6 100644 --- a/docs/mkarray/special.md +++ b/docs/mkarray/special.md @@ -220,24 +220,24 @@ var rangeMoon = map[string]int{ * [Calendar Date Ranges](../mkarray/date.md): Create arrays of dates -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array +* [Reverse Array (`mtac`)](../commands/mtac.md): + Reverse the order of an array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.reverse (`mtac`)](../commands/mtac.md): - Reverse the order of an array -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.count](../commands/count.md): - Count items in a map, list or array
diff --git a/docs/optional/README.md b/docs/optional/README.md index 5e1d62d78..209c95440 100644 --- a/docs/optional/README.md +++ b/docs/optional/README.md @@ -38,6 +38,8 @@ murex-docs trypipe ## Pages +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines * [`!bz2`](../optional/bz2.md): Decompress a bz2 file * [`base64` ](../optional/base64.md): @@ -47,6 +49,4 @@ murex-docs trypipe * [`qr`](../optional/qr.md): Creates a QR code from stdin * [`sleep`](../optional/sleep.md): - Suspends the shell for a number of seconds -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines \ No newline at end of file + Suspends the shell for a number of seconds \ No newline at end of file diff --git a/docs/optional/base64.md b/docs/optional/base64.md index 8d42d7cec..b5802a176 100644 --- a/docs/optional/base64.md +++ b/docs/optional/base64.md @@ -55,18 +55,18 @@ it doesn't require the OS fork processes. ## See Also +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input * [`!bz2`](../optional/bz2.md): Decompress a bz2 file * [`gz`](../optional/gz.md): Compress or decompress a gzip file -* [escape.cli](../commands/esccli.md): - Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): - Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): - Encode or decodes text for the URL
diff --git a/docs/optional/bz2.md b/docs/optional/bz2.md index 2d52bde24..888420a68 100644 --- a/docs/optional/bz2.md +++ b/docs/optional/bz2.md @@ -23,18 +23,18 @@ Currently there is no support for compressing a stream using bz2. ## See Also +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input * [`base64` ](../optional/base64.md): Encode or decode a base64 string * [`gz`](../optional/gz.md): Compress or decompress a gzip file -* [escape.cli](../commands/esccli.md): - Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): - Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): - Encode or decodes text for the URL
diff --git a/docs/optional/gz.md b/docs/optional/gz.md index 81347ec6e..a7aa34044 100644 --- a/docs/optional/gz.md +++ b/docs/optional/gz.md @@ -22,18 +22,18 @@ An optional builtin for compressing or decompressing a gzip stream from stdin. ## See Also +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input * [`!bz2`](../optional/bz2.md): Decompress a bz2 file * [`base64` ](../optional/base64.md): Encode or decode a base64 string -* [escape.cli](../commands/esccli.md): - Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): - Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): - Encode or decodes text for the URL
diff --git a/docs/optional/qr.md b/docs/optional/qr.md index 417bd98a1..36cff3af7 100644 --- a/docs/optional/qr.md +++ b/docs/optional/qr.md @@ -35,9 +35,9 @@ have to `cast` the output in some circumstances. ## See Also -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [fs.open.image](../commands/open-image.md): +* [Render Image In Terminal (`open-image`)](../commands/open-image.md): Renders bitmap image data on your terminal
diff --git a/docs/optional/select.md b/docs/optional/select.md index 22cdf95c9..a56c110c7 100644 --- a/docs/optional/select.md +++ b/docs/optional/select.md @@ -1,4 +1,4 @@ -# table.select: `select` +# Inline SQL (`select`) > Inlining SQL into shell pipelines @@ -133,14 +133,14 @@ If you do run into any issues then please raise them on [Github](https://github. ## See Also +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`*` (generic)](../types/generic.md): generic (primitive) * [`csv`](../types/csv.md): CSV files (and other character delimited tables) * [`jsonl`](../types/jsonl.md): JSON Lines -* [shell.config](../commands/config.md): - Query or define Murex runtime settings * [v2.1](../changelog/v2.1.md): This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details. diff --git a/docs/optional/sleep.md b/docs/optional/sleep.md index 227d1e23f..d1aa8d611 100644 --- a/docs/optional/sleep.md +++ b/docs/optional/sleep.md @@ -32,12 +32,12 @@ or similar platforms then you will need to launch with the `exec` builtin: ## See Also -* [`time`](../commands/time.md): - Returns the execution run time of a command or block -* [exec.file: `exec`](../commands/exec.md): +* [Execute External Command (`exec`)](../commands/exec.md): Runs an executable -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block +* [Processes Execution Time (`time`)](../commands/time.md): + Returns the execution run time of a command or block
diff --git a/docs/parser/README.md b/docs/parser/README.md index f4bb6d567..3971bbd4f 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -303,6 +303,18 @@ files. Inline expressions * [C-style functions](../parser/c-style-fun.md): Inlined commands for expressions and statements +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`$Scalar` Sigil (eg variables)](../parser/scalar.md): @@ -353,12 +365,6 @@ files. Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`[ ..Range ]`](../parser/range.md): - Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [`[{ Lambda }]`](../parser/lambda.md): Iterate through structured data * [`{ Curly Brace }`](../parser/curly-brace.md): diff --git a/docs/parser/add-with.md b/docs/parser/add-with.md index a4890fd55..b8162f754 100644 --- a/docs/parser/add-with.md +++ b/docs/parser/add-with.md @@ -43,8 +43,12 @@ value op value**, for example: ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): Multiplies a variable by the right hand value (expression) * [`+` Addition Operator](../parser/addition.md): @@ -53,8 +57,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -63,8 +65,6 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/addition.md b/docs/parser/addition.md index 080239924..81e7bc228 100644 --- a/docs/parser/addition.md +++ b/docs/parser/addition.md @@ -61,8 +61,12 @@ Error in `expr` (0,1): cannot Add with string types ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): Expressions can auto-convert types or strictly honour data types * [`*` Multiplication Operator](../parser/multiplication.md): @@ -73,8 +77,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -83,8 +85,6 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/array.md b/docs/parser/array.md index 515cb99b7..39c779373 100644 --- a/docs/parser/array.md +++ b/docs/parser/array.md @@ -116,6 +116,12 @@ foo 1 2 3 4 5 bar ## See Also +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`"Double Quote"`](../parser/double-quote.md): @@ -126,16 +132,10 @@ foo 1 2 3 4 5 bar Initiates or terminates a string (variables not expanded) * [`(brace quote)`](../parser/brace-quote-func.md): Write a string to the stdout without new line (deprecated) -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array * [`string` (stringing)](../types/str.md): string (primitive) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/assign-or-merge.md b/docs/parser/assign-or-merge.md index b9ff8c991..e68b0fa23 100644 --- a/docs/parser/assign-or-merge.md +++ b/docs/parser/assign-or-merge.md @@ -90,18 +90,18 @@ builtin. ## See Also +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Globbing (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [fs.glob (`g`)](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input
diff --git a/docs/parser/brace-quote-func.md b/docs/parser/brace-quote-func.md index 21b28c827..2954cca9c 100644 --- a/docs/parser/brace-quote-func.md +++ b/docs/parser/brace-quote-func.md @@ -50,20 +50,20 @@ characters if you don't want them nested. * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences -* [`>>` Append File](../parser/file-append.md): - Writes stdin to disk - appending contents if file already exists -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [io.err](../commands/err.md): +* [Error String (`err`)](../commands/err.md): Print a line to the stderr -* [io.out](../commands/out.md): +* [Get Pipe Status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [io.status (`pt`)](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [`>>` Append File](../parser/file-append.md): + Writes stdin to disk - appending contents if file already exists
diff --git a/docs/parser/brace-quote.md b/docs/parser/brace-quote.md index 15032582e..eafe3403e 100644 --- a/docs/parser/brace-quote.md +++ b/docs/parser/brace-quote.md @@ -90,6 +90,10 @@ Hello (World!) * [Code Block Parsing](../user-guide/code-block.md): Overview of how code blocks are parsed +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`'Single Quote'`](../parser/single-quote.md): @@ -104,10 +108,6 @@ Hello (World!) Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/c-style-fun.md b/docs/parser/c-style-fun.md index 8a573ce1a..9b3d01428 100644 --- a/docs/parser/c-style-fun.md +++ b/docs/parser/c-style-fun.md @@ -101,16 +101,16 @@ It is 23 o' clock ## See Also +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) * [Language Tour](../Murex/tour.md): Getting started with Murex -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators -* [fs.open](../commands/open.md): +* [Open File (`open`)](../commands/open.md): Open a file with a preferred handler -* [io.echo](../commands/out.md): +* [Output String (`echo`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [sub-shell](../parser/sub-shell.md): diff --git a/docs/parser/create-array.md b/docs/parser/create-array.md index 04ba0baae..956dac790 100644 --- a/docs/parser/create-array.md +++ b/docs/parser/create-array.md @@ -175,8 +175,14 @@ arrays. For more details on these please refer to the documents for each format ## See Also +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type * [Special Ranges](../mkarray/special.md): Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`%(Brace Quote)`](../parser/brace-quote.md): @@ -187,12 +193,6 @@ arrays. For more details on these please refer to the documents for each format Initiates or terminates a string (variables not expanded) * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type
diff --git a/docs/parser/curly-brace.md b/docs/parser/curly-brace.md index e5af1145f..36bd29b50 100644 --- a/docs/parser/curly-brace.md +++ b/docs/parser/curly-brace.md @@ -72,6 +72,14 @@ constants are available. Infixed constants that return ANSI escape sequences * [Code Block Parsing](../user-guide/code-block.md): Overview of how code blocks are parsed +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`%(Brace Quote)`](../parser/brace-quote.md): @@ -86,14 +94,6 @@ constants are available. string (primitive) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/divide-by.md b/docs/parser/divide-by.md index 5c9c761ec..84a33abe5 100644 --- a/docs/parser/divide-by.md +++ b/docs/parser/divide-by.md @@ -43,8 +43,12 @@ value op value**, for example: ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): Multiplies a variable by the right hand value (expression) * [`+=` Add With Operator](../parser/add-with.md): @@ -53,8 +57,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -63,8 +65,6 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/division.md b/docs/parser/division.md index 61a4326e0..43eb95838 100644 --- a/docs/parser/division.md +++ b/docs/parser/division.md @@ -56,8 +56,12 @@ Error in `expr` (0,1): cannot Add with string types ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): Expressions can auto-convert types or strictly honour data types * [`*` Multiplication Operator](../parser/multiplication.md): @@ -68,8 +72,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -78,8 +80,6 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/double-quote.md b/docs/parser/double-quote.md index e98322067..a790b4d2e 100644 --- a/docs/parser/double-quote.md +++ b/docs/parser/double-quote.md @@ -35,6 +35,10 @@ bar ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) * [`'Single Quote'`](../parser/single-quote.md): @@ -49,10 +53,6 @@ bar Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/element.md b/docs/parser/element.md index 4f8ca3760..4eb6dc58a 100644 --- a/docs/parser/element.md +++ b/docs/parser/element.md @@ -1,4 +1,4 @@ -# `[[ Element ]]` +# Get Nested Element (`[[ Element ]]`) > Outputs an element from a nested structure @@ -122,20 +122,20 @@ bool ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[ Index ]`](../parser/item-index.md): +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md index aa361494d..f82aaf607 100644 --- a/docs/parser/elvis.md +++ b/docs/parser/elvis.md @@ -49,12 +49,20 @@ where it says: ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes * [`??` Null Coalescing Operator](../parser/null-coalescing.md): @@ -63,16 +71,8 @@ where it says: Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/equ.md b/docs/parser/equ.md index 8341a8799..e6cdb026d 100644 --- a/docs/parser/equ.md +++ b/docs/parser/equ.md @@ -188,30 +188,30 @@ Murex uses the [govaluate package](https://github.com/Knetic/govaluate). More in ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Get Item (`[ Index ]`)](../parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) -* [`[ Index ]`](../parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/expr-inlined.md b/docs/parser/expr-inlined.md index 3b04834e4..638f264db 100644 --- a/docs/parser/expr-inlined.md +++ b/docs/parser/expr-inlined.md @@ -25,10 +25,10 @@ that parameter will be treated like a string. * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Output String (`echo`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [io.echo](../commands/out.md): - Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/file-append.md b/docs/parser/file-append.md index aba38d2a2..89648f318 100644 --- a/docs/parser/file-append.md +++ b/docs/parser/file-append.md @@ -51,20 +51,20 @@ To truncate a file (ie overwrite its contents) use `|>` instead. ## See Also +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe
diff --git a/docs/commands/file-truncate.md b/docs/parser/file-truncate.md similarity index 82% rename from docs/commands/file-truncate.md rename to docs/parser/file-truncate.md index 7b4dc13cb..276607216 100644 --- a/docs/commands/file-truncate.md +++ b/docs/parser/file-truncate.md @@ -1,4 +1,4 @@ -# fs.truncate (`>`) +# Truncate File (`>`) > Writes stdin to disk - overwriting contents if file already exists @@ -24,13 +24,20 @@ g * |> files.txt ## Synonyms * `>` -* `fs.truncate` * `|>` * `fwrite` ## See Also +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Create Temporary File (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [Globbing (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`>>` Append File](../parser/file-append.md): @@ -39,14 +46,6 @@ g * |> files.txt Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [fs.glob (`g`)](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [fs.tmpfile (`tmp`)](../commands/tmp.md): - Create a temporary file and write to it -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe
diff --git a/docs/parser/item-index.md b/docs/parser/item-index.md index 0a10e31df..19e393901 100644 --- a/docs/parser/item-index.md +++ b/docs/parser/item-index.md @@ -1,4 +1,4 @@ -# `[ Index ]` +# Get Item (`[ Index ]`) > Outputs an element from an array, map or table @@ -147,20 +147,20 @@ Error in `[` ((builtin) 2,11): Key 'foobar' not found ## See Also -* [`[ ..Range ]`](../parser/range.md): +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/parser/lambda.md b/docs/parser/lambda.md index f38255d0d..ec7d0b80c 100644 --- a/docs/parser/lambda.md +++ b/docs/parser/lambda.md @@ -181,22 +181,22 @@ The following meta values are defined: ## See Also -* [`%[]` Array Builder](../parser/create-array.md): - Quickly generate arrays -* [`%{}` Object Builder](../parser/create-object.md): - Quickly generate objects (dictionaries / maps) -* [`foreach`](../commands/foreach.md): +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`while`](../commands/while.md): +* [Loop While (`while`)](../commands/while.md): Loop until condition false -* [list.regex](../commands/regexp.md): +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [`%[]` Array Builder](../parser/create-array.md): + Quickly generate arrays +* [`%{}` Object Builder](../parser/create-object.md): + Quickly generate objects (dictionaries / maps)
diff --git a/docs/parser/logical-and.md b/docs/parser/logical-and.md index 1e83c68f2..e106cab35 100644 --- a/docs/parser/logical-and.md +++ b/docs/parser/logical-and.md @@ -47,24 +47,24 @@ try { ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`?:` Elvis Operator](../parser/elvis.md): Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/logical-or.md b/docs/parser/logical-or.md index d05d01d49..6fb6c9dc0 100644 --- a/docs/parser/logical-or.md +++ b/docs/parser/logical-or.md @@ -50,24 +50,24 @@ There is no workaround for `trypipe`. ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes * [`?:` Elvis Operator](../parser/elvis.md): Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character
diff --git a/docs/parser/multiplication.md b/docs/parser/multiplication.md index 077b34e55..4d09ba6e5 100644 --- a/docs/parser/multiplication.md +++ b/docs/parser/multiplication.md @@ -56,8 +56,12 @@ Error in `expr` (0,1): cannot Add with string types ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): Expressions can auto-convert types or strictly honour data types * [`*=` Multiply By Operator](../parser/multiply-by.md): @@ -68,8 +72,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -78,8 +80,6 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/multiply-by.md b/docs/parser/multiply-by.md index 32bfd524f..7f31e0b06 100644 --- a/docs/parser/multiply-by.md +++ b/docs/parser/multiply-by.md @@ -43,8 +43,12 @@ value op value**, for example: ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`*` Multiplication Operator](../parser/multiplication.md): Multiplies one numeric value with another (expression) * [`+=` Add With Operator](../parser/add-with.md): @@ -53,8 +57,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -63,8 +65,6 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/commands/namedpipe.md b/docs/parser/namedpipe.md similarity index 87% rename from docs/commands/namedpipe.md rename to docs/parser/namedpipe.md index ab63a7627..521f77654 100644 --- a/docs/commands/namedpipe.md +++ b/docs/parser/namedpipe.md @@ -1,4 +1,4 @@ -# io.pipe (``) +# Read / Write To A Named Pipe (``) > Reads from a Murex named pipe @@ -113,23 +113,22 @@ that pipes created in modules should be prefixed with the name of its package. * `(murex named pipe)` * `<>` * `read-named-pipe` -* `io.pipe` ## See Also -* [`ja` (mkarray)](../commands/ja.md): +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [Create JSON Array (`ja`)](../commands/ja.md): A sophisticated yet simply way to build a JSON array -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [io.new.pipe](../commands/pipe.md): +* [Create Named Pipe (`pipe`)](../commands/pipe.md): Manage Murex named pipes -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [proc.bg](../commands/bg.md): - Run processes in the background -* [shell.runtime](../commands/runtime.md): +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md index ef7dfbce1..d718e8374 100644 --- a/docs/parser/null-coalescing.md +++ b/docs/parser/null-coalescing.md @@ -54,12 +54,22 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Schedulers](../user-guide/schedulers.md): Overview of the different schedulers (or 'run modes') in Murex +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes * [`?:` Elvis Operator](../parser/elvis.md): @@ -68,18 +78,8 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character * [null](../commands/devnull.md): null function. Similar to /dev/null diff --git a/docs/parser/pipe-arrow.md b/docs/parser/pipe-arrow.md index 8878ac61e..17dcc8638 100644 --- a/docs/parser/pipe-arrow.md +++ b/docs/parser/pipe-arrow.md @@ -49,22 +49,22 @@ Hello, Earth! ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [list.regex](../commands/regexp.md): - Regexp tools for arrays / lists of strings
diff --git a/docs/parser/pipe-err.md b/docs/parser/pipe-err.md index ecdef523e..d2501bf61 100644 --- a/docs/parser/pipe-err.md +++ b/docs/parser/pipe-err.md @@ -41,22 +41,22 @@ Hello, world!? regexp s/world/Earth/ ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [list.regex](../commands/regexp.md): - Regexp tools for arrays / lists of strings
diff --git a/docs/parser/pipe-generic.md b/docs/parser/pipe-generic.md index 9508dee68..04c0ba83c 100644 --- a/docs/parser/pipe-generic.md +++ b/docs/parser/pipe-generic.md @@ -48,20 +48,20 @@ To demonstrate how the previous pipeline might look without a formatted pipe: ## See Also +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe
diff --git a/docs/parser/pipe-posix.md b/docs/parser/pipe-posix.md index b6002272a..c8ead49d2 100644 --- a/docs/parser/pipe-posix.md +++ b/docs/parser/pipe-posix.md @@ -44,22 +44,22 @@ Hello, Earth! ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [list.regex](../commands/regexp.md): - Regexp tools for arrays / lists of strings
diff --git a/docs/parser/range.md b/docs/parser/range.md index 1a81fb838..edd0bc456 100644 --- a/docs/parser/range.md +++ b/docs/parser/range.md @@ -1,4 +1,4 @@ -# `[ ..Range ]` +# Filter By Range `[ ..Range ]` > Outputs a ranged subset of data from stdin @@ -96,24 +96,24 @@ December ## See Also -* [`[ Index ]`](../parser/item-index.md): +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.prepend](../commands/prepend.md): +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [str.split](../commands/jsplit.md): +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): - Count items in a map, list or array +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray)
diff --git a/docs/parser/scalar.md b/docs/parser/scalar.md index a4d7d983a..cc051defb 100644 --- a/docs/parser/scalar.md +++ b/docs/parser/scalar.md @@ -157,6 +157,12 @@ do not. ## See Also +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`"Double Quote"`](../parser/double-quote.md): @@ -169,16 +175,10 @@ do not. Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/parser/single-quote.md b/docs/parser/single-quote.md index c38016bc0..5f238d99f 100644 --- a/docs/parser/single-quote.md +++ b/docs/parser/single-quote.md @@ -34,6 +34,10 @@ bar ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [`"Double Quote"`](../parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`%(Brace Quote)`](../parser/brace-quote.md): @@ -48,10 +52,6 @@ bar Initiates or terminates a code block * [`~` Home Sigil](../parser/tilde.md): Home directory path variable -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/commands/stdin.md b/docs/parser/stdin.md similarity index 90% rename from docs/commands/stdin.md rename to docs/parser/stdin.md index dd080c27b..c43231992 100644 --- a/docs/commands/stdin.md +++ b/docs/parser/stdin.md @@ -1,4 +1,4 @@ -# io.in (``) +# Read From Stdin (``) > Read the stdin belonging to the parent code block @@ -127,24 +127,23 @@ that pipes created in modules should be prefixed with the name of its package. ## Synonyms * `` -* `io.in` ## See Also -* [Pipeline](../user-guide/pipeline.md): - Overview of what a "pipeline" is -* [io.new.pipe](../commands/pipe.md): +* [Create Named Pipe (`pipe`)](../commands/pipe.md): Manage Murex named pipes -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [list.str (`match`)](../commands/match.md): +* [Match String (`match`)](../commands/match.md): Match an exact value in an array -* [shell.function](../commands/function.md): +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Pipeline](../user-guide/pipeline.md): + Overview of what a "pipeline" is +* [Public Function (`function`)](../commands/function.md): Define a function block -* [shell.runtime](../commands/runtime.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): + Reads from a Murex named pipe +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/parser/subtract-by.md b/docs/parser/subtract-by.md index bfdd0426f..f4772ff7a 100644 --- a/docs/parser/subtract-by.md +++ b/docs/parser/subtract-by.md @@ -43,8 +43,12 @@ value op value**, for example: ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): Multiplies a variable by the right hand value (expression) * [`+=` Add With Operator](../parser/add-with.md): @@ -53,8 +57,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`-` Subtraction Operator](../parser/subtraction.md): Subtracts one numeric value from another (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -63,8 +65,6 @@ value op value**, for example: Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/subtraction.md b/docs/parser/subtraction.md index 25cf28780..0f740f7d2 100644 --- a/docs/parser/subtraction.md +++ b/docs/parser/subtraction.md @@ -56,8 +56,12 @@ Error in `expr` (0,1): cannot Add with string types ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): Expressions can auto-convert types or strictly honour data types * [`*` Multiplication Operator](../parser/multiplication.md): @@ -68,8 +72,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts a variable by the right hand value (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): @@ -78,8 +80,6 @@ Error in `expr` (0,1): cannot Add with string types Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/parser/tilde.md b/docs/parser/tilde.md index d8ba89d27..1a3b8e756 100644 --- a/docs/parser/tilde.md +++ b/docs/parser/tilde.md @@ -60,6 +60,12 @@ But it cannot be expanded inside single quotes. ## See Also +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`"Double Quote"`](../parser/double-quote.md): @@ -72,14 +78,8 @@ But it cannot be expanded inside single quotes. Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/types/commonlog.md b/docs/types/commonlog.md index 3eed67106..ba2148594 100644 --- a/docs/types/commonlog.md +++ b/docs/types/commonlog.md @@ -33,14 +33,14 @@ the following: ## See Also -* [`*` (generic)](../types/generic.md): - generic (primitive) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [`*` (generic)](../types/generic.md): + generic (primitive) * [`str` (string)](../types/str.md): string (primitive) * [index](../parser/item-index.md): diff --git a/docs/types/csv.md b/docs/types/csv.md index f0c2268a4..40cf11fbf 100644 --- a/docs/types/csv.md +++ b/docs/types/csv.md @@ -64,14 +64,18 @@ use `config`) ## See Also -* [`*` (generic)](../types/generic.md): - generic (primitive) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [`*` (generic)](../types/generic.md): + generic (primitive) * [`int`](../types/int.md): Whole number (primitive) * [`jsonl`](../types/jsonl.md): @@ -80,10 +84,6 @@ use `config`) string (primitive) * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines ### Read more about type hooks diff --git a/docs/types/generic.md b/docs/types/generic.md index d313eb027..adb0f88e6 100644 --- a/docs/types/generic.md +++ b/docs/types/generic.md @@ -28,24 +28,24 @@ executables. ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`int`](../types/int.md): Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/hcl.md b/docs/types/hcl.md index a08b6b4a6..08d157a8d 100644 --- a/docs/types/hcl.md +++ b/docs/types/hcl.md @@ -85,28 +85,28 @@ See the HashiCorp's [documentation](https://github.com/hashicorp/hcl) for HCL sy ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/int.md b/docs/types/int.md index 1de201cab..d2b1a0b64 100644 --- a/docs/types/int.md +++ b/docs/types/int.md @@ -28,22 +28,22 @@ AMD64 or other 64bit built of Murex would see the range from ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`num` (number)](../types/num.md): Floating point number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/json.md b/docs/types/json.md index 934e7f4c9..1a10e3297 100644 --- a/docs/types/json.md +++ b/docs/types/json.md @@ -211,12 +211,18 @@ jsonl ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`hcl`](../types/hcl.md): HashiCorp Configuration Language (HCL) * [`jsonc`](../types/jsonc.md): @@ -227,16 +233,10 @@ jsonl Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonc.md b/docs/types/jsonc.md index a48cea521..65cc0d798 100644 --- a/docs/types/jsonc.md +++ b/docs/types/jsonc.md @@ -130,18 +130,24 @@ parser is still in beta), it is shipped as an additional data-type. ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`*` (generic)](../types/generic.md): generic (primitive) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`format`](../commands/format.md): - Reformat one data-type into another data-type * [`hcl`](../types/hcl.md): HashiCorp Configuration Language (HCL) * [`json`](../types/json.md): @@ -152,16 +158,10 @@ parser is still in beta), it is shipped as an additional data-type. Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/jsonl.md b/docs/types/jsonl.md index c9fbe24cb..8453c5fb3 100644 --- a/docs/types/jsonl.md +++ b/docs/types/jsonl.md @@ -141,18 +141,24 @@ cases for JSON lines. ## See Also +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`*` (generic)](../types/generic.md): generic (primitive) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`format`](../commands/format.md): - Reformat one data-type into another data-type * [`hcl`](../types/hcl.md): HashiCorp Configuration Language (HCL) * [`json`](../types/json.md): @@ -163,16 +169,10 @@ cases for JSON lines. Tom's Obvious, Minimal Language (TOML) * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table * [mxjson](../types/mxjson.md): Murex-flavoured JSON (deprecated) -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/mxjson.md b/docs/types/mxjson.md index d9fa70749..c0a7e3506 100644 --- a/docs/types/mxjson.md +++ b/docs/types/mxjson.md @@ -52,18 +52,28 @@ Any block quoted by this method will be converted to the following valid JSON: * [Code Block Parsing](../user-guide/code-block.md): Overview of how code blocks are parsed +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays * [`%{}` Object Builder](../parser/create-object.md): Quickly generate objects (dictionaries / maps) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): - Reformat one data-type into another data-type * [`hcl`](../types/hcl.md): HashiCorp Configuration Language (HCL) * [`json`](../types/json.md): @@ -78,18 +88,8 @@ Any block quoted by this method will be converted to the following valid JSON: YAML Ain't Markup Language (YAML) * [`{ Curly Brace }`](../parser/curly-brace.md): Initiates or terminates a code block -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable ### Read more about type hooks diff --git a/docs/types/num.md b/docs/types/num.md index 05f63981f..4e59dd41e 100644 --- a/docs/types/num.md +++ b/docs/types/num.md @@ -19,22 +19,22 @@ numbers. ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`int`](../types/int.md): Whole number (primitive) * [`str` (string)](../types/str.md): string (primitive) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/str.md b/docs/types/str.md index 7ff9048ba..f7a261010 100644 --- a/docs/types/str.md +++ b/docs/types/str.md @@ -28,24 +28,24 @@ This type is modelled closely on generic but is more tailored for textual ## See Also -* [`*` (generic)](../types/generic.md): - generic (primitive) -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex +* [`*` (generic)](../types/generic.md): + generic (primitive) * [`int`](../types/int.md): Whole number (primitive) * [`num` (number)](../types/num.md): Floating point number (primitive) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/toml.md b/docs/types/toml.md index d39c2a922..d2d189a9b 100644 --- a/docs/types/toml.md +++ b/docs/types/toml.md @@ -76,24 +76,24 @@ hosts = [ ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines * [`yaml`](../types/yaml.md): YAML Ain't Markup Language (YAML) -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/types/yaml.md b/docs/types/yaml.md index db89ff29a..59d46738c 100644 --- a/docs/types/yaml.md +++ b/docs/types/yaml.md @@ -41,22 +41,22 @@ external source packages for the shell to compile. ## See Also -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`cast`](../commands/cast.md): +* [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output -* [`format`](../commands/format.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Reformat Data type (`format`)](../commands/format.md): Reformat one data-type into another data-type +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`jsonl`](../types/jsonl.md): JSON Lines -* [fs.open](../commands/open.md): - Open a file with a preferred handler * [index](../parser/item-index.md): Outputs an element from an array, map or table -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex ### Read more about type hooks diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 9af367e4c..2c84e2cb8 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -72,6 +72,18 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Inline expressions * [C-style functions](parser/c-style-fun.md): Inlined commands for expressions and statements +* [Filter By Range `[ ..Range ]`](parser/range.md): + Outputs a ranged subset of data from stdin +* [Get Item (`[ Index ]`)](parser/item-index.md): + Outputs an element from an array, map or table +* [Get Nested Element (`[[ Element ]]`)](parser/element.md): + Outputs an element from a nested structure +* [Read / Write To A Named Pipe (``)](parser/namedpipe.md): + Reads from a Murex named pipe +* [Read From Stdin (``)](parser/stdin.md): + Read the stdin belonging to the parent code block +* [Truncate File (`>`)](parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists * [`"Double Quote"`](parser/double-quote.md): Initiates or terminates a string (variables expanded) * [`$Scalar` Sigil (eg variables)](parser/scalar.md): @@ -122,12 +134,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`@Array` Sigil](parser/array.md): Expand values as an array -* [`[ ..Range ]`](parser/range.md): - Outputs a ranged subset of data from stdin -* [`[ Index ]`](parser/item-index.md): - Outputs an element from an array, map or table -* [`[[ Element ]]`](parser/element.md): - Outputs an element from a nested structure * [`[{ Lambda }]`](parser/lambda.md): Iterate through structured data * [`{ Curly Brace }`](parser/curly-brace.md): @@ -143,250 +149,248 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. ### Standard Builtins -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`args` ](../commands/args.md): - Command line flag parser for Murex shell scripting -* [`break`](../commands/break.md): - Terminate execution of a block within your processes scope -* [`cast`](../commands/cast.md): - Alters the data-type of the previous function without altering its output -* [`catch`](../commands/catch.md): +* [Add Heading (`addheading`)](../commands/addheading.md): + Adds headings to a table +* [Add Prefix (`prefix`)](../commands/prefix.md): + Prefix a string to every item in a list +* [Add Suffix (`suffix`)](../commands/suffix.md): + Prefix a string to every item in a list +* [Alias Pointer (`alias`)](../commands/alias.md): + Create an alias for a command +* [Alter Data Structure (`alter`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Append To List (`append`)](../commands/append.md): + Add data to the end of an array +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background +* [CPU Architecture (`cpuarch`)](../commands/cpuarch.md): + Output the hosts CPU architecture +* [CPU Count (`cpucount`)](../commands/cpucount.md): + Output the number of CPU cores available on your host +* [Caught Error Block (`catch`)](../commands/catch.md): Handles the exception code raised by `try` or `trypipe` -* [`cd`](../commands/cd.md): +* [Change Directory (`cd`)](../commands/cd.md): Change (working) directory -* [`continue`](../commands/continue.md): - Terminate process of a block within a caller function -* [`die`](../commands/die.md): - Terminate murex with an exit number of 1 (deprecated) -* [`event`](../commands/event.md): - Event driven programming for shell scripts -* [`exit`](../commands/exit.md): +* [Change Text Case (`list.case`)](../commands/list.case.md): + Changes the character case of a string or all elements in an array +* [Check Builtin Exists (`bexists`)](../commands/bexists.md): + Check which builtins exist +* [Command Line History (`history`)](../commands/history.md): + Outputs murex's command history +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Create 2d Array (`2darray`)](../commands/2darray.md): + Create a 2D JSON array from multiple input sources +* [Create JSON Array (`ja`)](../commands/ja.md): + A sophisticated yet simply way to build a JSON array +* [Create Map (`map`)](../commands/map.md): + Creates a map from two data sources +* [Create Named Pipe (`pipe`)](../commands/pipe.md): + Manage Murex named pipes +* [Create New Array (`ta`)](../commands/ta.md): + A sophisticated yet simple way to build an array of a user defined data-type +* [Create Temporary File (`tmp`)](../commands/tmp.md): + Create a temporary file and write to it +* [Date And Time Conversion (`datetime`)](../commands/datetime.md): + A date and/or time conversion tool (like `printf` but for date and time values) +* [Debugging Mode (`debug`)](../commands/debug.md): + Debugging information +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Function Arguments (`args`)](../commands/args.md): + Command line flag parser for Murex shell scripting +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types +* [Define Type (`cast`)](../commands/cast.md): + Alters the data-type of the previous function without altering its output +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Display Command Type (`type`)](../commands/type.md): + Command type (function, builtin, alias, etc) +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Download File (`getfile`)](../commands/getfile.md): + Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Escape Command Line String (`esccli`)](../commands/esccli.md): + Escapes an array so output is valid shell code +* [Escape HTML (`eschtml`)](../commands/eschtml.md): + Encode or decodes text for HTML +* [Escape URL (`escurl`)](../commands/escurl.md): + Encode or decodes text for the URL +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Exit Block (`break`)](../commands/break.md): + Terminate execution of a block within your processes scope +* [Exit Function (`return`)](../commands/return.md): + Exits current function scope +* [Exit Murex (`exit`)](../commands/exit.md): Exit murex -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators -* [`false`](../commands/false.md): +* [False (`false`)](../commands/false.md): Returns a `false` value -* [`for`](../commands/for.md): - A more familiar iteration loop to existing developers -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`format`](../commands/format.md): - Reformat one data-type into another data-type -* [`get-type`](../commands/get-type.md): +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [Foreground Process (`fg`)](../commands/fg.md): + Sends a background process into the foreground +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Generate Random Sequence (`rand`)](../commands/rand.md): + Random field generator +* [Get Data Type (`get-type`)](../commands/get-type.md): Returns the data-type of a variable or pipe -* [`get`](../commands/get.md): +* [Get Exit Code (`exitnum`)](../commands/exitnum.md): + Output the exit number of the previous process +* [Get Pipe Status (`pt`)](../commands/pt.md): + Pipe telemetry. Writes data-types and bytes written +* [Get Request (`get`)](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object -* [`getfile`](../commands/getfile.md): - Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. -* [`if`](../commands/if.md): +* [Globbing (`g`)](../commands/g.md): + Glob pattern matching for file system objects (eg `*.txt`) +* [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition -* [`is-null`](../commands/is-null.md): - Checks if a variable is null or undefined -* [`ja` (mkarray)](../commands/ja.md): - A sophisticated yet simply way to build a JSON array -* [`key-code`](../commands/key-code.md): - Returns character sequences for any key pressed (ie sent from the terminal) -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) -* [`murex-docs`](../commands/murex-docs.md): - Displays the man pages for Murex builtins -* [`null`](../commands/devnull.md): - null function. Similar to /dev/null -* [`or`](../commands/or.md): - Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [`post`](../commands/post.md): - HTTP POST request with a JSON-parsable return -* [`rand`](../commands/rand.md): - Random field generator -* [`return`](../commands/return.md): - Exits current function scope -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`signal`](../commands/signal.md): - Sends a signal RPC -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [`tabulate`](../commands/tabulate.md): - Table transformation tools -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [`time`](../commands/time.md): - Returns the execution run time of a command or block -* [`true`](../commands/true.md): - Returns a `true` value -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): - Checks state of each function in a pipeline and exits block on error -* [`type`](../commands/type.md): - Command type (function, builtin, alias, etc) -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number -* [`which`](../commands/which.md): - Locate command origin -* [`while`](../commands/while.md): - Loop until condition false -* [escape.cli](../commands/esccli.md): - Escapes an array so output is valid shell code -* [escape.html](../commands/eschtml.md): - Encode or decodes text for HTML -* [escape.quote](../commands/escape.md): - Escape or unescape input -* [escape.url](../commands/escurl.md): - Encode or decodes text for the URL -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block -* [fs.files (`f`)](../commands/f.md): +* [Is Value Null (`is-null`)](../commands/is-null.md): + Checks if a variable is null or undefined +* [Join Array To String (`mjoin`)](../commands/mjoin.md): + Joins a list or array into a single string +* [Kill All In Session (`fid-killall`)](../commands/fid-killall.md): + Terminate all running Murex functions in current session +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): + Terminate a running Murex function +* [Left Sub-String (`left`)](../commands/left.md): + Left substring every item in a list +* [List Filesystem Objects (`f`)](../commands/f.md): Lists or filters file system objects (eg files) -* [fs.glob (`g`)](../commands/g.md): - Glob pattern matching for file system objects (eg `*.txt`) -* [fs.lockfile](../commands/lockfile.md): +* [Location Of Command (`which`)](../commands/which.md): + Locate command origin +* [Lock Files (`lockfile`)](../commands/lockfile.md): Create and manage lock files -* [fs.open](../commands/open.md): - Open a file with a preferred handler -* [fs.open.image](../commands/open-image.md): - Renders bitmap image data on your terminal -* [fs.regex (`rx`)](../commands/rx.md): - Regexp pattern matching for file system objects (eg `.*\\.txt`) -* [fs.tmpfile (`tmp`)](../commands/tmp.md): - Create a temporary file and write to it -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists -* [help.man.flags](../commands/man-get-flags.md): - Parses man page files for command line flags -* [help.man.summary](../commands/man-summary.md): +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): + Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. +* [Loop While (`while`)](../commands/while.md): + Loop until condition false +* [Man-Page Summary (`man-summary`)](../commands/man-summary.md): Outputs a man page summary of a command -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [io.new.pipe](../commands/pipe.md): - Manage Murex named pipes -* [io.out](../commands/out.md): +* [Match String (`match`)](../commands/match.md): + Match an exact value in an array +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): + Murex's package manager +* [Murex Version (`version`)](../commands/version.md): + Get Murex version +* [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): + Displays the man pages for Murex builtins +* [Next Iteration (`continue`)](../commands/continue.md): + Terminate process of a block within a caller function +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition +* [Null (`null`)](../commands/devnull.md): + null function. Similar to /dev/null +* [Open File (`open`)](../commands/open.md): + Open a file with a preferred handler +* [Operating System (`os`)](../commands/os.md): + Output the auto-detected OS name +* [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): +* [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [io.pipe (``)](../commands/namedpipe.md): - Reads from a Murex named pipe -* [io.read](../commands/read.md): - `read` a line of input from the user and store as a variable -* [io.status (`pt`)](../commands/pt.md): - Pipe telemetry. Writes data-types and bytes written -* [list.append](../commands/append.md): - Add data to the end of an array -* [list.case](../commands/list.case.md): - Changes the character case of a string or all elements in an array -* [list.join](../commands/mjoin.md): - Joins a list or array into a single string -* [list.left](../commands/left.md): - Left substring every item in a list -* [list.new.str (`a`)](../commands/a.md): - A sophisticated yet simple way to build an array or list (mkarray) -* [list.new.type: `ta`](../commands/ta.md): - A sophisticated yet simple way to build an array of a user defined data-type -* [list.prefix](../commands/prefix.md): - Prefix a string to every item in a list -* [list.prepend](../commands/prepend.md): +* [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): + Parses man page files for command line flags +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline +* [Post Request (`post`)](../commands/post.md): + HTTP POST request with a JSON-parsable return +* [Prepend To List (`prepend`)](../commands/prepend.md): Add data to the start of an array -* [list.regex](../commands/regexp.md): +* [Prettify JSON](../commands/pretty.md): + Prettifies JSON to make it human readable +* [Print Map / Structure Keys (`struct-keys`)](../commands/struct-keys.md): + Outputs all the keys in a structure as a file path +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Processes Execution Time (`time`)](../commands/time.md): + Returns the execution run time of a command or block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Quote String (`escape`)](../commands/escape.md): + Escape or unescape input +* [Re-Scan $PATH For Executables](../commands/murex-update-exe-list.md): + Forces Murex to rescan $PATH looking for executables +* [Read User Input (`read`)](../commands/read.md): + `read` a line of input from the user and store as a variable +* [Read With Type (`tread`) (removed 7.x)](../commands/tread.md): + `read` a line of input from the user and store as a user defined *typed* variable (deprecated) +* [Reformat Data type (`format`)](../commands/format.md): + Reformat one data-type into another data-type +* [Regex Matches (`rx`)](../commands/rx.md): + Regexp pattern matching for file system objects (eg `.*\\.txt`) +* [Regex Operations (`regexp`)](../commands/regexp.md): Regexp tools for arrays / lists of strings -* [list.reverse (`mtac`)](../commands/mtac.md): +* [Render Image In Terminal (`open-image`)](../commands/open-image.md): + Renders bitmap image data on your terminal +* [Reverse Array (`mtac`)](../commands/mtac.md): Reverse the order of an array -* [list.right](../commands/right.md): +* [Right Sub-String (`right`)](../commands/right.md): Right substring every item in a list -* [list.sort](../commands/msort.md): - Sorts an array - data type agnostic -* [list.str (`match`)](../commands/match.md): - Match an exact value in an array -* [list.suffix](../commands/suffix.md): - Prefix a string to every item in a list -* [num.round: `round`](../commands/round.md): +* [Round Number (`round`)](../commands/round.md): Round a number by a user defined precision -* [proc.bg](../commands/bg.md): - Run processes in the background -* [proc.exitnum](../commands/exitnum.md): - Output the exit number of the previous process -* [proc.fg](../commands/fg.md): - Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): - Terminate a running Murex function -* [proc.kill.all](../commands/fid-killall.md): - Terminate _all_ running Murex functions -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [shell.alias](../commands/alias.md): - Create an alias for a command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.builtins.exist](../commands/bexists.md): - Check which builtins exist -* [shell.config](../commands/config.md): +* [Set Command Summary Hint (`summary`)](../commands/summary.md): + Defines a summary help text for a command +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [shell.debug](../commands/debug.md): - Debugging information -* [shell.function](../commands/function.md): - Define a function block -* [shell.history](../commands/history.md): - Outputs murex's command history -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.packages (`murex-package`)](../commands/murex-package.md): - Murex's package manager -* [shell.private](../commands/private.md): - Define a private function block -* [shell.rescan.path](../commands/murex-update-exe-list.md): - Forces Murex to rescan $PATH looking for executables -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [shell.summary](../commands/summary.md): - Defines a summary help text for a command -* [shell.version](../commands/version.md): - Get Murex version -* [str.datetime: `datetime`](../commands/datetime.md): - A date and/or time conversion tool (like `printf` but for date and time values) -* [str.split](../commands/jsplit.md): +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts +* [Sort Array (`msort`)](../commands/msort.md): + Sorts an array - data type agnostic +* [Split String (`jsplit`)](../commands/jsplit.md): Splits stdin into a JSON array based on a regex parameter -* [struct.alter](../commands/alter.md): - Change a value within a structured data-type and pass that change along the pipeline without altering the original source input -* [struct.count](../commands/count.md): - Count items in a map, list or array -* [struct.json.pretty](../commands/pretty.md): - Prettifies JSON to make it human readable -* [struct.keys](../commands/struct-keys.md): - Outputs all the keys in a structure as a file path -* [struct.new.2darray](../commands/2darray.md): - Create a 2D JSON array from multiple input sources -* [struct.new.map (`map`)](../commands/map.md): - Creates a map from two data sources -* [sys.cpu.arch](../commands/cpuarch.md): - Output the hosts CPU architecture -* [sys.cpu.count](../commands/cpucount.md): - Output the number of CPU cores available on your host -* [sys.os](../commands/os.md): - Output the auto-detected OS name -* [table.add.heading](../commands/addheading.md): - Adds headings to a table -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): + Checks state of each function in a pipeline and exits block on error +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Stream New List (`a`)](../commands/a.md): + A sophisticated yet simple way to stream an array or list (mkarray) +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line +* [Transformation Tools (`tabulate`)](../commands/tabulate.md): + Table transformation tools +* [True (`true`)](../commands/true.md): + Returns a `true` value +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code +* [`die`](../commands/die.md): + Terminate murex with an exit number of 1 (deprecated) +* [`event`](../commands/event.md): + Event driven programming for shell scripts +* [`expr`](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators +* [`key-code`](../commands/key-code.md): + Returns character sequences for any key pressed (ie sent from the terminal) +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated) +* [`murex-parser`](../commands/murex-parser.md): + Runs the Murex parser against a block of code +* [`signal`](../commands/signal.md): + Sends a signal RPC ### Optional Builtins @@ -394,6 +398,8 @@ These builtins are optional. `select` is included as part of the default build but can be disabled without breaking functionality. The other optional builtins are only included by default on Windows. +* [Inline SQL (`select`)](../optional/select.md): + Inlining SQL into shell pipelines * [`!bz2`](../optional/bz2.md): Decompress a bz2 file * [`base64` ](../optional/base64.md): @@ -404,8 +410,6 @@ are only included by default on Windows. Creates a QR code from stdin * [`sleep`](../optional/sleep.md): Suspends the shell for a number of seconds -* [table.select: `select`](../optional/select.md): - Inlining SQL into shell pipelines ## Data Types diff --git a/docs/user-guide/ansi.md b/docs/user-guide/ansi.md index 278e37d5e..dce670f81 100644 --- a/docs/user-guide/ansi.md +++ b/docs/user-guide/ansi.md @@ -222,18 +222,18 @@ it persistent. ## See Also +* [Error String (`err`)](../commands/err.md): + Print a line to the stderr +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Output With Type Annotation (`tout`)](../commands/tout.md): + Print a string to the stdout and set it's data-type * [Profile Files](../user-guide/profile.md): A breakdown of the different files loaded on start up * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) * [`(brace quote)`](../parser/brace-quote-func.md): Write a string to the stdout without new line (deprecated) -* [io.err](../commands/err.md): - Print a line to the stderr -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [io.out.type (`tout`)](../commands/tout.md): - Print a string to the stdout and set it's data-type
diff --git a/docs/user-guide/bang-prefix.md b/docs/user-guide/bang-prefix.md index af3ba8c19..993029e99 100644 --- a/docs/user-guide/bang-prefix.md +++ b/docs/user-guide/bang-prefix.md @@ -21,20 +21,20 @@ bang prefix and what the behavior of that prefix is. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Logic And Statements (`and`)](../commands/and.md): + Returns `true` or `false` depending on whether multiple conditions are met +* [Logic Or Statements (`or`)](../commands/or.md): + Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. +* [Not (`!`)](../commands/not-func.md): + Reads the stdin and exit number from previous process and not's it's condition * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`!` (not)](../commands/not-func.md): - Reads the stdin and exit number from previous process and not's it's condition -* [`and`](../commands/and.md): - Returns `true` or `false` depending on whether multiple conditions are met -* [`or`](../commands/or.md): - Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful. -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/user-guide/fileref.md b/docs/user-guide/fileref.md index 72bde0621..57cfd9784 100644 --- a/docs/user-guide/fileref.md +++ b/docs/user-guide/fileref.md @@ -54,15 +54,15 @@ empty Filename string. ## See Also -* [Modules And Packages](../user-guide/modules.md): - An introduction to Murex modules and packages -* [`[[ Element ]]`](../parser/element.md): +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): Outputs an element from a nested structure -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.packages (`murex-package`)](../commands/murex-package.md): +* [Modules And Packages](../user-guide/modules.md): + An introduction to Murex modules and packages +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [shell.runtime](../commands/runtime.md): +* [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex
diff --git a/docs/user-guide/hint-text.md b/docs/user-guide/hint-text.md index 35630e035..6a80c5760 100644 --- a/docs/user-guide/hint-text.md +++ b/docs/user-guide/hint-text.md @@ -87,7 +87,7 @@ prompt: * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? -* [shell.config](../commands/config.md): +* [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings
diff --git a/docs/user-guide/interactive-shell.md b/docs/user-guide/interactive-shell.md index f24ab37e5..9719deb18 100644 --- a/docs/user-guide/interactive-shell.md +++ b/docs/user-guide/interactive-shell.md @@ -215,10 +215,18 @@ give you as much useful detail as it can. Infixed constants that return ANSI escape sequences * [Code Block Parsing](../user-guide/code-block.md): Overview of how code blocks are parsed +* [Define Method Relationships (`method`)](../commands/method.md): + Define a methods supported data-types * [Hint Text](../user-guide/hint-text.md): A status bar for your shell +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Shell Runtime (`runtime`)](../commands/runtime.md): + Returns runtime information on the internal state of Murex * [Spellcheck](../integrations/spellcheck.md): How to enable inline spellchecking +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses * [`->` Arrow Pipe](../parser/pipe-arrow.md): @@ -229,14 +237,6 @@ give you as much useful detail as it can. Initiates or terminates a code block * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.method](../commands/method.md): - Define a methods supported data-types -* [shell.runtime](../commands/runtime.md): - Returns runtime information on the internal state of Murex
diff --git a/docs/user-guide/job-control.md b/docs/user-guide/job-control.md index 1ed76526e..09ec36f0a 100644 --- a/docs/user-guide/job-control.md +++ b/docs/user-guide/job-control.md @@ -138,22 +138,22 @@ Task 1 ## See Also -* [Terminal Hotkeys](../user-guide/terminal-keys.md): - A list of all the terminal hotkeys and their uses -* [exec.* (`fexec`)](../commands/fexec.md): - Execute a command or function, bypassing the usual order of precedence. -* [exec.file: `exec`](../commands/exec.md): - Runs an executable -* [jobs](../commands/fid-list.md): - Lists all running functions within the current Murex session -* [proc.bg](../commands/bg.md): +* [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [proc.fg](../commands/fg.md): +* [Display Running Functions (`fid-list`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Display Running Functions (`jobs`)](../commands/fid-list.md): + Lists all running functions within the current Murex session +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Execute Shell Function or Builtin (`fexec`)](../commands/fexec.md): + Execute a command or function, bypassing the usual order of precedence. +* [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground -* [proc.kill](../commands/fid-kill.md): +* [Kill Function (`fid-kill`)](../commands/fid-kill.md): Terminate a running Murex function -* [proc.list](../commands/fid-list.md): - Lists all running functions within the current Murex session +* [Terminal Hotkeys](../user-guide/terminal-keys.md): + A list of all the terminal hotkeys and their uses
diff --git a/docs/user-guide/modules.md b/docs/user-guide/modules.md index 5f6b8537d..31e4b1c42 100644 --- a/docs/user-guide/modules.md +++ b/docs/user-guide/modules.md @@ -116,14 +116,14 @@ empty Filename string. * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [exec.include (`source`)](../commands/source.md): +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block -* [shell.packages (`murex-package`)](../commands/murex-package.md): +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [shell.private](../commands/private.md): +* [Private Function (`private`)](../commands/private.md): Define a private function block +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts
diff --git a/docs/user-guide/namedpipes.md b/docs/user-guide/namedpipes.md index 1e6131a29..9453517c4 100644 --- a/docs/user-guide/namedpipes.md +++ b/docs/user-guide/namedpipes.md @@ -49,12 +49,12 @@ command parameter1 parameter2 parameter3 ## See Also -* [`test`](../commands/test.md): - Murex's test framework - define tests, run tests and debug shell scripts -* [io.in (``)](../commands/stdin.md): - Read the stdin belonging to the parent code block -* [io.pipe (``)](../commands/namedpipe.md): +* [Read / Write To A Named Pipe (``)](../parser/namedpipe.md): Reads from a Murex named pipe +* [Read From Stdin (``)](../parser/stdin.md): + Read the stdin belonging to the parent code block +* [Shell Script Tests (`test`)](../commands/test.md): + Murex's test framework - define tests, run tests and debug shell scripts
diff --git a/docs/user-guide/pipeline.md b/docs/user-guide/pipeline.md index ca8efd162..983675518 100644 --- a/docs/user-guide/pipeline.md +++ b/docs/user-guide/pipeline.md @@ -69,6 +69,8 @@ document but you can read more on them in links the links below. ## See Also +* [Background Process (`bg`)](../commands/bg.md): + Run processes in the background * [Bang Prefix](../user-guide/bang-prefix.md): Bang prefixing to reverse default actions * [Schedulers](../user-guide/schedulers.md): @@ -81,8 +83,6 @@ document but you can read more on them in links the links below. Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command -* [proc.bg](../commands/bg.md): - Run processes in the background
diff --git a/docs/user-guide/profile.md b/docs/user-guide/profile.md index b662c82a6..0a02a6922 100644 --- a/docs/user-guide/profile.md +++ b/docs/user-guide/profile.md @@ -77,12 +77,12 @@ how you define that value. ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages -* [shell.packages (`murex-package`)](../commands/murex-package.md): +* [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value
diff --git a/docs/user-guide/reserved-vars.md b/docs/user-guide/reserved-vars.md index 7f54764b6..febc4ed4f 100644 --- a/docs/user-guide/reserved-vars.md +++ b/docs/user-guide/reserved-vars.md @@ -24,18 +24,18 @@ Error in `set` (0,1): cannot set a reserved variable: SELF ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value +* [Define Global (`global`)](../commands/global.md): + Define a global variable and set it's value +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value -* [var.global: `global`](../commands/global.md): - Define a global variable and set it's value -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/user-guide/rosetta-stone.md b/docs/user-guide/rosetta-stone.md index 79f64f5ed..e3ecec4b4 100644 --- a/docs/user-guide/rosetta-stone.md +++ b/docs/user-guide/rosetta-stone.md @@ -141,10 +141,22 @@ if you want to learn more about shell scripting in Murex. ## See Also +* [Filter By Range `[ ..Range ]`](../parser/range.md): + Outputs a ranged subset of data from stdin +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Get Nested Element (`[[ Element ]]`)](../parser/element.md): + Outputs an element from a nested structure * [Named Pipes](../user-guide/namedpipes.md): A detailed breakdown of named pipes in Murex +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses +* [Truncate File (`>`)](../parser/file-truncate.md): + Writes stdin to disk - overwriting contents if file already exists +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes * [`>>` Append File](../parser/file-append.md): @@ -153,22 +165,10 @@ if you want to learn more about shell scripting in Murex. Writes stdin to disk - appending contents if file already exists * [`@Array` Sigil](../parser/array.md): Expand values as an array -* [`[ ..Range ]`](../parser/range.md): - Outputs a ranged subset of data from stdin -* [`[[ Element ]]`](../parser/element.md): - Outputs an element from a nested structure -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level * [`string` (stringing)](../types/str.md): string (primitive) -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails -* [fs.truncate (`>`)](../commands/file-truncate.md): - Writes stdin to disk - overwriting contents if file already exists * [index](../parser/item-index.md): Outputs an element from an array, map or table diff --git a/docs/user-guide/schedulers.md b/docs/user-guide/schedulers.md index ebfca0b20..7826da78b 100644 --- a/docs/user-guide/schedulers.md +++ b/docs/user-guide/schedulers.md @@ -62,26 +62,26 @@ in the pipeline. ## See Also +* [Disable Error Handling In Block (`unsafe`)](../commands/unsafe.md): + Execute a block of code, always returning a zero exit number +* [Function / Module Defaults (`runmode`)](../commands/runmode.md): + Alter the scheduler's behaviour at higher scoping level +* [Pipe Fail (`trypipe`)](../commands/trypipe.md): + Checks for non-zero exits of each function in a pipeline * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Stderr Checking In Pipes (`trypipeerr`)](../commands/trypipeerr.md): + Checks state of each function in a pipeline and exits block on error +* [Stderr Checking In TTY (`tryerr`)](../commands/tryerr.md): + Handles errors inside a block of code +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code * [`->` Arrow Pipe](../parser/pipe-arrow.md): Pipes stdout from the left hand command to stdin of the right hand command * [`=>` Generic Pipe](../parser/pipe-generic.md): Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`runmode`](../commands/runmode.md): - Alter the scheduler's behaviour at higher scoping level -* [`try`](../commands/try.md): - Handles non-zero exits inside a block of code -* [`tryerr`](../commands/tryerr.md): - Handles errors inside a block of code -* [`trypipe`](../commands/trypipe.md): - Checks for non-zero exits of each function in a pipeline -* [`trypipeerr`](../commands/trypipeerr.md): - Checks state of each function in a pipeline and exits block on error -* [`unsafe`](../commands/unsafe.md): - Execute a block of code, always returning a zero exit number * [`|` POSIX Pipe](../parser/pipe-posix.md): Pipes stdout from the left hand command to stdin of the right hand command diff --git a/docs/user-guide/scoping.md b/docs/user-guide/scoping.md index 9760f237b..ea251bc22 100644 --- a/docs/user-guide/scoping.md +++ b/docs/user-guide/scoping.md @@ -51,32 +51,32 @@ scope. Subshells also do not create a new scope either. ## See Also +* [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): + Creates a handler function for `open` +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [For Each In List (`foreach`)](../commands/foreach.md): + Iterate through an array +* [If Conditional (`if`)](../commands/if.md): + Conditional statement to execute different blocks of code depending on the result of the condition +* [Include / Evaluate Murex Code (`source`)](../commands/source.md): + Import Murex code from another file or code block +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [Switch Conditional (`switch`)](../commands/switch.md): + Blocks of cascading conditionals +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`foreach`](../commands/foreach.md): - Iterate through an array -* [`if`](../commands/if.md): - Conditional statement to execute different blocks of code depending on the result of the condition * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) -* [`switch`](../commands/switch.md): - Blocks of cascading conditionals -* [exec.include (`source`)](../commands/source.md): - Import Murex code from another file or code block -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.config](../commands/config.md): - Query or define Murex runtime settings -* [shell.function](../commands/function.md): - Define a function block -* [shell.open: `openagent`](../commands/openagent.md): - Creates a handler function for `open` -* [shell.private](../commands/private.md): - Define a private function block -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index 50e42d994..debd5c27c 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -52,12 +52,12 @@ changing this option will not cause accidental side-effects in other functions. * [Language Tour](../Murex/tour.md): Getting started with Murex +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`expr`](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators -* [shell.config](../commands/config.md): - Query or define Murex runtime settings
diff --git a/docs/variables/argv.md b/docs/variables/argv.md index cdde9d49d..3dbf506f4 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -67,12 +67,22 @@ deprecated and may be removed from future releases. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`@Array` Sigil](../parser/array.md): @@ -83,16 +93,6 @@ deprecated and may be removed from future releases. JavaScript Object Notation (JSON) * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/columns.md b/docs/variables/columns.md index 644fe1f33..a168cc054 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -43,6 +43,8 @@ This is a reserved variable so it cannot be changed. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Reserved Variables](../user-guide/reserved-vars.md): @@ -51,8 +53,6 @@ This is a reserved variable so it cannot be changed. string (primitive) * [`string` (stringing)](../types/str.md): string (primitive) -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index cc28ad7a8..418ac4539 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -40,14 +40,14 @@ This is a reserved variable so it cannot be changed. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`str` (string)](../types/str.md): string (primitive) * [`string` (stringing)](../types/str.md): string (primitive) -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/meta-values.md b/docs/variables/meta-values.md index 363744d30..79040046b 100644 --- a/docs/variables/meta-values.md +++ b/docs/variables/meta-values.md @@ -53,14 +53,14 @@ iteration structure's documentation to check what information is exposed via ## See Also -* [`[{ Lambda }]`](../parser/lambda.md): - Iterate through structured data -* [`foreach`](../commands/foreach.md): +* [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array -* [`formap`](../commands/formap.md): +* [For Each In Map (`formap`)](../commands/formap.md): Iterate through a map or other collection of data -* [`while`](../commands/while.md): +* [Loop While (`while`)](../commands/while.md): Loop until condition false +* [`[{ Lambda }]`](../parser/lambda.md): + Iterate through structured data
diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index ab0007158..489d55fcb 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -41,14 +41,14 @@ This is a reserved variable so it cannot be changed. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`SHELL` (str)](../variables/shell.md): Path of current shell * [`path`](../types/path.md): Structured object for working with file and directory paths -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index 8eecb811e..b50fb848f 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -60,22 +60,22 @@ then variables `$1` through to `$19` (inclusive) will all be set. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/params.md b/docs/variables/params.md index 79182e848..4293fa134 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -55,12 +55,22 @@ This is a reserved variable so it cannot be changed. ## See Also +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Output String (`out`)](../commands/out.md): + Print a string to the stdout with a trailing new line character * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Private Function (`private`)](../commands/private.md): + Define a private function block +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex +* [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): + Set definitions for tab-completion in the command line * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`@Array` Sigil](../parser/array.md): @@ -71,16 +81,6 @@ This is a reserved variable so it cannot be changed. JavaScript Object Notation (JSON) * [`string` (stringing)](../types/str.md): string (primitive) -* [io.out](../commands/out.md): - Print a string to the stdout with a trailing new line character -* [shell.autocomplete](../commands/autocomplete.md): - Set definitions for tab-completion in the command line -* [shell.function](../commands/function.md): - Define a function block -* [shell.private](../commands/private.md): - Define a private function block -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/pwd.md b/docs/variables/pwd.md index e4273cf9c..81ad014b0 100644 --- a/docs/variables/pwd.md +++ b/docs/variables/pwd.md @@ -39,14 +39,14 @@ It is updated via `cd` however you can overwrite its value manually via `export` ## See Also +* [Change Directory (`cd`)](../commands/cd.md): + Change (working) directory +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value * [`PWDHIST` (json)](../variables/pwdhist.md): History of each change to the sessions working directory -* [`cd`](../commands/cd.md): - Change (working) directory * [`path`](../types/path.md): Structured object for working with file and directory paths -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value
diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index 87cc1908f..86bad8bb4 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -52,6 +52,10 @@ It is updated via `cd` however you can overwrite its value manually via `set`. ## See Also +* [Change Directory (`cd`)](../commands/cd.md): + Change (working) directory +* [Define Variable (`set`)](../commands/set.md): + Define a variable (typically local) and set it's value * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages * [Pipeline](../user-guide/pipeline.md): @@ -64,16 +68,12 @@ It is updated via `cd` however you can overwrite its value manually via `set`. Expand values as an array * [`PWD` (path)](../variables/pwd.md): Current working directory -* [`cd`](../commands/cd.md): - Change (working) directory * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`path`](../types/path.md): Structured object for working with file and directory paths * [`string` (stringing)](../types/str.md): string (primitive) -* [var.set: `set`](../commands/set.md): - Define a local variable and set it's value
diff --git a/docs/variables/self.md b/docs/variables/self.md index 5fb879e70..b8d37df37 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -117,6 +117,8 @@ terminal (TTY) or a pipe?) An introduction to Murex modules and packages * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is +* [Public Function (`function`)](../commands/function.md): + Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [Variable and Config Scoping](../user-guide/scoping.md): @@ -125,8 +127,6 @@ terminal (TTY) or a pipe?) JavaScript Object Notation (JSON) * [`string` (stringing)](../types/str.md): string (primitive) -* [shell.function](../commands/function.md): - Define a function block
diff --git a/docs/variables/shell.md b/docs/variables/shell.md index eac886a42..caa61b445 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -43,12 +43,12 @@ precision. ## See Also +* [Define Environmental Variable (`export`)](../commands/export.md): + Define an environmental variable and set it's value * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell * [`string` (stringing)](../types/str.md): string (primitive) -* [var.env: `export`](../commands/export.md): - Define an environmental variable and set it's value
diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index 20f720eb8..8928d3d84 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -10,10 +10,20 @@ category: {{ md (include .Description) }}{{ end }} ## Pages +{{ if .SubCategories }}{{ range $cat := .SubCategories }} -{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +### {{ .Title }} + +{{ .Description }} + +{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): - {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }}{{ end }} + +{{ if .UncatDocs }}### Uncategorised +{{ range $i,$a := .UncatDocs }} +* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ end }} ## Optional Builtins diff --git a/gen/docgen.yaml b/gen/docgen.yaml index fdb53eb28..234a3d4eb 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -13,10 +13,72 @@ Categories: DocumentTemplate: gen/root-md-doc.tmpl - ID: commands - Title: Builtins Reference + Title: Command Reference Description: |- - {{ include "gen/commands-md-cat.inc.md" }} - + {{ include "gen/commands-md-cat.inc.md" }} + + SubCategories: + - ID: commands.io + Title: Input / Output Streams + Description: |- + Commands for managing the flow of data between different processes and/or the terminal screen. + - ID: commands.fs + Title: Filesystem Operations + Description: |- + Commands for working with files and/or the filesystem. + - ID: commands.posix + Title: Defined by POSIX + Description: |- + Commands defined by POSIX. + - ID: commands.list + Title: List / Array Editing + Description: |- + Commands that operate against a list or array. + - ID: commands.str + Title: String Manipulation + Description: |- + Commands for working with strings. + > All list based tools also work with strings. + - ID: commands.num + Title: Numeric / Math Tools + Description: |- + Commands for working with numerical data. + - ID: commands.struct + Title: Structured Data Management + Description: |- + Commands for working with structured data such as maps, tables, arrays and other data formats that are present in documents such as CSV, JSON, YAML, TOML, Sexpr, CSV, etc. + - ID: commands.table + Title: Table Management + Description: |- + Commands specifically for working with tabulated data. + - ID: commands.sys + Title: System Inspection + Description: |- + Tools to inspect the host system. + - ID: commands.shell + Title: Shell / Murex Management + Description: |- + Commands to manage the Murex shell session. + - ID: commands.esc + Title: String Escaping / Character Codes + Description: |- + Commands to escape special characters in various different string formats. + - ID: commands.proc + Title: Process Management + Description: |- + Management of system processes and Murex FIDs. + - ID: commands.lang + Title: Language And Scripting + Description: |- + Various commands that enable control flow, error handling and other important characteristics that turn Murex into a functional programming language. + - ID: commands.err + Title: Error Handling + Description: |- + Tools and control flow structures to handle errors. + - ID: commands.help + Title: Help and Hint Tools + Description: |- + Tools for providing help and hints, useful when working inside the interactive shell. Templates: - OutputPath: docs/commands CategoryFile: README.md diff --git a/integrations/_namespaces_any.mx b/integrations/_namespaces_any.mx index f0fb1346f..0636569d2 100644 --- a/integrations/_namespaces_any.mx +++ b/integrations/_namespaces_any.mx @@ -11,91 +11,19 @@ alias !list.regex = !regexp alias list.str = match alias !list.str = !match alias list.join = mjoin -alias list.new.str = a -alias list.new.type = ta alias str.split = jsplit alias str.datetime = datetime alias num.round = round -alias struct.count = count -alias struct.alter = alter -alias struct.keys = struct-keys -alias struct.new.map = map -alias struct.new.2darray = 2darray -alias struct.json.pretty = pretty - alias table.select = select alias table.add.heading = addheading -alias var.set = set -alias !var.set = !set -alias var.global = global -alias !var.global = !global -alias var.env = export -alias !var.env = !export - -alias escape.quote = escape -alias !escape.quote = !escape -alias escape.html = eschtml -alias !escape.html = !eschtml -alias escape.url = escurl -alias !escape.url = !escurl -alias escape.cli = esccli - -alias io.in = read-namedpipe stdin -alias io.out = out -alias io.err = err -alias io.read = read -alias io.pipe = read-named-pipe -alias io.status = pt -alias io.new.pipe = pipe -alias !io.new.pipe = !pipe - -alias fs.glob = g -alias !fs.glob = !g -alias fs.regex = rx -alias !fs.regex = !rx -alias fs.files = f -alias fs.lockfile = lockfile -alias fs.tmpfile = tmp -alias fs.truncate = ">" -alias fs.append = ">>" -alias fs.open = open -alias fs.open.image= open-image - alias sys.os = os alias sys.cpu.arch = cpuarch alias sys.cpu.count = cpucount -alias shell.alias = alias -alias !shell.alias = !alias -alias shell.function = function -alias !shell.function = !function -alias shell.private = private -alias shell.method = method -alias shell.pipe = pipe -alias !shell.pipe = !pipe -alias shell.event = event -alias !shell.event = !event -alias shell.autocomplete= autocomplete -alias shell.packages = murex-package -alias shell.rescan.path = murex-update-exe-list -alias shell.runtime = runtime -alias shell.config = config -alias shell.builtins.exist = bexists -alias shell.history = history -alias shell.summary = summary -alias !shell.summary = !summary -alias shell.open = openagent - -alias help = murex-docs -alias help.man.summary = man-summary -alias help.man.flags = man-get-flags - -alias exec.file = exec -alias exec.include = source alias exec.builtin = fexec builtin alias exec.function = fexec function alias exec.private = fexec private diff --git a/utils/docgen/api/category.go b/utils/docgen/api/category.go index f2d005058..74f74b6bd 100644 --- a/utils/docgen/api/category.go +++ b/utils/docgen/api/category.go @@ -1,6 +1,7 @@ package docgen import ( + "fmt" "sort" "text/template" ) @@ -15,9 +16,39 @@ type category struct { // Description of the category Description string `yaml:"Description"` + SubCategories []*category `yaml:"SubCategories"` + Templates []templates `yaml:"Templates"` } +func (c *category) SubCategoryByID(id string) (*category, error) { + for i := range c.SubCategories { + if c.SubCategories[i].ID == id { + return c.SubCategories[i], nil + } + } + + return nil, fmt.Errorf("cannot find a sub-category with the id '%s'", id) +} + +func (c *category) getSubCategoryTitle(id string) string { + sub, err := c.SubCategoryByID(id) + if err != nil { + return "" + } + + return sub.Title +} + +func (c *category) getSubCategoryDescription(id string) string { + sub, err := c.SubCategoryByID(id) + if err != nil { + return "" + } + + return sub.Description +} + type templates struct { // OutputPath to write the rendered documents OutputPath string `yaml:"OutputPath"` @@ -64,18 +95,72 @@ func (t templates) CategoryValues(docs documents) *categoryValues { sort.Sort(dt) return &categoryValues{ - ID: t.ref.ID, - Title: t.ref.Title, - Description: t.ref.Description, - Documents: dv, - DateTime: dt, + ID: t.ref.ID, + Title: t.ref.Title, + Description: t.ref.Description, + Documents: dv, + DateTime: dt, + SubCategories: t.SubCategoryValues(docs, t.ref), + UncatDocs: t.UncategorisedValues(docs, t.ref), + } +} + +func (t templates) UncategorisedValues(docs documents, cat *category) []*documentValues { + var uncat []*documentValues + + for i := range docs { + if docs[i].CategoryID != cat.ID || len(docs[i].SubCategoryIDs) > 0 { + continue + } + uncat = append(uncat, t.DocumentValues(&docs[i], docs, true)) + } + + return uncat +} + +func (t templates) SubCategoryValues(docs documents, cat *category) []*categoryValues { + var subs []*categoryValues + + for i := range cat.SubCategories { + subs = append(subs, t.subCategoryValues(docs, cat.SubCategories[i])) + } + + return subs +} + +func (t templates) subCategoryValues(docs documents, cat *category) *categoryValues { + var ( + dv sortableDocumentValues + dt sortableDocumentDateTime + ) + + for i := range docs { + //if docs[i].SubCategoryID == cat.ID { + if docs[i].IsInSubCategory(cat.ID) { + dv = append(dv, t.DocumentValues(&docs[i], docs, true)) + dt = append(dt, t.DocumentValues(&docs[i], docs, true)) + } + } + + sort.Sort(dv) + sort.Sort(dt) + + return &categoryValues{ + ID: cat.ID, + Title: cat.Title, + Description: cat.Description, + Documents: dv, + DateTime: dt, + SubCategories: t.SubCategoryValues(docs, cat), } } type categoryValues struct { - ID string - Title string - Description string - Documents []*documentValues - DateTime []*documentValues + ID string + Title string + Description string + Documents []*documentValues + DateTime []*documentValues + SubCategories []*categoryValues + UncatDocs []*documentValues } diff --git a/utils/docgen/api/document.go b/utils/docgen/api/document.go index 5fd0d6d4d..b9157a42b 100644 --- a/utils/docgen/api/document.go +++ b/utils/docgen/api/document.go @@ -18,6 +18,9 @@ type document struct { // CategoryID as per the Categories map (see below) CategoryID string `yaml:"CategoryID"` + // SubCategory is an optional field for grouping documents in a particular category + SubCategoryIDs []string `yaml:"SubCategoryIDs"` + // Summary is a one line summary Summary string `yaml:"Summary"` @@ -126,6 +129,7 @@ func (t templates) DocumentValues(d *document, docs documents, nest bool) *docum CategoryID: d.CategoryID, CategoryTitle: t.ref.Title, CategoryDescription: t.ref.Description, + SubCategories: documentSubCategories(t.ref), Summary: d.Summary, Description: d.Description, Usage: d.Usage, @@ -190,6 +194,24 @@ func (t templates) DocumentValues(d *document, docs documents, nest bool) *docum return dv } +type documentValuesSubCats struct { + ID string + Title string + Description string +} + +func documentSubCategories(cat *category) []documentValuesSubCats { + var subs []documentValuesSubCats + for _, c := range cat.SubCategories { + subs = append(subs, documentValuesSubCats{ + ID: c.ID, + Title: c.Title, + Description: c.Description, + }) + } + return subs +} + type documentValues struct { ID string Title string @@ -201,6 +223,7 @@ type documentValues struct { CategoryID string CategoryTitle string CategoryDescription string + SubCategories []documentValuesSubCats Summary string Description string Payload string @@ -317,3 +340,13 @@ func (d documents) ByID(requesterID, categoryID, documentID string) *document { // Documents is all of the collated documents pre-rendering var Documents documents + +func (d *document) IsInSubCategory(id string) bool { + for i := range d.SubCategoryIDs { + if d.SubCategoryIDs[i] == id { + return true + } + } + + return false +} diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 87a4bf57b..c69026b2a 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -2,6 +2,7 @@ package docgen import ( "bytes" + "encoding/json" "errors" "fmt" "os" @@ -33,6 +34,7 @@ var funcMap = template.FuncMap{ "otherdocs": funcOtherDocs, "env": funcEnv, "fn": funcFunctions, + "dump": funcDump, } var funcMap__fn = template.FuncMap{} @@ -326,3 +328,13 @@ func funcFunctions(s string) string { } return w.String() } + +/************ + * Dump * + ************/ + +// Returns: A JSON dump of something (this is an internal tool for debugging) +func funcDump() string { + b, _ := json.MarshalIndent(Config.Categories, "", " ") + return string(b) +} diff --git a/utils/docgen/api/unmarshaller.go b/utils/docgen/api/unmarshaller.go index c308e3708..eb0e4475b 100644 --- a/utils/docgen/api/unmarshaller.go +++ b/utils/docgen/api/unmarshaller.go @@ -8,9 +8,9 @@ import ( func parseSourceFile(path string, structure interface{}) { f := fileReader(path) - b := readAll(f) - - err := yaml.Unmarshal(b, structure) + yml := yaml.NewDecoder(f) + yml.KnownFields(true) + err := yml.Decode(structure) if err != nil { panic(fmt.Sprintf("%s (%s)", err.Error(), path)) } diff --git a/utils/docgen/main.go b/utils/docgen/main.go index 50782c00e..db72e7321 100644 --- a/utils/docgen/main.go +++ b/utils/docgen/main.go @@ -11,7 +11,7 @@ import ( const ( // Version is the release ID of docgen - Version = "3.3.0" + Version = "4.0.0" // Copyright is the copyright owner string Copyright = "(c) 2018-2024 Laurence Morgan" From 20e415827cf02fc3130a860c1438859c206de6b2 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 22:25:06 +0100 Subject: [PATCH 068/142] docgen: support for vuepress json menus --- gen/commands-vue-cat.tmpl | 1 + gen/docgen.yaml | 6 +- gen/vuepress/commands_generated.json | 705 +++++++++++++++++++++++++++ gen/vuepress/sidebar.ts | 3 +- utils/docgen/api/functions.go | 91 +++- 5 files changed, 785 insertions(+), 21 deletions(-) create mode 100644 gen/commands-vue-cat.tmpl create mode 100644 gen/vuepress/commands_generated.json diff --git a/gen/commands-vue-cat.tmpl b/gen/commands-vue-cat.tmpl new file mode 100644 index 000000000..dfab16a8c --- /dev/null +++ b/gen/commands-vue-cat.tmpl @@ -0,0 +1 @@ +{{ vuepressmenu "commands" }} \ No newline at end of file diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 234a3d4eb..ad3385b4b 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -88,9 +88,11 @@ Categories: - OutputPath: builtins/docs CategoryFile: summaries.go - #OutputExt: _commands_docgen.go CategoryTemplate: gen/commands-go-cat.tmpl - #DocumentTemplate: gen/commands-go-doc.tmpl + + - OutputPath: gen/vuepress + CategoryFile: commands_generated.json + CategoryTemplate: gen/commands-vue-cat.tmpl - ID: mkarray Title: mkarray diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json new file mode 100644 index 000000000..c5d20f907 --- /dev/null +++ b/gen/vuepress/commands_generated.json @@ -0,0 +1,705 @@ +[ + { + "children": [ + { + "link": "commands/out.html", + "text": "Output String (`out`)" + }, + { + "link": "commands/tout.html", + "text": "Output With Type Annotation (`tout`)" + }, + { + "link": "parser/brace-quote-func.html", + "text": "`(brace quote)`" + }, + { + "link": "commands/err.html", + "text": "Error String (`err`)" + }, + { + "link": "commands/pt.html", + "text": "Get Pipe Status (`pt`)" + }, + { + "link": "commands/read.html", + "text": "Read User Input (`read`)" + }, + { + "link": "commands/tread.html", + "text": "Read With Type (`tread`) (removed 7.x)" + }, + { + "link": "commands/open-image.html", + "text": "Render Image In Terminal (`open-image`)" + }, + { + "link": "parser/namedpipe.html", + "text": "Read / Write To A Named Pipe (`\u003cpipe\u003e`)" + }, + { + "link": "parser/stdin.html", + "text": "Read From Stdin (`\u003cstdin\u003e`)" + }, + { + "link": "commands/pipe.html", + "text": "Create Named Pipe (`pipe`)" + } + ], + "text": "Input / Output Streams" + }, + { + "children": [ + { + "link": "commands/f.html", + "text": "List Filesystem Objects (`f`)" + }, + { + "link": "parser/file-truncate.html", + "text": "Truncate File (`\u003e`)" + }, + { + "link": "commands/g.html", + "text": "Globbing (`g`)" + }, + { + "link": "commands/lockfile.html", + "text": "Lock Files (`lockfile`)" + }, + { + "link": "commands/rx.html", + "text": "Regex Matches (`rx`)" + }, + { + "link": "commands/tmp.html", + "text": "Create Temporary File (`tmp`)" + }, + { + "link": "commands/open.html", + "text": "Open File (`open`)" + }, + { + "link": "commands/open-image.html", + "text": "Render Image In Terminal (`open-image`)" + } + ], + "text": "Filesystem Operations" + }, + { + "children": [ + { + "link": "commands/expr.html", + "text": "`expr`" + }, + { + "link": "commands/out.html", + "text": "Output String (`out`)" + }, + { + "link": "commands/read.html", + "text": "Read User Input (`read`)" + }, + { + "link": "commands/cd.html", + "text": "Change Directory (`cd`)" + }, + { + "link": "commands/type.html", + "text": "Display Command Type (`type`)" + }, + { + "link": "commands/which.html", + "text": "Location Of Command (`which`)" + }, + { + "link": "commands/alias.html", + "text": "Alias Pointer (`alias`)" + }, + { + "link": "commands/time.html", + "text": "Processes Execution Time (`time`)" + }, + { + "link": "commands/true.html", + "text": "True (`true`)" + }, + { + "link": "commands/false.html", + "text": "False (`false`)" + } + ], + "text": "Defined by POSIX" + }, + { + "children": [ + { + "link": "commands/count.html", + "text": "Count (`count`)" + }, + { + "link": "parser/item-index.html", + "text": "Get Item (`[ Index ]`)" + }, + { + "link": "commands/prepend.html", + "text": "Prepend To List (`prepend`)" + }, + { + "link": "commands/append.html", + "text": "Append To List (`append`)" + }, + { + "link": "commands/list.case.html", + "text": "Change Text Case (`list.case`)" + }, + { + "link": "commands/mjoin.html", + "text": "Join Array To String (`mjoin`)" + }, + { + "link": "commands/msort.html", + "text": "Sort Array (`msort`)" + }, + { + "link": "commands/mtac.html", + "text": "Reverse Array (`mtac`)" + }, + { + "link": "commands/left.html", + "text": "Left Sub-String (`left`)" + }, + { + "link": "commands/right.html", + "text": "Right Sub-String (`right`)" + }, + { + "link": "commands/prefix.html", + "text": "Add Prefix (`prefix`)" + }, + { + "link": "commands/suffix.html", + "text": "Add Suffix (`suffix`)" + }, + { + "link": "commands/match.html", + "text": "Match String (`match`)" + }, + { + "link": "commands/regexp.html", + "text": "Regex Operations (`regexp`)" + }, + { + "link": "commands/a.html", + "text": "Stream New List (`a`)" + }, + { + "link": "commands/ja.html", + "text": "Create JSON Array (`ja`)" + }, + { + "link": "commands/ta.html", + "text": "Create New Array (`ta`)" + }, + { + "link": "parser/range.html", + "text": "Filter By Range `[ ..Range ]`" + }, + { + "link": "commands/foreach.html", + "text": "For Each In List (`foreach`)" + }, + { + "link": "commands/format.html", + "text": "Reformat Data type (`format`)" + } + ], + "text": "List / Array Editing" + }, + { + "children": [ + { + "link": "commands/escape.html", + "text": "Quote String (`escape`)" + }, + { + "link": "commands/eschtml.html", + "text": "Escape HTML (`eschtml`)" + }, + { + "link": "commands/escurl.html", + "text": "Escape URL (`escurl`)" + }, + { + "link": "commands/esccli.html", + "text": "Escape Command Line String (`esccli`)" + }, + { + "link": "commands/list.case.html", + "text": "Change Text Case (`list.case`)" + }, + { + "link": "commands/jsplit.html", + "text": "Split String (`jsplit`)" + }, + { + "link": "commands/left.html", + "text": "Left Sub-String (`left`)" + }, + { + "link": "commands/right.html", + "text": "Right Sub-String (`right`)" + }, + { + "link": "commands/regexp.html", + "text": "Regex Operations (`regexp`)" + }, + { + "link": "commands/pretty.html", + "text": "Prettify JSON" + }, + { + "link": "commands/rand.html", + "text": "Generate Random Sequence (`rand`)" + }, + { + "link": "commands/datetime.html", + "text": "Date And Time Conversion (`datetime`)" + }, + { + "link": "commands/format.html", + "text": "Reformat Data type (`format`)" + } + ], + "text": "String Manipulation" + }, + { + "children": [ + { + "link": "commands/expr.html", + "text": "`expr`" + }, + { + "link": "commands/rand.html", + "text": "Generate Random Sequence (`rand`)" + }, + { + "link": "commands/round.html", + "text": "Round Number (`round`)" + } + ], + "text": "Numeric / Math Tools" + }, + { + "children": [ + { + "link": "commands/2darray.html", + "text": "Create 2d Array (`2darray`)" + }, + { + "link": "commands/map.html", + "text": "Create Map (`map`)" + }, + { + "link": "commands/alter.html", + "text": "Alter Data Structure (`alter`)" + }, + { + "link": "commands/count.html", + "text": "Count (`count`)" + }, + { + "link": "commands/struct-keys.html", + "text": "Print Map / Structure Keys (`struct-keys`)" + }, + { + "link": "parser/element.html", + "text": "Get Nested Element (`[[ Element ]]`)" + }, + { + "link": "parser/item-index.html", + "text": "Get Item (`[ Index ]`)" + }, + { + "link": "commands/formap.html", + "text": "For Each In Map (`formap`)" + }, + { + "link": "commands/tabulate.html", + "text": "Transformation Tools (`tabulate`)" + }, + { + "link": "commands/format.html", + "text": "Reformat Data type (`format`)" + } + ], + "text": "Structured Data Management" + }, + { + "children": [ + { + "link": "commands/addheading.html", + "text": "Add Heading (`addheading`)" + }, + { + "link": "commands/formap.html", + "text": "For Each In Map (`formap`)" + }, + { + "link": "commands/tabulate.html", + "text": "Transformation Tools (`tabulate`)" + }, + { + "link": "commands/format.html", + "text": "Reformat Data type (`format`)" + }, + { + "link": "optional/select.html", + "text": "Inline SQL (`select`)" + } + ], + "text": "Table Management" + }, + { + "children": [ + { + "link": "commands/os.html", + "text": "Operating System (`os`)" + }, + { + "link": "commands/cpuarch.html", + "text": "CPU Architecture (`cpuarch`)" + }, + { + "link": "commands/cpucount.html", + "text": "CPU Count (`cpucount`)" + }, + { + "link": "commands/export.html", + "text": "Define Environmental Variable (`export`)" + } + ], + "text": "System Inspection" + }, + { + "children": [ + { + "link": "commands/autocomplete.html", + "text": "Tab Autocompletion (`autocomplete`)" + }, + { + "link": "commands/config.html", + "text": "Shell Configuration And Settings (`config`)" + }, + { + "link": "commands/debug.html", + "text": "Debugging Mode (`debug`)" + }, + { + "link": "commands/fexec.html", + "text": "Execute Shell Function or Builtin (`fexec`)" + }, + { + "link": "commands/murex-update-exe-list.html", + "text": "Re-Scan $PATH For Executables" + }, + { + "link": "commands/history.html", + "text": "Command Line History (`history`)" + }, + { + "link": "commands/summary.html", + "text": "Set Command Summary Hint (`summary`)" + }, + { + "link": "commands/source.html", + "text": "Include / Evaluate Murex Code (`source`)" + }, + { + "link": "commands/version.html", + "text": "Murex Version (`version`)" + }, + { + "link": "commands/murex-package.html", + "text": "Murex Package Management (`murex-package`)" + }, + { + "link": "commands/openagent.html", + "text": "Define Handlers For \"`open`\" (`openagent`)" + }, + { + "link": "commands/pipe.html", + "text": "Create Named Pipe (`pipe`)" + }, + { + "link": "commands/runtime.html", + "text": "Shell Runtime (`runtime`)" + }, + { + "link": "commands/alias.html", + "text": "Alias Pointer (`alias`)" + }, + { + "link": "commands/function.html", + "text": "Public Function (`function`)" + }, + { + "link": "commands/private.html", + "text": "Private Function (`private`)" + }, + { + "link": "commands/method.html", + "text": "Define Method Relationships (`method`)" + }, + { + "link": "commands/test.html", + "text": "Shell Script Tests (`test`)" + }, + { + "link": "commands/event.html", + "text": "`event`" + } + ], + "text": "Shell / Murex Management" + }, + { + "children": [ + { + "link": "commands/escape.html", + "text": "Quote String (`escape`)" + }, + { + "link": "commands/eschtml.html", + "text": "Escape HTML (`eschtml`)" + }, + { + "link": "commands/escurl.html", + "text": "Escape URL (`escurl`)" + }, + { + "link": "commands/esccli.html", + "text": "Escape Command Line String (`esccli`)" + }, + { + "link": "commands/key-code.html", + "text": "`key-code`" + } + ], + "text": "String Escaping / Character Codes" + }, + { + "children": [ + { + "link": "commands/exitnum.html", + "text": "Get Exit Code (`exitnum`)" + }, + { + "link": "commands/bexists.html", + "text": "Check Builtin Exists (`bexists`)" + }, + { + "link": "commands/source.html", + "text": "Include / Evaluate Murex Code (`source`)" + }, + { + "link": "commands/which.html", + "text": "Location Of Command (`which`)" + }, + { + "link": "commands/bg.html", + "text": "Background Process (`bg`)" + }, + { + "link": "commands/fg.html", + "text": "Foreground Process (`fg`)" + }, + { + "link": "commands/fid-list.html", + "text": "Display Running Functions (`fid-list`)" + }, + { + "link": "commands/fid-kill.html", + "text": "Kill Function (`fid-kill`)" + }, + { + "link": "commands/fid-killall.html", + "text": "Kill All In Session (`fid-killall`)" + }, + { + "link": "commands/time.html", + "text": "Processes Execution Time (`time`)" + }, + { + "link": "commands/exec.html", + "text": "Execute External Command (`exec`)" + }, + { + "link": "commands/signal.html", + "text": "`signal`" + } + ], + "text": "Process Management" + }, + { + "children": [ + { + "link": "commands/expr.html", + "text": "`expr`" + }, + { + "link": "commands/args.html", + "text": "Define Function Arguments (`args`)" + }, + { + "link": "commands/and.html", + "text": "Logic And Statements (`and`)" + }, + { + "link": "commands/or.html", + "text": "Logic Or Statements (`or`)" + }, + { + "link": "commands/return.html", + "text": "Exit Function (`return`)" + }, + { + "link": "commands/break.html", + "text": "Exit Block (`break`)" + }, + { + "link": "commands/continue.html", + "text": "Next Iteration (`continue`)" + }, + { + "link": "commands/for.html", + "text": "For Loop (`for`)" + }, + { + "link": "commands/foreach.html", + "text": "For Each In List (`foreach`)" + }, + { + "link": "commands/formap.html", + "text": "For Each In Map (`formap`)" + }, + { + "link": "commands/function.html", + "text": "Public Function (`function`)" + }, + { + "link": "commands/private.html", + "text": "Private Function (`private`)" + }, + { + "link": "commands/if.html", + "text": "If Conditional (`if`)" + }, + { + "link": "commands/switch.html", + "text": "Switch Conditional (`switch`)" + }, + { + "link": "commands/while.html", + "text": "Loop While (`while`)" + }, + { + "link": "commands/get-type.html", + "text": "Get Data Type (`get-type`)" + }, + { + "link": "commands/is-null.html", + "text": "Is Value Null (`is-null`)" + }, + { + "link": "commands/exit.html", + "text": "Exit Murex (`exit`)" + }, + { + "link": "commands/devnull.html", + "text": "Null (`null`)" + }, + { + "link": "commands/not-func.html", + "text": "Not (`!`)" + }, + { + "link": "commands/cast.html", + "text": "Define Type (`cast`)" + }, + { + "link": "commands/set.html", + "text": "Define Variable (`set`)" + }, + { + "link": "commands/global.html", + "text": "Define Global (`global`)" + } + ], + "text": "Language And Scripting" + }, + { + "children": [ + { + "link": "commands/unsafe.html", + "text": "Disable Error Handling In Block (`unsafe`)" + }, + { + "link": "commands/try.html", + "text": "Try Block (`try`)" + }, + { + "link": "commands/trypipe.html", + "text": "Pipe Fail (`trypipe`)" + }, + { + "link": "commands/catch.html", + "text": "Caught Error Block (`catch`)" + }, + { + "link": "commands/runmode.html", + "text": "Function / Module Defaults (`runmode`)" + }, + { + "link": "commands/tryerr.html", + "text": "Stderr Checking In TTY (`tryerr`)" + }, + { + "link": "commands/trypipeerr.html", + "text": "Stderr Checking In Pipes (`trypipeerr`)" + } + ], + "text": "Error Handling" + }, + { + "children": [ + { + "link": "commands/man-summary.html", + "text": "Man-Page Summary (`man-summary`)" + }, + { + "link": "commands/summary.html", + "text": "Set Command Summary Hint (`summary`)" + }, + { + "link": "commands/man-get-flags.html", + "text": "Parse Man-Page For Flags (`man-get-flags`)" + }, + { + "link": "commands/murex-docs.html", + "text": "Murex's Offline Documentation (`murex-docs`)" + } + ], + "text": "Help and Hint Tools" + }, + { + "link": "commands/murex-parser.html", + "text": "`murex-parser`\n" + }, + { + "link": "commands/let.html", + "text": "`let`\n" + }, + { + "link": "commands/die.html", + "text": "`die`\n" + } +] \ No newline at end of file diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index 91f9b040d..202c66cc9 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -1,4 +1,5 @@ import { sidebar } from "vuepress-theme-hope"; +import commandsMenu from "./commands_generated.json" export default sidebar({ "/": [ @@ -42,7 +43,7 @@ export default sidebar({ text: "Builtins", icon: "cubes", prefix: "commands/", - children: "structure", + children: commandsMenu, collapsible: true, }, { diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index c69026b2a..e14823dd3 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -17,24 +17,25 @@ import ( ) var funcMap = template.FuncMap{ - "md": funcMarkdown, - "quote": funcQuote, - "trim": strings.TrimSpace, - "doc": funcRenderedDocuments, - "cat": funcRenderedCategories, - "link": funcLink, - "bookmark": funcLinkBookmark, - "section": funcSection, - "file": funcFile, - "notanindex": funcNotAnIndex, - "date": funcDate, - "time": funcTime, - "doct": funcDocT, - "othercats": funcOtherCats, - "otherdocs": funcOtherDocs, - "env": funcEnv, - "fn": funcFunctions, - "dump": funcDump, + "md": funcMarkdown, + "quote": funcQuote, + "trim": strings.TrimSpace, + "doc": funcRenderedDocuments, + "cat": funcRenderedCategories, + "link": funcLink, + "bookmark": funcLinkBookmark, + "section": funcSection, + "file": funcFile, + "notanindex": funcNotAnIndex, + "date": funcDate, + "time": funcTime, + "doct": funcDocT, + "othercats": funcOtherCats, + "otherdocs": funcOtherDocs, + "env": funcEnv, + "fn": funcFunctions, + "vuepressmenu": funcVuePressMenu, + "dump": funcDump, } var funcMap__fn = template.FuncMap{} @@ -329,6 +330,60 @@ func funcFunctions(s string) string { return w.String() } +/************ + * VuePress * + ************/ + +// Takes: string, category ID +// Returns: JSON string +func funcVuePressMenu(catID string) string { + //var menu vuePressMenuItem + cat := Config.Categories.ByID(catID) + if cat == nil { + panic(fmt.Sprintf("cannot find category with ID '%s'", catID)) + } + + menu := vuePressSubMenu(cat) + + for i := range Documents { + if Documents[i].CategoryID != cat.ID || len(Documents[i].SubCategoryIDs) > 0 { + continue + } + menu = append(menu, map[string]any{ + "text": Documents[i].Title, + "link": Documents[i].Hierarchy() + ".html", + }) + } + + b, err := json.MarshalIndent(menu, "", " ") + if err != nil { + panic(fmt.Sprintf("cannot marshal JSON: %s", err.Error())) + } + + return string(b) +} + +func vuePressSubMenu(cat *category) []map[string]any { + var menu []map[string]any + for _, sub := range cat.SubCategories { + var subMenu []map[string]any + for i := range Documents { + if Documents[i].IsInSubCategory(sub.ID) { + subMenu = append(subMenu, map[string]any{ + "text": strings.Trim(Documents[i].Title, "\n"), + "link": Documents[i].Hierarchy() + ".html", + }) + } + } + menu = append(menu, map[string]any{ + "text": sub.Title, + "children": subMenu, + }) + } + + return menu +} + /************ * Dump * ************/ From d63d8fa79551edd600fefc75c94eff7e638cb9b3 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 22:37:36 +0100 Subject: [PATCH 069/142] docgen: vue menu tweaks --- gen/vuepress/commands_generated.json | 639 ++++++++++++++------------- gen/vuepress/sidebar.ts | 2 +- utils/docgen/api/functions.go | 15 +- 3 files changed, 339 insertions(+), 317 deletions(-) diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index c5d20f907..40783bacc 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -2,704 +2,719 @@ { "children": [ { - "link": "commands/out.html", - "text": "Output String (`out`)" + "link": "out.html", + "text": "Output String (out)" }, { - "link": "commands/tout.html", - "text": "Output With Type Annotation (`tout`)" + "link": "tout.html", + "text": "Output With Type Annotation (tout)" }, { - "link": "parser/brace-quote-func.html", - "text": "`(brace quote)`" + "link": "brace-quote-func.html", + "text": "(brace quote)" }, { - "link": "commands/err.html", - "text": "Error String (`err`)" + "link": "err.html", + "text": "Error String (err)" }, { - "link": "commands/pt.html", - "text": "Get Pipe Status (`pt`)" + "link": "pt.html", + "text": "Get Pipe Status (pt)" }, { - "link": "commands/read.html", - "text": "Read User Input (`read`)" + "link": "read.html", + "text": "Read User Input (read)" }, { - "link": "commands/tread.html", - "text": "Read With Type (`tread`) (removed 7.x)" + "link": "tread.html", + "text": "Read With Type (tread) (removed 7.x)" }, { - "link": "commands/open-image.html", - "text": "Render Image In Terminal (`open-image`)" + "link": "open-image.html", + "text": "Render Image In Terminal (open-image)" }, { - "link": "parser/namedpipe.html", - "text": "Read / Write To A Named Pipe (`\u003cpipe\u003e`)" + "link": "namedpipe.html", + "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { - "link": "parser/stdin.html", - "text": "Read From Stdin (`\u003cstdin\u003e`)" + "link": "stdin.html", + "text": "Read From Stdin (\u003cstdin\u003e)" }, { - "link": "commands/pipe.html", - "text": "Create Named Pipe (`pipe`)" + "link": "pipe.html", + "text": "Create Named Pipe (pipe)" } ], + "collapsible": true, "text": "Input / Output Streams" }, { "children": [ { - "link": "commands/f.html", - "text": "List Filesystem Objects (`f`)" + "link": "f.html", + "text": "List Filesystem Objects (f)" }, { - "link": "parser/file-truncate.html", - "text": "Truncate File (`\u003e`)" + "link": "file-truncate.html", + "text": "Truncate File (\u003e)" }, { - "link": "commands/g.html", - "text": "Globbing (`g`)" + "link": "g.html", + "text": "Globbing (g)" }, { - "link": "commands/lockfile.html", - "text": "Lock Files (`lockfile`)" + "link": "lockfile.html", + "text": "Lock Files (lockfile)" }, { - "link": "commands/rx.html", - "text": "Regex Matches (`rx`)" + "link": "rx.html", + "text": "Regex Matches (rx)" }, { - "link": "commands/tmp.html", - "text": "Create Temporary File (`tmp`)" + "link": "tmp.html", + "text": "Create Temporary File (tmp)" }, { - "link": "commands/open.html", - "text": "Open File (`open`)" + "link": "open.html", + "text": "Open File (open)" }, { - "link": "commands/open-image.html", - "text": "Render Image In Terminal (`open-image`)" + "link": "open-image.html", + "text": "Render Image In Terminal (open-image)" } ], + "collapsible": true, "text": "Filesystem Operations" }, { "children": [ { - "link": "commands/expr.html", - "text": "`expr`" + "link": "expr.html", + "text": "expr" }, { - "link": "commands/out.html", - "text": "Output String (`out`)" + "link": "out.html", + "text": "Output String (out)" }, { - "link": "commands/read.html", - "text": "Read User Input (`read`)" + "link": "read.html", + "text": "Read User Input (read)" }, { - "link": "commands/cd.html", - "text": "Change Directory (`cd`)" + "link": "cd.html", + "text": "Change Directory (cd)" }, { - "link": "commands/type.html", - "text": "Display Command Type (`type`)" + "link": "type.html", + "text": "Display Command Type (type)" }, { - "link": "commands/which.html", - "text": "Location Of Command (`which`)" + "link": "which.html", + "text": "Location Of Command (which)" }, { - "link": "commands/alias.html", - "text": "Alias Pointer (`alias`)" + "link": "alias.html", + "text": "Alias Pointer (alias)" }, { - "link": "commands/time.html", - "text": "Processes Execution Time (`time`)" + "link": "time.html", + "text": "Processes Execution Time (time)" }, { - "link": "commands/true.html", - "text": "True (`true`)" + "link": "true.html", + "text": "True (true)" }, { - "link": "commands/false.html", - "text": "False (`false`)" + "link": "false.html", + "text": "False (false)" } ], + "collapsible": true, "text": "Defined by POSIX" }, { "children": [ { - "link": "commands/count.html", - "text": "Count (`count`)" + "link": "count.html", + "text": "Count (count)" }, { - "link": "parser/item-index.html", - "text": "Get Item (`[ Index ]`)" + "link": "item-index.html", + "text": "Get Item ([ Index ])" }, { - "link": "commands/prepend.html", - "text": "Prepend To List (`prepend`)" + "link": "prepend.html", + "text": "Prepend To List (prepend)" }, { - "link": "commands/append.html", - "text": "Append To List (`append`)" + "link": "append.html", + "text": "Append To List (append)" }, { - "link": "commands/list.case.html", - "text": "Change Text Case (`list.case`)" + "link": "list.case.html", + "text": "Change Text Case (list.case)" }, { - "link": "commands/mjoin.html", - "text": "Join Array To String (`mjoin`)" + "link": "mjoin.html", + "text": "Join Array To String (mjoin)" }, { - "link": "commands/msort.html", - "text": "Sort Array (`msort`)" + "link": "msort.html", + "text": "Sort Array (msort)" }, { - "link": "commands/mtac.html", - "text": "Reverse Array (`mtac`)" + "link": "mtac.html", + "text": "Reverse Array (mtac)" }, { - "link": "commands/left.html", - "text": "Left Sub-String (`left`)" + "link": "left.html", + "text": "Left Sub-String (left)" }, { - "link": "commands/right.html", - "text": "Right Sub-String (`right`)" + "link": "right.html", + "text": "Right Sub-String (right)" }, { - "link": "commands/prefix.html", - "text": "Add Prefix (`prefix`)" + "link": "prefix.html", + "text": "Add Prefix (prefix)" }, { - "link": "commands/suffix.html", - "text": "Add Suffix (`suffix`)" + "link": "suffix.html", + "text": "Add Suffix (suffix)" }, { - "link": "commands/match.html", - "text": "Match String (`match`)" + "link": "match.html", + "text": "Match String (match)" }, { - "link": "commands/regexp.html", - "text": "Regex Operations (`regexp`)" + "link": "regexp.html", + "text": "Regex Operations (regexp)" }, { - "link": "commands/a.html", - "text": "Stream New List (`a`)" + "link": "a.html", + "text": "Stream New List (a)" }, { - "link": "commands/ja.html", - "text": "Create JSON Array (`ja`)" + "link": "ja.html", + "text": "Create JSON Array (ja)" }, { - "link": "commands/ta.html", - "text": "Create New Array (`ta`)" + "link": "ta.html", + "text": "Create New Array (ta)" }, { - "link": "parser/range.html", - "text": "Filter By Range `[ ..Range ]`" + "link": "range.html", + "text": "Filter By Range [ ..Range ]" }, { - "link": "commands/foreach.html", - "text": "For Each In List (`foreach`)" + "link": "foreach.html", + "text": "For Each In List (foreach)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (`format`)" + "link": "format.html", + "text": "Reformat Data type (format)" } ], + "collapsible": true, "text": "List / Array Editing" }, { "children": [ { - "link": "commands/escape.html", - "text": "Quote String (`escape`)" + "link": "escape.html", + "text": "Quote String (escape)" }, { - "link": "commands/eschtml.html", - "text": "Escape HTML (`eschtml`)" + "link": "eschtml.html", + "text": "Escape HTML (eschtml)" }, { - "link": "commands/escurl.html", - "text": "Escape URL (`escurl`)" + "link": "escurl.html", + "text": "Escape URL (escurl)" }, { - "link": "commands/esccli.html", - "text": "Escape Command Line String (`esccli`)" + "link": "esccli.html", + "text": "Escape Command Line String (esccli)" }, { - "link": "commands/list.case.html", - "text": "Change Text Case (`list.case`)" + "link": "list.case.html", + "text": "Change Text Case (list.case)" }, { - "link": "commands/jsplit.html", - "text": "Split String (`jsplit`)" + "link": "jsplit.html", + "text": "Split String (jsplit)" }, { - "link": "commands/left.html", - "text": "Left Sub-String (`left`)" + "link": "left.html", + "text": "Left Sub-String (left)" }, { - "link": "commands/right.html", - "text": "Right Sub-String (`right`)" + "link": "right.html", + "text": "Right Sub-String (right)" }, { - "link": "commands/regexp.html", - "text": "Regex Operations (`regexp`)" + "link": "regexp.html", + "text": "Regex Operations (regexp)" }, { - "link": "commands/pretty.html", + "link": "pretty.html", "text": "Prettify JSON" }, { - "link": "commands/rand.html", - "text": "Generate Random Sequence (`rand`)" + "link": "rand.html", + "text": "Generate Random Sequence (rand)" }, { - "link": "commands/datetime.html", - "text": "Date And Time Conversion (`datetime`)" + "link": "datetime.html", + "text": "Date And Time Conversion (datetime)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (`format`)" + "link": "format.html", + "text": "Reformat Data type (format)" } ], + "collapsible": true, "text": "String Manipulation" }, { "children": [ { - "link": "commands/expr.html", - "text": "`expr`" + "link": "expr.html", + "text": "expr" }, { - "link": "commands/rand.html", - "text": "Generate Random Sequence (`rand`)" + "link": "rand.html", + "text": "Generate Random Sequence (rand)" }, { - "link": "commands/round.html", - "text": "Round Number (`round`)" + "link": "round.html", + "text": "Round Number (round)" } ], + "collapsible": true, "text": "Numeric / Math Tools" }, { "children": [ { - "link": "commands/2darray.html", - "text": "Create 2d Array (`2darray`)" + "link": "2darray.html", + "text": "Create 2d Array (2darray)" }, { - "link": "commands/map.html", - "text": "Create Map (`map`)" + "link": "map.html", + "text": "Create Map (map)" }, { - "link": "commands/alter.html", - "text": "Alter Data Structure (`alter`)" + "link": "alter.html", + "text": "Alter Data Structure (alter)" }, { - "link": "commands/count.html", - "text": "Count (`count`)" + "link": "count.html", + "text": "Count (count)" }, { - "link": "commands/struct-keys.html", - "text": "Print Map / Structure Keys (`struct-keys`)" + "link": "struct-keys.html", + "text": "Print Map / Structure Keys (struct-keys)" }, { - "link": "parser/element.html", - "text": "Get Nested Element (`[[ Element ]]`)" + "link": "element.html", + "text": "Get Nested Element ([[ Element ]])" }, { - "link": "parser/item-index.html", - "text": "Get Item (`[ Index ]`)" + "link": "item-index.html", + "text": "Get Item ([ Index ])" }, { - "link": "commands/formap.html", - "text": "For Each In Map (`formap`)" + "link": "formap.html", + "text": "For Each In Map (formap)" }, { - "link": "commands/tabulate.html", - "text": "Transformation Tools (`tabulate`)" + "link": "tabulate.html", + "text": "Transformation Tools (tabulate)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (`format`)" + "link": "format.html", + "text": "Reformat Data type (format)" } ], + "collapsible": true, "text": "Structured Data Management" }, { "children": [ { - "link": "commands/addheading.html", - "text": "Add Heading (`addheading`)" + "link": "addheading.html", + "text": "Add Heading (addheading)" }, { - "link": "commands/formap.html", - "text": "For Each In Map (`formap`)" + "link": "formap.html", + "text": "For Each In Map (formap)" }, { - "link": "commands/tabulate.html", - "text": "Transformation Tools (`tabulate`)" + "link": "tabulate.html", + "text": "Transformation Tools (tabulate)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (`format`)" + "link": "format.html", + "text": "Reformat Data type (format)" }, { - "link": "optional/select.html", - "text": "Inline SQL (`select`)" + "link": "select.html", + "text": "Inline SQL (select)" } ], + "collapsible": true, "text": "Table Management" }, { "children": [ { - "link": "commands/os.html", - "text": "Operating System (`os`)" + "link": "os.html", + "text": "Operating System (os)" }, { - "link": "commands/cpuarch.html", - "text": "CPU Architecture (`cpuarch`)" + "link": "cpuarch.html", + "text": "CPU Architecture (cpuarch)" }, { - "link": "commands/cpucount.html", - "text": "CPU Count (`cpucount`)" + "link": "cpucount.html", + "text": "CPU Count (cpucount)" }, { - "link": "commands/export.html", - "text": "Define Environmental Variable (`export`)" + "link": "export.html", + "text": "Define Environmental Variable (export)" } ], + "collapsible": true, "text": "System Inspection" }, { "children": [ { - "link": "commands/autocomplete.html", - "text": "Tab Autocompletion (`autocomplete`)" + "link": "autocomplete.html", + "text": "Tab Autocompletion (autocomplete)" }, { - "link": "commands/config.html", - "text": "Shell Configuration And Settings (`config`)" + "link": "config.html", + "text": "Shell Configuration And Settings (config)" }, { - "link": "commands/debug.html", - "text": "Debugging Mode (`debug`)" + "link": "debug.html", + "text": "Debugging Mode (debug)" }, { - "link": "commands/fexec.html", - "text": "Execute Shell Function or Builtin (`fexec`)" + "link": "fexec.html", + "text": "Execute Shell Function or Builtin (fexec)" }, { - "link": "commands/murex-update-exe-list.html", + "link": "murex-update-exe-list.html", "text": "Re-Scan $PATH For Executables" }, { - "link": "commands/history.html", - "text": "Command Line History (`history`)" + "link": "history.html", + "text": "Command Line History (history)" }, { - "link": "commands/summary.html", - "text": "Set Command Summary Hint (`summary`)" + "link": "summary.html", + "text": "Set Command Summary Hint (summary)" }, { - "link": "commands/source.html", - "text": "Include / Evaluate Murex Code (`source`)" + "link": "source.html", + "text": "Include / Evaluate Murex Code (source)" }, { - "link": "commands/version.html", - "text": "Murex Version (`version`)" + "link": "version.html", + "text": "Murex Version (version)" }, { - "link": "commands/murex-package.html", - "text": "Murex Package Management (`murex-package`)" + "link": "murex-package.html", + "text": "Murex Package Management (murex-package)" }, { - "link": "commands/openagent.html", - "text": "Define Handlers For \"`open`\" (`openagent`)" + "link": "openagent.html", + "text": "Define Handlers For \"open\" (openagent)" }, { - "link": "commands/pipe.html", - "text": "Create Named Pipe (`pipe`)" + "link": "pipe.html", + "text": "Create Named Pipe (pipe)" }, { - "link": "commands/runtime.html", - "text": "Shell Runtime (`runtime`)" + "link": "runtime.html", + "text": "Shell Runtime (runtime)" }, { - "link": "commands/alias.html", - "text": "Alias Pointer (`alias`)" + "link": "alias.html", + "text": "Alias Pointer (alias)" }, { - "link": "commands/function.html", - "text": "Public Function (`function`)" + "link": "function.html", + "text": "Public Function (function)" }, { - "link": "commands/private.html", - "text": "Private Function (`private`)" + "link": "private.html", + "text": "Private Function (private)" }, { - "link": "commands/method.html", - "text": "Define Method Relationships (`method`)" + "link": "method.html", + "text": "Define Method Relationships (method)" }, { - "link": "commands/test.html", - "text": "Shell Script Tests (`test`)" + "link": "test.html", + "text": "Shell Script Tests (test)" }, { - "link": "commands/event.html", - "text": "`event`" + "link": "event.html", + "text": "event" } ], + "collapsible": true, "text": "Shell / Murex Management" }, { "children": [ { - "link": "commands/escape.html", - "text": "Quote String (`escape`)" + "link": "escape.html", + "text": "Quote String (escape)" }, { - "link": "commands/eschtml.html", - "text": "Escape HTML (`eschtml`)" + "link": "eschtml.html", + "text": "Escape HTML (eschtml)" }, { - "link": "commands/escurl.html", - "text": "Escape URL (`escurl`)" + "link": "escurl.html", + "text": "Escape URL (escurl)" }, { - "link": "commands/esccli.html", - "text": "Escape Command Line String (`esccli`)" + "link": "esccli.html", + "text": "Escape Command Line String (esccli)" }, { - "link": "commands/key-code.html", - "text": "`key-code`" + "link": "key-code.html", + "text": "key-code" } ], + "collapsible": true, "text": "String Escaping / Character Codes" }, { "children": [ { - "link": "commands/exitnum.html", - "text": "Get Exit Code (`exitnum`)" + "link": "exitnum.html", + "text": "Get Exit Code (exitnum)" }, { - "link": "commands/bexists.html", - "text": "Check Builtin Exists (`bexists`)" + "link": "bexists.html", + "text": "Check Builtin Exists (bexists)" }, { - "link": "commands/source.html", - "text": "Include / Evaluate Murex Code (`source`)" + "link": "source.html", + "text": "Include / Evaluate Murex Code (source)" }, { - "link": "commands/which.html", - "text": "Location Of Command (`which`)" + "link": "which.html", + "text": "Location Of Command (which)" }, { - "link": "commands/bg.html", - "text": "Background Process (`bg`)" + "link": "bg.html", + "text": "Background Process (bg)" }, { - "link": "commands/fg.html", - "text": "Foreground Process (`fg`)" + "link": "fg.html", + "text": "Foreground Process (fg)" }, { - "link": "commands/fid-list.html", - "text": "Display Running Functions (`fid-list`)" + "link": "fid-list.html", + "text": "Display Running Functions (fid-list)" }, { - "link": "commands/fid-kill.html", - "text": "Kill Function (`fid-kill`)" + "link": "fid-kill.html", + "text": "Kill Function (fid-kill)" }, { - "link": "commands/fid-killall.html", - "text": "Kill All In Session (`fid-killall`)" + "link": "fid-killall.html", + "text": "Kill All In Session (fid-killall)" }, { - "link": "commands/time.html", - "text": "Processes Execution Time (`time`)" + "link": "time.html", + "text": "Processes Execution Time (time)" }, { - "link": "commands/exec.html", - "text": "Execute External Command (`exec`)" + "link": "exec.html", + "text": "Execute External Command (exec)" }, { - "link": "commands/signal.html", - "text": "`signal`" + "link": "signal.html", + "text": "signal" } ], + "collapsible": true, "text": "Process Management" }, { "children": [ { - "link": "commands/expr.html", - "text": "`expr`" + "link": "expr.html", + "text": "expr" }, { - "link": "commands/args.html", - "text": "Define Function Arguments (`args`)" + "link": "args.html", + "text": "Define Function Arguments (args)" }, { - "link": "commands/and.html", - "text": "Logic And Statements (`and`)" + "link": "and.html", + "text": "Logic And Statements (and)" }, { - "link": "commands/or.html", - "text": "Logic Or Statements (`or`)" + "link": "or.html", + "text": "Logic Or Statements (or)" }, { - "link": "commands/return.html", - "text": "Exit Function (`return`)" + "link": "return.html", + "text": "Exit Function (return)" }, { - "link": "commands/break.html", - "text": "Exit Block (`break`)" + "link": "break.html", + "text": "Exit Block (break)" }, { - "link": "commands/continue.html", - "text": "Next Iteration (`continue`)" + "link": "continue.html", + "text": "Next Iteration (continue)" }, { - "link": "commands/for.html", - "text": "For Loop (`for`)" + "link": "for.html", + "text": "For Loop (for)" }, { - "link": "commands/foreach.html", - "text": "For Each In List (`foreach`)" + "link": "foreach.html", + "text": "For Each In List (foreach)" }, { - "link": "commands/formap.html", - "text": "For Each In Map (`formap`)" + "link": "formap.html", + "text": "For Each In Map (formap)" }, { - "link": "commands/function.html", - "text": "Public Function (`function`)" + "link": "function.html", + "text": "Public Function (function)" }, { - "link": "commands/private.html", - "text": "Private Function (`private`)" + "link": "private.html", + "text": "Private Function (private)" }, { - "link": "commands/if.html", - "text": "If Conditional (`if`)" + "link": "if.html", + "text": "If Conditional (if)" }, { - "link": "commands/switch.html", - "text": "Switch Conditional (`switch`)" + "link": "switch.html", + "text": "Switch Conditional (switch)" }, { - "link": "commands/while.html", - "text": "Loop While (`while`)" + "link": "while.html", + "text": "Loop While (while)" }, { - "link": "commands/get-type.html", - "text": "Get Data Type (`get-type`)" + "link": "get-type.html", + "text": "Get Data Type (get-type)" }, { - "link": "commands/is-null.html", - "text": "Is Value Null (`is-null`)" + "link": "is-null.html", + "text": "Is Value Null (is-null)" }, { - "link": "commands/exit.html", - "text": "Exit Murex (`exit`)" + "link": "exit.html", + "text": "Exit Murex (exit)" }, { - "link": "commands/devnull.html", - "text": "Null (`null`)" + "link": "devnull.html", + "text": "Null (null)" }, { - "link": "commands/not-func.html", - "text": "Not (`!`)" + "link": "not-func.html", + "text": "Not (!)" }, { - "link": "commands/cast.html", - "text": "Define Type (`cast`)" + "link": "cast.html", + "text": "Define Type (cast)" }, { - "link": "commands/set.html", - "text": "Define Variable (`set`)" + "link": "set.html", + "text": "Define Variable (set)" }, { - "link": "commands/global.html", - "text": "Define Global (`global`)" + "link": "global.html", + "text": "Define Global (global)" } ], + "collapsible": true, "text": "Language And Scripting" }, { "children": [ { - "link": "commands/unsafe.html", - "text": "Disable Error Handling In Block (`unsafe`)" + "link": "unsafe.html", + "text": "Disable Error Handling In Block (unsafe)" }, { - "link": "commands/try.html", - "text": "Try Block (`try`)" + "link": "try.html", + "text": "Try Block (try)" }, { - "link": "commands/trypipe.html", - "text": "Pipe Fail (`trypipe`)" + "link": "trypipe.html", + "text": "Pipe Fail (trypipe)" }, { - "link": "commands/catch.html", - "text": "Caught Error Block (`catch`)" + "link": "catch.html", + "text": "Caught Error Block (catch)" }, { - "link": "commands/runmode.html", - "text": "Function / Module Defaults (`runmode`)" + "link": "runmode.html", + "text": "Function / Module Defaults (runmode)" }, { - "link": "commands/tryerr.html", - "text": "Stderr Checking In TTY (`tryerr`)" + "link": "tryerr.html", + "text": "Stderr Checking In TTY (tryerr)" }, { - "link": "commands/trypipeerr.html", - "text": "Stderr Checking In Pipes (`trypipeerr`)" + "link": "trypipeerr.html", + "text": "Stderr Checking In Pipes (trypipeerr)" } ], + "collapsible": true, "text": "Error Handling" }, { "children": [ { - "link": "commands/man-summary.html", - "text": "Man-Page Summary (`man-summary`)" + "link": "man-summary.html", + "text": "Man-Page Summary (man-summary)" }, { - "link": "commands/summary.html", - "text": "Set Command Summary Hint (`summary`)" + "link": "summary.html", + "text": "Set Command Summary Hint (summary)" }, { - "link": "commands/man-get-flags.html", - "text": "Parse Man-Page For Flags (`man-get-flags`)" + "link": "man-get-flags.html", + "text": "Parse Man-Page For Flags (man-get-flags)" }, { - "link": "commands/murex-docs.html", - "text": "Murex's Offline Documentation (`murex-docs`)" + "link": "murex-docs.html", + "text": "Murex's Offline Documentation (murex-docs)" } ], + "collapsible": true, "text": "Help and Hint Tools" }, { - "link": "commands/murex-parser.html", - "text": "`murex-parser`\n" + "link": "murex-parser.html", + "text": "murex-parser" }, { - "link": "commands/let.html", - "text": "`let`\n" + "link": "let.html", + "text": "let" }, { - "link": "commands/die.html", - "text": "`die`\n" + "link": "die.html", + "text": "die" } ] \ No newline at end of file diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index 202c66cc9..bfb8c55c6 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -42,7 +42,7 @@ export default sidebar({ { text: "Builtins", icon: "cubes", - prefix: "commands/", + prefix: "/", children: commandsMenu, collapsible: true, }, diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index e14823dd3..1af053a86 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -350,7 +350,7 @@ func funcVuePressMenu(catID string) string { continue } menu = append(menu, map[string]any{ - "text": Documents[i].Title, + "text": vueTitle(Documents[i].Title), "link": Documents[i].Hierarchy() + ".html", }) } @@ -370,20 +370,27 @@ func vuePressSubMenu(cat *category) []map[string]any { for i := range Documents { if Documents[i].IsInSubCategory(sub.ID) { subMenu = append(subMenu, map[string]any{ - "text": strings.Trim(Documents[i].Title, "\n"), + "text": vueTitle(Documents[i].Title), "link": Documents[i].Hierarchy() + ".html", }) } } menu = append(menu, map[string]any{ - "text": sub.Title, - "children": subMenu, + "text": vueTitle(sub.Title), + "children": subMenu, + "collapsible": true, }) } return menu } +var rxVueTitle = regexp.MustCompile("[\\r\\n`]") + +func vueTitle(s string) string { + return rxVueTitle.ReplaceAllString(s, "") +} + /************ * Dump * ************/ From 2efb24cde758ba88f57e672929f82361140a481b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 23:21:25 +0100 Subject: [PATCH 070/142] docgen: vue icons --- gen/docgen.yaml | 15 ++ gen/vuepress/commands_generated.json | 329 ++++++++++++++------------- utils/docgen/api/category.go | 2 + utils/docgen/api/functions.go | 1 + 4 files changed, 190 insertions(+), 157 deletions(-) diff --git a/gen/docgen.yaml b/gen/docgen.yaml index ad3385b4b..3ed8b0d9f 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -20,63 +20,78 @@ Categories: SubCategories: - ID: commands.io Title: Input / Output Streams + VueIcon: arrows-turn-to-dots Description: |- Commands for managing the flow of data between different processes and/or the terminal screen. - ID: commands.fs Title: Filesystem Operations + VueIcon: floppy-disk Description: |- Commands for working with files and/or the filesystem. - ID: commands.posix Title: Defined by POSIX + VueIcon: freebsd Description: |- Commands defined by POSIX. - ID: commands.list Title: List / Array Editing + VueIcon: rectangle-list Description: |- Commands that operate against a list or array. - ID: commands.str Title: String Manipulation + VueIcon: quote-left Description: |- Commands for working with strings. > All list based tools also work with strings. - ID: commands.num Title: Numeric / Math Tools + VueIcon: square-root-variable Description: |- Commands for working with numerical data. - ID: commands.struct Title: Structured Data Management + VueIcon: Description: |- Commands for working with structured data such as maps, tables, arrays and other data formats that are present in documents such as CSV, JSON, YAML, TOML, Sexpr, CSV, etc. - ID: commands.table Title: Table Management + VueIcon: table Description: |- Commands specifically for working with tabulated data. - ID: commands.sys Title: System Inspection + VueIcon: microchip Description: |- Tools to inspect the host system. - ID: commands.shell Title: Shell / Murex Management + VueIcon: gear Description: |- Commands to manage the Murex shell session. - ID: commands.esc Title: String Escaping / Character Codes + VueIcon: file-code Description: |- Commands to escape special characters in various different string formats. - ID: commands.proc Title: Process Management + VueIcon: robot Description: |- Management of system processes and Murex FIDs. - ID: commands.lang Title: Language And Scripting + VueIcon: language Description: |- Various commands that enable control flow, error handling and other important characteristics that turn Murex into a functional programming language. - ID: commands.err Title: Error Handling + VueIcon: bomb Description: |- Tools and control flow structures to handle errors. - ID: commands.help Title: Help and Hint Tools + VueIcon: lightbulb Description: |- Tools for providing help and hints, useful when working inside the interactive shell. Templates: diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 40783bacc..7e1cb170b 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -2,719 +2,734 @@ { "children": [ { - "link": "out.html", + "link": "commands/out.html", "text": "Output String (out)" }, { - "link": "tout.html", + "link": "commands/tout.html", "text": "Output With Type Annotation (tout)" }, { - "link": "brace-quote-func.html", + "link": "parser/brace-quote-func.html", "text": "(brace quote)" }, { - "link": "err.html", + "link": "commands/err.html", "text": "Error String (err)" }, { - "link": "pt.html", + "link": "commands/pt.html", "text": "Get Pipe Status (pt)" }, { - "link": "read.html", + "link": "commands/read.html", "text": "Read User Input (read)" }, { - "link": "tread.html", + "link": "commands/tread.html", "text": "Read With Type (tread) (removed 7.x)" }, { - "link": "open-image.html", + "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" }, { - "link": "namedpipe.html", + "link": "parser/namedpipe.html", "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { - "link": "stdin.html", + "link": "parser/stdin.html", "text": "Read From Stdin (\u003cstdin\u003e)" }, { - "link": "pipe.html", + "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" } ], "collapsible": true, + "icon": "arrows-turn-to-dots", "text": "Input / Output Streams" }, { "children": [ { - "link": "f.html", + "link": "commands/f.html", "text": "List Filesystem Objects (f)" }, { - "link": "file-truncate.html", + "link": "parser/file-truncate.html", "text": "Truncate File (\u003e)" }, { - "link": "g.html", + "link": "commands/g.html", "text": "Globbing (g)" }, { - "link": "lockfile.html", + "link": "commands/lockfile.html", "text": "Lock Files (lockfile)" }, { - "link": "rx.html", + "link": "commands/rx.html", "text": "Regex Matches (rx)" }, { - "link": "tmp.html", + "link": "commands/tmp.html", "text": "Create Temporary File (tmp)" }, { - "link": "open.html", + "link": "commands/open.html", "text": "Open File (open)" }, { - "link": "open-image.html", + "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" } ], "collapsible": true, + "icon": "floppy-disk", "text": "Filesystem Operations" }, { "children": [ { - "link": "expr.html", + "link": "commands/expr.html", "text": "expr" }, { - "link": "out.html", + "link": "commands/out.html", "text": "Output String (out)" }, { - "link": "read.html", + "link": "commands/read.html", "text": "Read User Input (read)" }, { - "link": "cd.html", + "link": "commands/cd.html", "text": "Change Directory (cd)" }, { - "link": "type.html", + "link": "commands/type.html", "text": "Display Command Type (type)" }, { - "link": "which.html", + "link": "commands/which.html", "text": "Location Of Command (which)" }, { - "link": "alias.html", + "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { - "link": "time.html", + "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { - "link": "true.html", + "link": "commands/true.html", "text": "True (true)" }, { - "link": "false.html", + "link": "commands/false.html", "text": "False (false)" } ], "collapsible": true, + "icon": "freebsd", "text": "Defined by POSIX" }, { "children": [ { - "link": "count.html", + "link": "commands/count.html", "text": "Count (count)" }, { - "link": "item-index.html", + "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "link": "prepend.html", + "link": "commands/prepend.html", "text": "Prepend To List (prepend)" }, { - "link": "append.html", + "link": "commands/append.html", "text": "Append To List (append)" }, { - "link": "list.case.html", + "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { - "link": "mjoin.html", + "link": "commands/mjoin.html", "text": "Join Array To String (mjoin)" }, { - "link": "msort.html", + "link": "commands/msort.html", "text": "Sort Array (msort)" }, { - "link": "mtac.html", + "link": "commands/mtac.html", "text": "Reverse Array (mtac)" }, { - "link": "left.html", + "link": "commands/left.html", "text": "Left Sub-String (left)" }, { - "link": "right.html", + "link": "commands/right.html", "text": "Right Sub-String (right)" }, { - "link": "prefix.html", + "link": "commands/prefix.html", "text": "Add Prefix (prefix)" }, { - "link": "suffix.html", + "link": "commands/suffix.html", "text": "Add Suffix (suffix)" }, { - "link": "match.html", + "link": "commands/match.html", "text": "Match String (match)" }, { - "link": "regexp.html", + "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { - "link": "a.html", + "link": "commands/a.html", "text": "Stream New List (a)" }, { - "link": "ja.html", + "link": "commands/ja.html", "text": "Create JSON Array (ja)" }, { - "link": "ta.html", + "link": "commands/ta.html", "text": "Create New Array (ta)" }, { - "link": "range.html", + "link": "parser/range.html", "text": "Filter By Range [ ..Range ]" }, { - "link": "foreach.html", + "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { - "link": "format.html", + "link": "commands/format.html", "text": "Reformat Data type (format)" } ], "collapsible": true, + "icon": "rectangle-list", "text": "List / Array Editing" }, { "children": [ { - "link": "escape.html", + "link": "commands/escape.html", "text": "Quote String (escape)" }, { - "link": "eschtml.html", + "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { - "link": "escurl.html", + "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { - "link": "esccli.html", + "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { - "link": "list.case.html", + "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { - "link": "jsplit.html", + "link": "commands/jsplit.html", "text": "Split String (jsplit)" }, { - "link": "left.html", + "link": "commands/left.html", "text": "Left Sub-String (left)" }, { - "link": "right.html", + "link": "commands/right.html", "text": "Right Sub-String (right)" }, { - "link": "regexp.html", + "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { - "link": "pretty.html", + "link": "commands/pretty.html", "text": "Prettify JSON" }, { - "link": "rand.html", + "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { - "link": "datetime.html", + "link": "commands/datetime.html", "text": "Date And Time Conversion (datetime)" }, { - "link": "format.html", + "link": "commands/format.html", "text": "Reformat Data type (format)" } ], "collapsible": true, + "icon": "quote-left", "text": "String Manipulation" }, { "children": [ { - "link": "expr.html", + "link": "commands/expr.html", "text": "expr" }, { - "link": "rand.html", + "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { - "link": "round.html", + "link": "commands/round.html", "text": "Round Number (round)" } ], "collapsible": true, + "icon": "square-root-variable", "text": "Numeric / Math Tools" }, { "children": [ { - "link": "2darray.html", + "link": "commands/2darray.html", "text": "Create 2d Array (2darray)" }, { - "link": "map.html", + "link": "commands/map.html", "text": "Create Map (map)" }, { - "link": "alter.html", + "link": "commands/alter.html", "text": "Alter Data Structure (alter)" }, { - "link": "count.html", + "link": "commands/count.html", "text": "Count (count)" }, { - "link": "struct-keys.html", + "link": "commands/struct-keys.html", "text": "Print Map / Structure Keys (struct-keys)" }, { - "link": "element.html", + "link": "parser/element.html", "text": "Get Nested Element ([[ Element ]])" }, { - "link": "item-index.html", + "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "link": "formap.html", + "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "link": "tabulate.html", + "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" }, { - "link": "format.html", + "link": "commands/format.html", "text": "Reformat Data type (format)" } ], "collapsible": true, + "icon": "", "text": "Structured Data Management" }, { "children": [ { - "link": "addheading.html", + "link": "commands/addheading.html", "text": "Add Heading (addheading)" }, { - "link": "formap.html", + "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "link": "tabulate.html", + "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" }, { - "link": "format.html", + "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "link": "select.html", + "link": "optional/select.html", "text": "Inline SQL (select)" } ], "collapsible": true, + "icon": "table", "text": "Table Management" }, { "children": [ { - "link": "os.html", + "link": "commands/os.html", "text": "Operating System (os)" }, { - "link": "cpuarch.html", + "link": "commands/cpuarch.html", "text": "CPU Architecture (cpuarch)" }, { - "link": "cpucount.html", + "link": "commands/cpucount.html", "text": "CPU Count (cpucount)" }, { - "link": "export.html", + "link": "commands/export.html", "text": "Define Environmental Variable (export)" } ], "collapsible": true, + "icon": "microchip", "text": "System Inspection" }, { "children": [ { - "link": "autocomplete.html", + "link": "commands/autocomplete.html", "text": "Tab Autocompletion (autocomplete)" }, { - "link": "config.html", + "link": "commands/config.html", "text": "Shell Configuration And Settings (config)" }, { - "link": "debug.html", + "link": "commands/debug.html", "text": "Debugging Mode (debug)" }, { - "link": "fexec.html", + "link": "commands/fexec.html", "text": "Execute Shell Function or Builtin (fexec)" }, { - "link": "murex-update-exe-list.html", + "link": "commands/murex-update-exe-list.html", "text": "Re-Scan $PATH For Executables" }, { - "link": "history.html", + "link": "commands/history.html", "text": "Command Line History (history)" }, { - "link": "summary.html", + "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" }, { - "link": "source.html", + "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { - "link": "version.html", + "link": "commands/version.html", "text": "Murex Version (version)" }, { - "link": "murex-package.html", + "link": "commands/murex-package.html", "text": "Murex Package Management (murex-package)" }, { - "link": "openagent.html", + "link": "commands/openagent.html", "text": "Define Handlers For \"open\" (openagent)" }, { - "link": "pipe.html", + "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" }, { - "link": "runtime.html", + "link": "commands/runtime.html", "text": "Shell Runtime (runtime)" }, { - "link": "alias.html", + "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { - "link": "function.html", + "link": "commands/function.html", "text": "Public Function (function)" }, { - "link": "private.html", + "link": "commands/private.html", "text": "Private Function (private)" }, { - "link": "method.html", + "link": "commands/method.html", "text": "Define Method Relationships (method)" }, { - "link": "test.html", + "link": "commands/test.html", "text": "Shell Script Tests (test)" }, { - "link": "event.html", + "link": "commands/event.html", "text": "event" } ], "collapsible": true, + "icon": "gear", "text": "Shell / Murex Management" }, { "children": [ { - "link": "escape.html", + "link": "commands/escape.html", "text": "Quote String (escape)" }, { - "link": "eschtml.html", + "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { - "link": "escurl.html", + "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { - "link": "esccli.html", + "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { - "link": "key-code.html", + "link": "commands/key-code.html", "text": "key-code" } ], "collapsible": true, + "icon": "file-code", "text": "String Escaping / Character Codes" }, { "children": [ { - "link": "exitnum.html", + "link": "commands/exitnum.html", "text": "Get Exit Code (exitnum)" }, { - "link": "bexists.html", + "link": "commands/bexists.html", "text": "Check Builtin Exists (bexists)" }, { - "link": "source.html", + "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { - "link": "which.html", + "link": "commands/which.html", "text": "Location Of Command (which)" }, { - "link": "bg.html", + "link": "commands/bg.html", "text": "Background Process (bg)" }, { - "link": "fg.html", + "link": "commands/fg.html", "text": "Foreground Process (fg)" }, { - "link": "fid-list.html", + "link": "commands/fid-list.html", "text": "Display Running Functions (fid-list)" }, { - "link": "fid-kill.html", + "link": "commands/fid-kill.html", "text": "Kill Function (fid-kill)" }, { - "link": "fid-killall.html", + "link": "commands/fid-killall.html", "text": "Kill All In Session (fid-killall)" }, { - "link": "time.html", + "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { - "link": "exec.html", + "link": "commands/exec.html", "text": "Execute External Command (exec)" }, { - "link": "signal.html", + "link": "commands/signal.html", "text": "signal" } ], "collapsible": true, + "icon": "robot", "text": "Process Management" }, { "children": [ { - "link": "expr.html", + "link": "commands/expr.html", "text": "expr" }, { - "link": "args.html", + "link": "commands/args.html", "text": "Define Function Arguments (args)" }, { - "link": "and.html", + "link": "commands/and.html", "text": "Logic And Statements (and)" }, { - "link": "or.html", + "link": "commands/or.html", "text": "Logic Or Statements (or)" }, { - "link": "return.html", + "link": "commands/return.html", "text": "Exit Function (return)" }, { - "link": "break.html", + "link": "commands/break.html", "text": "Exit Block (break)" }, { - "link": "continue.html", + "link": "commands/continue.html", "text": "Next Iteration (continue)" }, { - "link": "for.html", + "link": "commands/for.html", "text": "For Loop (for)" }, { - "link": "foreach.html", + "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { - "link": "formap.html", + "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "link": "function.html", + "link": "commands/function.html", "text": "Public Function (function)" }, { - "link": "private.html", + "link": "commands/private.html", "text": "Private Function (private)" }, { - "link": "if.html", + "link": "commands/if.html", "text": "If Conditional (if)" }, { - "link": "switch.html", + "link": "commands/switch.html", "text": "Switch Conditional (switch)" }, { - "link": "while.html", + "link": "commands/while.html", "text": "Loop While (while)" }, { - "link": "get-type.html", + "link": "commands/get-type.html", "text": "Get Data Type (get-type)" }, { - "link": "is-null.html", + "link": "commands/is-null.html", "text": "Is Value Null (is-null)" }, { - "link": "exit.html", + "link": "commands/exit.html", "text": "Exit Murex (exit)" }, { - "link": "devnull.html", + "link": "commands/devnull.html", "text": "Null (null)" }, { - "link": "not-func.html", + "link": "commands/not-func.html", "text": "Not (!)" }, { - "link": "cast.html", + "link": "commands/cast.html", "text": "Define Type (cast)" }, { - "link": "set.html", + "link": "commands/set.html", "text": "Define Variable (set)" }, { - "link": "global.html", + "link": "commands/global.html", "text": "Define Global (global)" } ], "collapsible": true, + "icon": "language", "text": "Language And Scripting" }, { "children": [ { - "link": "unsafe.html", + "link": "commands/unsafe.html", "text": "Disable Error Handling In Block (unsafe)" }, { - "link": "try.html", + "link": "commands/try.html", "text": "Try Block (try)" }, { - "link": "trypipe.html", + "link": "commands/trypipe.html", "text": "Pipe Fail (trypipe)" }, { - "link": "catch.html", + "link": "commands/catch.html", "text": "Caught Error Block (catch)" }, { - "link": "runmode.html", + "link": "commands/runmode.html", "text": "Function / Module Defaults (runmode)" }, { - "link": "tryerr.html", + "link": "commands/tryerr.html", "text": "Stderr Checking In TTY (tryerr)" }, { - "link": "trypipeerr.html", + "link": "commands/trypipeerr.html", "text": "Stderr Checking In Pipes (trypipeerr)" } ], "collapsible": true, + "icon": "bomb", "text": "Error Handling" }, { "children": [ { - "link": "man-summary.html", + "link": "commands/man-summary.html", "text": "Man-Page Summary (man-summary)" }, { - "link": "summary.html", + "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" }, { - "link": "man-get-flags.html", + "link": "commands/man-get-flags.html", "text": "Parse Man-Page For Flags (man-get-flags)" }, { - "link": "murex-docs.html", + "link": "commands/murex-docs.html", "text": "Murex's Offline Documentation (murex-docs)" } ], "collapsible": true, + "icon": "lightbulb", "text": "Help and Hint Tools" }, { - "link": "murex-parser.html", + "link": "commands/murex-parser.html", "text": "murex-parser" }, { - "link": "let.html", + "link": "commands/let.html", "text": "let" }, { - "link": "die.html", + "link": "commands/die.html", "text": "die" } ] \ No newline at end of file diff --git a/utils/docgen/api/category.go b/utils/docgen/api/category.go index 74f74b6bd..79c0269ea 100644 --- a/utils/docgen/api/category.go +++ b/utils/docgen/api/category.go @@ -16,6 +16,8 @@ type category struct { // Description of the category Description string `yaml:"Description"` + VueIcon string `yaml:"VueIcon"` + SubCategories []*category `yaml:"SubCategories"` Templates []templates `yaml:"Templates"` diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 1af053a86..1cd74b4cf 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -377,6 +377,7 @@ func vuePressSubMenu(cat *category) []map[string]any { } menu = append(menu, map[string]any{ "text": vueTitle(sub.Title), + "icon": sub.VueIcon, "children": subMenu, "collapsible": true, }) From ccb7287b9b4017dc5b9520e6c6046cd2e8e7c433 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sat, 31 Aug 2024 23:33:25 +0100 Subject: [PATCH 071/142] docgen: vue icons --- gen/docgen.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 3ed8b0d9f..7c8b2c917 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -30,7 +30,7 @@ Categories: Commands for working with files and/or the filesystem. - ID: commands.posix Title: Defined by POSIX - VueIcon: freebsd + VueIcon: server Description: |- Commands defined by POSIX. - ID: commands.list @@ -51,7 +51,7 @@ Categories: Commands for working with numerical data. - ID: commands.struct Title: Structured Data Management - VueIcon: + VueIcon: sitemap Description: |- Commands for working with structured data such as maps, tables, arrays and other data formats that are present in documents such as CSV, JSON, YAML, TOML, Sexpr, CSV, etc. - ID: commands.table From 8327f457516a8fb911dd7b8506797aadec5fc066 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 00:36:49 +0100 Subject: [PATCH 072/142] website: update docs --- builtins/core/expressions/expressions_doc.yaml | 2 +- builtins/docs/summaries.go | 16 ++++++++-------- builtins/events/onKeyPress/keycodes_doc.yaml | 2 +- docs/changelog/v3.0.md | 4 ++-- docs/changelog/v4.4.md | 4 ++-- docs/changelog/v6.1.md | 4 ++-- docs/changelog/v6.2.md | 4 ++-- docs/commands/README.md | 16 ++++++++-------- docs/commands/export.md | 4 ++-- docs/commands/expr.md | 2 +- docs/commands/global.md | 4 ++-- docs/commands/key-code.md | 2 +- docs/commands/let.md | 4 ++-- docs/commands/round.md | 2 +- docs/commands/set.md | 4 ++-- docs/parser/add-with.md | 4 ++-- docs/parser/addition.md | 4 ++-- docs/parser/assign-or-merge.md | 4 ++-- docs/parser/c-style-fun.md | 4 ++-- docs/parser/create-array.md | 4 ++-- docs/parser/create-object.md | 4 ++-- docs/parser/divide-by.md | 4 ++-- docs/parser/division.md | 4 ++-- docs/parser/elvis.md | 4 ++-- docs/parser/equ.md | 4 ++-- docs/parser/expr-inlined.md | 4 ++-- docs/parser/multiplication.md | 4 ++-- docs/parser/multiply-by.md | 4 ++-- docs/parser/null-coalescing.md | 4 ++-- docs/parser/subtract-by.md | 4 ++-- docs/parser/subtraction.md | 4 ++-- docs/user-guide/README.md | 8 ++++---- docs/user-guide/operators-and-tokens.md | 4 ++-- docs/user-guide/strict-types.md | 4 ++-- gen/vuepress/commands_generated.json | 4 ++-- 35 files changed, 79 insertions(+), 79 deletions(-) diff --git a/builtins/core/expressions/expressions_doc.yaml b/builtins/core/expressions/expressions_doc.yaml index 8c1d586e6..ff3d171b0 100644 --- a/builtins/core/expressions/expressions_doc.yaml +++ b/builtins/core/expressions/expressions_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: expr Title: >+ - `expr` + Expressions (`expr`) CategoryID: commands SubCategoryIDs: - commands.num diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 0745a4546..6f3b9dd14 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -6,6 +6,7 @@ package docs func init() { Summary = map[string]string{ + "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "addheading": "Adds headings to a table", "prefix": "Prefix a string to every item in a list", "suffix": "Prefix a string to every item in a list", @@ -49,6 +50,7 @@ func init() { "break": "Terminate execution of a block within your processes scope", "return": "Exits current function scope", "exit": "Exit murex", + "expr": "Expressions: mathematical, string comparisons, logical operators", "false": "Returns a `false` value", "foreach": "Iterate through an array", "formap": "Iterate through a map or other collection of data", @@ -122,8 +124,6 @@ func init() { "try": "Handles non-zero exits inside a block of code", "die": "Terminate murex with an exit number of 1 (deprecated)", "event": "Event driven programming for shell scripts", - "expr": "Expressions: mathematical, string comparisons, logical operators", - "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "let": "Evaluate a mathematical function and assign to variable (deprecated)", "murex-parser": "Runs the Murex parser against a block of code", "signal": "Sends a signal RPC", @@ -135,6 +135,7 @@ func init() { "qr": "Creates a QR code from stdin", "sleep": "Suspends the shell for a number of seconds", + "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "commands/addheading": "Adds headings to a table", "commands/prefix": "Prefix a string to every item in a list", "commands/suffix": "Prefix a string to every item in a list", @@ -178,6 +179,7 @@ func init() { "commands/break": "Terminate execution of a block within your processes scope", "commands/return": "Exits current function scope", "commands/exit": "Exit murex", + "commands/expr": "Expressions: mathematical, string comparisons, logical operators", "commands/false": "Returns a `false` value", "commands/foreach": "Iterate through an array", "commands/formap": "Iterate through a map or other collection of data", @@ -251,8 +253,6 @@ func init() { "commands/try": "Handles non-zero exits inside a block of code", "commands/die": "Terminate murex with an exit number of 1 (deprecated)", "commands/event": "Event driven programming for shell scripts", - "commands/expr": "Expressions: mathematical, string comparisons, logical operators", - "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", "commands/murex-parser": "Runs the Murex parser against a block of code", "commands/signal": "Sends a signal RPC", @@ -415,6 +415,7 @@ func init() { Synonym = map[string]string{ + "key-code": "key-code", "addheading": "addheading", "prefix": "prefix", "list.prefix": "prefix", @@ -485,6 +486,7 @@ func init() { "break": "break", "return": "return", "exit": "exit", + "expr": "expr", "false": "false", "foreach": "foreach", "formap": "formap", @@ -593,8 +595,6 @@ func init() { "die": "die", "event": "event", "!event": "event", - "expr": "expr", - "key-code": "key-code", "let": "let", "murex-parser": "murex-parser", "signal": "signal", @@ -657,6 +657,7 @@ func init() { "logical-or": "parser/logical-or", "tilde": "parser/tilde", + "commands/key-code": "commands/key-code", "commands/addheading": "commands/addheading", "commands/prefix": "commands/prefix", "commands/list.prefix": "commands/prefix", @@ -727,6 +728,7 @@ func init() { "commands/break": "commands/break", "commands/return": "commands/return", "commands/exit": "commands/exit", + "commands/expr": "commands/expr", "commands/false": "commands/false", "commands/foreach": "commands/foreach", "commands/formap": "commands/formap", @@ -835,8 +837,6 @@ func init() { "commands/die": "commands/die", "commands/event": "commands/event", "commands/!event": "commands/event", - "commands/expr": "commands/expr", - "commands/key-code": "commands/key-code", "commands/let": "commands/let", "commands/murex-parser": "commands/murex-parser", "commands/signal": "commands/signal", diff --git a/builtins/events/onKeyPress/keycodes_doc.yaml b/builtins/events/onKeyPress/keycodes_doc.yaml index 2903ffc0a..2e56dcf5b 100644 --- a/builtins/events/onKeyPress/keycodes_doc.yaml +++ b/builtins/events/onKeyPress/keycodes_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: key-code Title: >+ - `key-code` + ASCII And ANSI Escape Sequences (`key-code`) CategoryID: commands SubCategoryIDs: [ commands.esc ] Summary: >- diff --git a/docs/changelog/v3.0.md b/docs/changelog/v3.0.md index 169116477..c37f6c88f 100644 --- a/docs/changelog/v3.0.md +++ b/docs/changelog/v3.0.md @@ -106,6 +106,8 @@ Published: 31.12.2022 at 08:10 Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines. * [Exit Block (`break`)](../commands/break.md): Terminate execution of a block within your processes scope +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Filter By Range `[ ..Range ]`](../parser/range.md): Outputs a ranged subset of data from stdin * [For Each In List (`foreach`)](../commands/foreach.md): @@ -122,8 +124,6 @@ Published: 31.12.2022 at 08:10 Query or define Murex runtime settings * [Stream New List (`a`)](../commands/a.md): A sophisticated yet simple way to stream an array or list (mkarray) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [index](../parser/item-index.md): Outputs an element from an array, map or table diff --git a/docs/changelog/v4.4.md b/docs/changelog/v4.4.md index 822678b67..d1fc8d5cb 100644 --- a/docs/changelog/v4.4.md +++ b/docs/changelog/v4.4.md @@ -136,6 +136,8 @@ Published: 27.07.2023 at 23:12 * [Exit Function (`return`)](../commands/return.md): Exits current function scope +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where * [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): @@ -156,8 +158,6 @@ Published: 27.07.2023 at 23:12 A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`int`](../types/int.md): Whole number (primitive) * [`num` (number)](../types/num.md): diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index 6a239c598..184767485 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -144,6 +144,8 @@ Published: 17.06.2024 at 22:54 * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences +* [ASCII And ANSI Escape Sequences (`key-code`)](../commands/key-code.md): + Returns character sequences for any key pressed (ie sent from the terminal) * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints * [Contributing](../Murex/CONTRIBUTING.md): @@ -170,8 +172,6 @@ Published: 17.06.2024 at 22:54 A list of all the terminal hotkeys and their uses * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`key-code`](../commands/key-code.md): - Returns character sequences for any key pressed (ie sent from the terminal) * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 2c9a36354..fcc5c4f60 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -90,14 +90,14 @@ Published: 19.07.2024 at 08:54 Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/commands/README.md b/docs/commands/README.md index 1b4928538..033fb6370 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -95,6 +95,8 @@ Commands defined by POSIX. Change (working) directory * [Display Command Type (`type`)](../commands/type.md): Command type (function, builtin, alias, etc) +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [False (`false`)](../commands/false.md): Returns a `false` value * [Location Of Command (`which`)](../commands/which.md): @@ -107,8 +109,6 @@ Commands defined by POSIX. `read` a line of input from the user and store as a variable * [True (`true`)](../commands/true.md): Returns a `true` value -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators ### List / Array Editing @@ -191,12 +191,12 @@ Commands for working with strings. Commands for working with numerical data. +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Generate Random Sequence (`rand`)](../commands/rand.md): Random field generator * [Round Number (`round`)](../commands/round.md): Round a number by a user defined precision -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators ### Structured Data Management @@ -298,6 +298,8 @@ Commands to manage the Murex shell session. Commands to escape special characters in various different string formats. +* [ASCII And ANSI Escape Sequences (`key-code`)](../commands/key-code.md): + Returns character sequences for any key pressed (ie sent from the terminal) * [Escape Command Line String (`esccli`)](../commands/esccli.md): Escapes an array so output is valid shell code * [Escape HTML (`eschtml`)](../commands/eschtml.md): @@ -306,8 +308,6 @@ Commands to escape special characters in various different string formats. Encode or decodes text for the URL * [Quote String (`escape`)](../commands/escape.md): Escape or unescape input -* [`key-code`](../commands/key-code.md): - Returns character sequences for any key pressed (ie sent from the terminal) ### Process Management @@ -356,6 +356,8 @@ Various commands that enable control flow, error handling and other important ch Exits current function scope * [Exit Murex (`exit`)](../commands/exit.md): Exit murex +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array * [For Each In Map (`formap`)](../commands/formap.md): @@ -386,8 +388,6 @@ Various commands that enable control flow, error handling and other important ch Define a function block * [Switch Conditional (`switch`)](../commands/switch.md): Blocks of cascading conditionals -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators ### Error Handling diff --git a/docs/commands/export.md b/docs/commands/export.md index e3d85d435..086c398a3 100644 --- a/docs/commands/export.md +++ b/docs/commands/export.md @@ -275,6 +275,8 @@ bar Define a global variable and set it's value * [Define Variable (`set`)](../commands/set.md): Define a variable (typically local) and set it's value +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): @@ -285,8 +287,6 @@ bar Initiates or terminates a string (variables expanded) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/commands/expr.md b/docs/commands/expr.md index 069a2afb6..2d5509ca5 100644 --- a/docs/commands/expr.md +++ b/docs/commands/expr.md @@ -1,4 +1,4 @@ -# `expr` +# Expressions (`expr`) > Expressions: mathematical, string comparisons, logical operators diff --git a/docs/commands/global.md b/docs/commands/global.md index a5b55a60c..40f0be19d 100644 --- a/docs/commands/global.md +++ b/docs/commands/global.md @@ -257,6 +257,8 @@ bar Define an environmental variable and set it's value * [Define Variable (`set`)](../commands/set.md): Define a variable (typically local) and set it's value +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table * [Get Nested Element (`[[ Element ]]`)](../parser/element.md): @@ -271,8 +273,6 @@ bar Initiates or terminates a string (variables expanded) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/commands/key-code.md b/docs/commands/key-code.md index 68b5f83af..c92ed2239 100644 --- a/docs/commands/key-code.md +++ b/docs/commands/key-code.md @@ -1,4 +1,4 @@ -# `key-code` +# ASCII And ANSI Escape Sequences (`key-code`) > Returns character sequences for any key pressed (ie sent from the terminal) diff --git a/docs/commands/let.md b/docs/commands/let.md index de9413cb2..bfa68b054 100644 --- a/docs/commands/let.md +++ b/docs/commands/let.md @@ -401,6 +401,8 @@ bar Define a global variable and set it's value * [Define Variable (`set`)](../commands/set.md): Define a variable (typically local) and set it's value +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table * [Get Nested Element (`[[ Element ]]`)](../parser/element.md): @@ -415,8 +417,6 @@ bar Initiates or terminates a string (variables expanded) * [`=` (arithmetic evaluation)](../parser/equ.md): Evaluate a mathematical function (deprecated) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/commands/round.md b/docs/commands/round.md index 165f2ef81..d5c369e80 100644 --- a/docs/commands/round.md +++ b/docs/commands/round.md @@ -79,7 +79,7 @@ Rounding to the nearest multiple of `20`: ## See Also -* [`expr`](../commands/expr.md): +* [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/commands/set.md b/docs/commands/set.md index ecb643770..aaf2ed852 100644 --- a/docs/commands/set.md +++ b/docs/commands/set.md @@ -259,6 +259,8 @@ bar Define a global variable and set it's value * [Execute External Command (`exec`)](../commands/exec.md): Runs an executable +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table * [Get Nested Element (`[[ Element ]]`)](../parser/element.md): @@ -273,8 +275,6 @@ bar Initiates or terminates a string (variables expanded) * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/parser/add-with.md b/docs/parser/add-with.md index b8162f754..d4d459444 100644 --- a/docs/parser/add-with.md +++ b/docs/parser/add-with.md @@ -45,6 +45,8 @@ value op value**, for example: * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -57,8 +59,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/addition.md b/docs/parser/addition.md index 81e7bc228..af8300004 100644 --- a/docs/parser/addition.md +++ b/docs/parser/addition.md @@ -63,6 +63,8 @@ Error in `expr` (0,1): cannot Add with string types * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -77,8 +79,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/assign-or-merge.md b/docs/parser/assign-or-merge.md index e68b0fa23..dbef191d4 100644 --- a/docs/parser/assign-or-merge.md +++ b/docs/parser/assign-or-merge.md @@ -92,6 +92,8 @@ builtin. * [Alter Data Structure (`alter`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [For Each In List (`foreach`)](../commands/foreach.md): Iterate through an array * [Globbing (`g`)](../commands/g.md): @@ -100,8 +102,6 @@ builtin. A table of all supported operators and tokens * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/parser/c-style-fun.md b/docs/parser/c-style-fun.md index 9b3d01428..5374f63e4 100644 --- a/docs/parser/c-style-fun.md +++ b/docs/parser/c-style-fun.md @@ -103,14 +103,14 @@ It is 23 o' clock * [Date And Time Conversion (`datetime`)](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): Getting started with Murex * [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [Output String (`echo`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [sub-shell](../parser/sub-shell.md): diff --git a/docs/parser/create-array.md b/docs/parser/create-array.md index 956dac790..e78f3d87f 100644 --- a/docs/parser/create-array.md +++ b/docs/parser/create-array.md @@ -179,6 +179,8 @@ arrays. For more details on these please refer to the documents for each format A sophisticated yet simply way to build a JSON array * [Create New Array (`ta`)](../commands/ta.md): A sophisticated yet simple way to build an array of a user defined data-type +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Special Ranges](../mkarray/special.md): Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) * [Stream New List (`a`)](../commands/a.md): @@ -191,8 +193,6 @@ arrays. For more details on these please refer to the documents for each format Quickly generate objects (dictionaries / maps) * [`'Single Quote'`](../parser/single-quote.md): Initiates or terminates a string (variables not expanded) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/parser/create-object.md b/docs/parser/create-object.md index a202afd5d..564c05b7a 100644 --- a/docs/parser/create-object.md +++ b/docs/parser/create-object.md @@ -63,6 +63,8 @@ look like a number. ## See Also +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Special Ranges](../mkarray/special.md): Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc) * [`"Double Quote"`](../parser/double-quote.md): @@ -73,8 +75,6 @@ look like a number. Quickly generate arrays * [`'Single Quote'`](../parser/single-quote.md): Initiates or terminates a string (variables not expanded) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/parser/divide-by.md b/docs/parser/divide-by.md index 84a33abe5..865e880fd 100644 --- a/docs/parser/divide-by.md +++ b/docs/parser/divide-by.md @@ -45,6 +45,8 @@ value op value**, for example: * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -57,8 +59,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/division.md b/docs/parser/division.md index 43eb95838..ef35db1af 100644 --- a/docs/parser/division.md +++ b/docs/parser/division.md @@ -58,6 +58,8 @@ Error in `expr` (0,1): cannot Add with string types * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -72,8 +74,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md index f82aaf607..a9db05611 100644 --- a/docs/parser/elvis.md +++ b/docs/parser/elvis.md @@ -51,6 +51,8 @@ where it says: * [Error String (`err`)](../commands/err.md): Print a line to the stderr +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Output String (`out`)](../commands/out.md): @@ -69,8 +71,6 @@ where it says: Returns the right operand if the left operand is empty / undefined (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails * [null](../commands/devnull.md): diff --git a/docs/parser/equ.md b/docs/parser/equ.md index e6cdb026d..9f4c549ae 100644 --- a/docs/parser/equ.md +++ b/docs/parser/equ.md @@ -196,6 +196,8 @@ Murex uses the [govaluate package](https://github.com/Knetic/govaluate). More in Define a global variable and set it's value * [Define Variable (`set`)](../commands/set.md): Define a variable (typically local) and set it's value +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Get Item (`[ Index ]`)](../parser/item-index.md): Outputs an element from an array, map or table * [Get Nested Element (`[[ Element ]]`)](../parser/element.md): @@ -208,8 +210,6 @@ Murex uses the [govaluate package](https://github.com/Knetic/govaluate). More in How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) diff --git a/docs/parser/expr-inlined.md b/docs/parser/expr-inlined.md index 638f264db..8096d8952 100644 --- a/docs/parser/expr-inlined.md +++ b/docs/parser/expr-inlined.md @@ -23,12 +23,12 @@ that parameter will be treated like a string. ## See Also +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Output String (`echo`)](../commands/out.md): Print a string to the stdout with a trailing new line character -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/parser/multiplication.md b/docs/parser/multiplication.md index 4d09ba6e5..d49ed0480 100644 --- a/docs/parser/multiplication.md +++ b/docs/parser/multiplication.md @@ -58,6 +58,8 @@ Error in `expr` (0,1): cannot Add with string types * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -72,8 +74,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts one numeric value from another (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/multiply-by.md b/docs/parser/multiply-by.md index 7f31e0b06..44f2700c0 100644 --- a/docs/parser/multiply-by.md +++ b/docs/parser/multiply-by.md @@ -45,6 +45,8 @@ value op value**, for example: * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -57,8 +59,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`/=` Divide By Operator](../parser/divide-by.md): Divides a variable by the right hand value (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md index d718e8374..dbcc04812 100644 --- a/docs/parser/null-coalescing.md +++ b/docs/parser/null-coalescing.md @@ -56,6 +56,8 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N * [Error String (`err`)](../commands/err.md): Print a line to the stderr +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined * [Operators And Tokens](../user-guide/operators-and-tokens.md): @@ -76,8 +78,6 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N Returns the right operand if the left operand is falsy (expression) * [`?` stderr Pipe](../parser/pipe-err.md): Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails * [null](../commands/devnull.md): diff --git a/docs/parser/subtract-by.md b/docs/parser/subtract-by.md index f4772ff7a..6d31ea6b7 100644 --- a/docs/parser/subtract-by.md +++ b/docs/parser/subtract-by.md @@ -45,6 +45,8 @@ value op value**, for example: * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -57,8 +59,6 @@ value op value**, for example: Subtracts a variable by the right hand value (expression) * [`-` Subtraction Operator](../parser/subtraction.md): Subtracts one numeric value from another (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/parser/subtraction.md b/docs/parser/subtraction.md index 0f740f7d2..cdeafb7a1 100644 --- a/docs/parser/subtraction.md +++ b/docs/parser/subtraction.md @@ -58,6 +58,8 @@ Error in `expr` (0,1): cannot Add with string types * [Define Type (`cast`)](../commands/cast.md): Alters the data-type of the previous function without altering its output +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): A table of all supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -72,8 +74,6 @@ Error in `expr` (0,1): cannot Add with string types Subtracts a variable by the right hand value (expression) * [`/` Division Operator](../parser/division.md): Divides one numeric value from another (expression) -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`int`](../types/int.md): diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 2c84e2cb8..b80f0f9d8 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -149,6 +149,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. ### Standard Builtins +* [ASCII And ANSI Escape Sequences (`key-code`)](../commands/key-code.md): + Returns character sequences for any key pressed (ie sent from the terminal) * [Add Heading (`addheading`)](../commands/addheading.md): Adds headings to a table * [Add Prefix (`prefix`)](../commands/prefix.md): @@ -235,6 +237,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Exits current function scope * [Exit Murex (`exit`)](../commands/exit.md): Exit murex +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [False (`false`)](../commands/false.md): Returns a `false` value * [For Each In List (`foreach`)](../commands/foreach.md): @@ -381,10 +385,6 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Terminate murex with an exit number of 1 (deprecated) * [`event`](../commands/event.md): Event driven programming for shell scripts -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators -* [`key-code`](../commands/key-code.md): - Returns character sequences for any key pressed (ie sent from the terminal) * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`murex-parser`](../commands/murex-parser.md): diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index ceb45605b..e8772bfea 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -285,10 +285,10 @@ characters have special meanings when escaped. ## See Also +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): Getting started with Murex -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index debd5c27c..7953b76e7 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -50,14 +50,14 @@ changing this option will not cause accidental side-effects in other functions. ## See Also +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): Getting started with Murex * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Variable and Config Scoping](../user-guide/scoping.md): How scoping works within Murex -* [`expr`](../commands/expr.md): - Expressions: mathematical, string comparisons, logical operators
diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 7e1cb170b..bb9d657d2 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -133,7 +133,7 @@ } ], "collapsible": true, - "icon": "freebsd", + "icon": "server", "text": "Defined by POSIX" }, { @@ -345,7 +345,7 @@ } ], "collapsible": true, - "icon": "", + "icon": "sitemap", "text": "Structured Data Management" }, { From 7da9f97fdf1d11966a66a95124d3533921d91dbf Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 00:42:52 +0100 Subject: [PATCH 073/142] gen: updated json --- gen/vuepress/commands_generated.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index bb9d657d2..c3a42b9ee 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -93,7 +93,7 @@ "children": [ { "link": "commands/expr.html", - "text": "expr" + "text": "Expressions (expr)" }, { "link": "commands/out.html", @@ -286,7 +286,7 @@ "children": [ { "link": "commands/expr.html", - "text": "expr" + "text": "Expressions (expr)" }, { "link": "commands/rand.html", @@ -501,7 +501,7 @@ }, { "link": "commands/key-code.html", - "text": "key-code" + "text": "ASCII And ANSI Escape Sequences (key-code)" } ], "collapsible": true, @@ -567,7 +567,7 @@ "children": [ { "link": "commands/expr.html", - "text": "expr" + "text": "Expressions (expr)" }, { "link": "commands/args.html", From 998671c57a341e3740848888e933428700c8bd13 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 13:30:31 +0100 Subject: [PATCH 074/142] #863 job-control: helix-editor ^Z in macOS iTerm2 --- app/app.go | 2 +- builtins/core/processes/bgfg_unix.go | 4 +- integrations/helix-editor_posix.mx | 3 +- lang/exec.go | 10 +-- lang/exec_test.go | 2 +- lang/exec_unix.go | 82 +++++++++++++++------- lang/process/sysproc.go | 76 ++++++++++++++++---- lang/process/sysproc_test.go | 12 ++-- lang/process_structs.go | 5 +- lang/session_fallback.go | 8 +++ lang/session_unix.go | 19 +++++ shell/shell.go | 1 + shell/signal_handler/sigfns/sigfns.go | 2 +- shell/signal_handler/sigfns/sigfns_unix.go | 28 ++++++-- version.svg | 2 +- 15 files changed, 193 insertions(+), 63 deletions(-) create mode 100644 lang/session_fallback.go create mode 100644 lang/session_unix.go diff --git a/app/app.go b/app/app.go index dc326bb33..d13c30604 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 497 + Revision = 587 Branch = "863/job-control" ) diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index 982832978..863dac248 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -27,7 +27,7 @@ func mkbg(p *lang.Process) error { return errors.New("FID is not a stopped process. Run `jobs` or `fid-list` to see a list of stopped processes") } - if f.SystemProcess.Defined() { + if f.SystemProcess.External() { err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err @@ -63,7 +63,7 @@ func cmdForeground(p *lang.Process) error { lang.ForegroundProc.Set(f) f.State.Set(state.Executing) - if f.SystemProcess.Defined() { + if f.SystemProcess.External() { if f.SystemProcess.ForcedTTY() { lang.UnixPidToFg(f.SystemProcess.Pid()) } diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index f301b8e80..8711335af 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -2,5 +2,6 @@ return } -summary hx "Helix: a post-modern text editor" +define-force-tty-func hx +summary hx "Helix: a post-modern text editor" diff --git a/lang/exec.go b/lang/exec.go index 8c557dcb6..1f5a3f963 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -42,11 +42,11 @@ func forceTTY(p *Process) bool { func External(p *Process) error { err := execute(p) if err != nil { - if p.SystemProcess.Defined() { - p.ExitNum = p.SystemProcess.ExitNum() - } else { - p.ExitNum = 1 - } + //if p.SystemProcess.External() { + p.ExitNum = p.SystemProcess.ExitNum() + //} else { + // p.ExitNum = 1 + //} return err } diff --git a/lang/exec_test.go b/lang/exec_test.go index d50d2361f..6a165c341 100644 --- a/lang/exec_test.go +++ b/lang/exec_test.go @@ -33,7 +33,7 @@ func TestProcessExecStruct(t *testing.T) { return } - if !p.SystemProcess.Defined() { + if !p.SystemProcess.External() { t.Errorf("Expecting a non-nil p.SystemProcess") return } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 3afd79bc6..248f7b074 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -6,7 +6,7 @@ package lang import ( "fmt" "os" - "os/signal" + "sync" "syscall" "github.com/lmorg/murex/debug" @@ -42,11 +42,11 @@ func osExecFork(p *Process, argv []string) error { //Dir: pwd, Files: []*os.File{ os.Stdin, - //os.Stdout, - //os.Stderr, + os.Stdout, + os.Stderr, //p.Stdin.File(), - p.Stdout.File(), - p.Stderr.File(), + //p.Stdout.File(), + //p.Stderr.File(), }, Env: p.Envs, Sys: &syscall.SysProcAttr{ @@ -60,14 +60,14 @@ func osExecFork(p *Process, argv []string) error { // This is only meaningful if Setsid is true. //Setctty: true, //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: int(os.Stdin.Fd()), // Controlling TTY fd + //Ctty: int(os.Stdin.Fd()), // Controlling TTY fd // Foreground places the child process group in the foreground. // This implies Setpgid. The Ctty field must be set to // the descriptor of the controlling TTY. // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. - Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. + //Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. }, }) @@ -78,54 +78,86 @@ func osExecFork(p *Process, argv []string) error { ) } - sysProc := sysProcUnixT{ - p: unixProcess, - } + sysProc := sysProcUnixT{p: unixProcess} p.SystemProcess.Set(&sysProc) - signal.Ignore(syscall.SIGTTOU) - defer signal.Reset(syscall.SIGTTOU) + //signal.Ignore(syscall.SIGTTOU) + //defer signal.Reset(syscall.SIGTTOU) UnixPidToFg(sysProc.p.Pid) //signalhandler.Register(Interactive) - sysProc.state, err = sysProc.p.Wait() - UnixPidToFg(0) + //defer UnixPidToFg(0) - if err != nil { + return sysProc.wait() + /*if err != nil { //if !strings.HasPrefix(err.Error(), "signal:") { return err //} } - return nil + return nil*/ } type sysProcUnixT struct { p *os.Process state *os.ProcessState + mutex sync.Mutex } func (sp *sysProcUnixT) Pid() int { return sp.p.Pid } func (sp *sysProcUnixT) ExitNum() int { return sp.state.ExitCode() } func (sp *sysProcUnixT) Kill() error { return sp.p.Kill() } func (sp *sysProcUnixT) Signal(sig os.Signal) error { return sp.p.Signal(sig) } -func (sp *sysProcUnixT) State() *os.ProcessState { return sp.state } func (sp *sysProcUnixT) ForcedTTY() bool { return true } +func (sp *sysProcUnixT) State() *os.ProcessState { + sp.mutex.Lock() + defer sp.mutex.Unlock() + return sp.state +} + +func (sp *sysProcUnixT) wait() error { + state, err := sp.p.Wait() + sp.mutex.Lock() + sp.state = state + sp.mutex.Unlock() + + /*if state.Sys().(syscall.WaitStatus).Stopped() { + syscallErr := syscall.Kill(syscall.Getpid(), syscall.SIGTSTP) + if err != nil { + return syscallErr + } + }*/ + return err +} + // UnixPidToFg brings a UNIX process to the foreground. // If pid == 0 then UnixPidToFg will assume Murex Pid instead. func UnixPidToFg(pid int) { if pid == 0 { - pid = os.Getpid() + pid = syscall.Getpgrp() + //pid = syscall.Getpid() + } + + err := unixPidToFg(pid, int(os.Stdin.Fd())) + if err != nil { + tty, err := os.Open("/dev/tty") + if err != nil && debug.Enabled { + debug.Log(fmt.Sprintf("!!! UnixPidToFg(%d)->os.Open(/dev/tty): %s\n", pid, err.Error())) + return + } + unixPidToFg(pid, int(tty.Fd())) + tty.Close() } +} - err := unix.IoctlSetPointerInt(0, unix.TIOCSPGRP, pid) +func unixPidToFg(pid int, tty int) error { + //err := syscall.Setpgid(int(os.Stdin.Fd()), pid) + err := unix.IoctlSetPointerInt(tty, unix.TIOCSPGRP, pid) if err != nil && debug.Enabled { - os.Stderr.WriteString( - fmt.Sprintf("!!! failed syscall in unix.IoctlSetPointerInt -> unixResetFg()...\n!!! %s\n", - err.Error(), - ), - ) + debug.Log(fmt.Sprintf("!!! unixPidToFg(%d, %d): %s\n", pid, tty, err.Error())) } + + return err } ///// diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index 76e6176fc..143335bc4 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -1,6 +1,7 @@ package process import ( + "fmt" "os" "sync" ) @@ -26,12 +27,6 @@ func NewSystemProcessStruct() *SystemProcess { return sp } -func (sp *SystemProcess) getInheritance() systemProcessInheritance { - sp.mutex.Lock() - defer sp.mutex.Unlock() - return sp.inheritance -} - func (sp *SystemProcess) Set(i systemProcessInheritance) { sp.mutex.Lock() sp.inheritance = i @@ -39,18 +34,73 @@ func (sp *SystemProcess) Set(i systemProcessInheritance) { sp.mutex.Unlock() } -func (sp *SystemProcess) Defined() bool { +func (sp *SystemProcess) External() bool { sp.mutex.Lock() defer sp.mutex.Unlock() return sp.inheritance != nil } -func (sp *SystemProcess) Signal(sig os.Signal) error { return sp.getInheritance().Signal(sig) } -func (sp *SystemProcess) Kill() error { return sp.getInheritance().Kill() } -func (sp *SystemProcess) Pid() int { return sp.getInheritance().Pid() } -func (sp *SystemProcess) ExitNum() int { return sp.getInheritance().ExitNum() } -func (sp *SystemProcess) State() *os.ProcessState { return sp.getInheritance().State() } -func (sp *SystemProcess) ForcedTTY() bool { return sp.getInheritance().ForcedTTY() } +var errNotDefined = fmt.Errorf("no system process defined") + +func (sp *SystemProcess) Signal(sig os.Signal) error { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.Signal(sig) + } + return errNotDefined +} + +func (sp *SystemProcess) Kill() error { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.Kill() + } + return errNotDefined +} + +func (sp *SystemProcess) Pid() int { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.Pid() + } + return -1 +} + +func (sp *SystemProcess) ExitNum() int { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.ExitNum() + } + return 1 +} + +func (sp *SystemProcess) State() *os.ProcessState { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.State() + } + return nil +} + +func (sp *SystemProcess) ForcedTTY() bool { + sp.mutex.Lock() + defer sp.mutex.Unlock() + + if sp.inheritance != nil { + return sp.inheritance.ForcedTTY() + } + return false +} // WaitForPid should only be used in redirection.go func (sp *SystemProcess) WaitForPid() int { diff --git a/lang/process/sysproc_test.go b/lang/process/sysproc_test.go index 66ebce341..48e29529a 100644 --- a/lang/process/sysproc_test.go +++ b/lang/process/sysproc_test.go @@ -32,8 +32,8 @@ func TestSystemProcess(t *testing.T) { p := lang.NewTestProcess() - if p.SystemProcess.Defined() { - t.Errorf("p.SystemProcess.Defined() returned true, should be false") + if p.SystemProcess.External() { + t.Errorf("p.SystemProcess.External() returned true, should be false") return } @@ -41,8 +41,8 @@ func TestSystemProcess(t *testing.T) { p.SystemProcess.Set(&sysProcTest1T{}) switch { - case !p.SystemProcess.Defined(): - t.Errorf("invalid return for: p.SystemProcess.Defined() in test 1") + case !p.SystemProcess.External(): + t.Errorf("invalid return for: p.SystemProcess.External() in test 1") case p.SystemProcess.Pid() != 0: t.Errorf("invalid return for: p.SystemProcess.Pid() in test 1") @@ -71,8 +71,8 @@ func TestSystemProcess(t *testing.T) { p.SystemProcess.Set(&sysProcTest2T{}) switch { - case !p.SystemProcess.Defined(): - t.Errorf("invalid return for: p.SystemProcess.Defined() in test 2") + case !p.SystemProcess.External(): + t.Errorf("invalid return for: p.SystemProcess.External() in test 2") case p.SystemProcess.Pid() != 4: t.Errorf("invalid return for: p.SystemProcess.Pid() in test 2") diff --git a/lang/process_structs.go b/lang/process_structs.go index b6d70dd9a..128cda5c3 100644 --- a/lang/process_structs.go +++ b/lang/process_structs.go @@ -8,6 +8,7 @@ import ( "github.com/lmorg/murex/builtins/pipes/streams" "github.com/lmorg/murex/config" + "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/parameters" "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/ref" @@ -123,7 +124,7 @@ func (p *Process) Dump() map[string]any { } func _jsonfySysProc(p *Process) any { - if !p.SystemProcess.Defined() { + if !p.SystemProcess.External() { return nil } @@ -238,6 +239,7 @@ func newForegroundProc() *foregroundProc { func (fp *foregroundProc) Get() *Process { fp.mutex.Lock() p := fp.p + debug.Log("foregroundProc.Get()", p.Name.String(), p.Parameters.StringAll()) //if p == nil { // panic("Get() retrieved p") //} @@ -248,6 +250,7 @@ func (fp *foregroundProc) Get() *Process { func (fp *foregroundProc) Set(p *Process) { fp.mutex.Lock() + debug.Log("foregroundProc.Set()", p.Name.String()) if p == nil { panic("nil p in (fp *foregroundProc) Set(p *Process)") } diff --git a/lang/session_fallback.go b/lang/session_fallback.go new file mode 100644 index 000000000..379b22afa --- /dev/null +++ b/lang/session_fallback.go @@ -0,0 +1,8 @@ +//go:build js || windows || plan9 +// +build js windows plan9 + +package lang + +func UnixCreateSession() { + // not supported on this platform +} diff --git a/lang/session_unix.go b/lang/session_unix.go new file mode 100644 index 000000000..ca81a291e --- /dev/null +++ b/lang/session_unix.go @@ -0,0 +1,19 @@ +//go:build !js && !windows && !plan9 +// +build !js,!windows,!plan9 + +package lang + +import "syscall" + +//var UnixSessionID int + +func UnixCreateSession() { + /*var err error + UnixSessionID, err = syscall.Setsid() + if err != nil { + panic(err) + }*/ + + // Create a new session + _, _ = syscall.Setsid() +} diff --git a/shell/shell.go b/shell/shell.go index f36b39c60..b2d08955f 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -59,6 +59,7 @@ func callEventsPreview(ctx context.Context, interrupt string, previewItem string // Start the interactive shell func Start() { defer crash.Handler() + lang.UnixCreateSession() whatsnew.Display() diff --git a/shell/signal_handler/sigfns/sigfns.go b/shell/signal_handler/sigfns/sigfns.go index c2a04a1fd..bfd60e4e5 100644 --- a/shell/signal_handler/sigfns/sigfns.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -58,7 +58,7 @@ func Sigquit(interactive bool) { p.Id, procName, procParam))) p.Kill() - if p.SystemProcess.Defined() { + if p.SystemProcess.External() { err := p.SystemProcess.Kill() if err != nil { lang.ShellProcess.Stderr.Writeln([]byte( diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 48e55c4d0..5d595917b 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -15,7 +15,7 @@ import ( func Sigtstp(interactive bool) { p := lang.ForegroundProc.Get() - if p.SystemProcess.Defined() { + if p.SystemProcess.External() { err := p.SystemProcess.Signal(syscall.SIGSTOP) if err != nil { lang.ShellProcess.Stderr.Write([]byte(err.Error())) @@ -28,42 +28,58 @@ func Sigtstp(interactive bool) { } func returnFromSigtstp(p *lang.Process) { + //debug.Log("returnFromSigtstp:0", p.Name.String(), p.Parameters.StringAll()) + p.State.Set(state.Stopped) - if p.SystemProcess.Defined() && p.SystemProcess.ForcedTTY() { + if p.SystemProcess.ForcedTTY() { lang.UnixPidToFg(0) } + //debug.Log("returnFromSigtstp:1", p.Name.String(), p.Parameters.StringAll()) + show, err := lang.ShellProcess.Config.Get("shell", "stop-status-enabled", types.Boolean) if err != nil { show = false } + //debug.Log("returnFromSigtstp:2", p.Name.String(), p.Parameters.StringAll()) + if show.(bool) { stopStatus(p) } - p.State.Set(state.Stopped) - go func() { p.HasStopped <- true }() + //debug.Log("returnFromSigtstp:3", p.Name.String(), p.Parameters.StringAll()) lang.ShowPrompt <- true + + //debug.Log("returnFromSigtstp:4", p.Name.String(), p.Parameters.StringAll()) + + p.HasStopped <- true } func Sigchld(interactive bool) { + //debug.Log("Sigchld:0") if !interactive { return } + //debug.Log("Sigchld:1") p := lang.ForegroundProc.Get() - if !p.SystemProcess.Defined() || !p.SystemProcess.ForcedTTY() { + //debug.Log("Sigchld:2", p.Name.String(), p.Parameters.StringAll()) + if !p.SystemProcess.ForcedTTY() { return } + //debug.Log("Sigchld:3", p.Name.String(), p.Parameters.StringAll()) if p.SystemProcess.State() == nil || p.SystemProcess.State().Sys().(syscall.WaitStatus).Stopped() { + //debug.Log("Sigchld:4", p.Name.String(), p.Parameters.StringAll()) if p.State.Get() != state.Stopped { + //debug.Log("Sigchld:5", p.Name.String(), p.Parameters.StringAll()) returnFromSigtstp(p) } } + //debug.Log("Sigchld:6", p.Name.String(), p.Parameters.StringAll()) } func stopStatus(p *lang.Process) { @@ -91,7 +107,7 @@ func stopStatus(p *lang.Process) { ) lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) - if p.SystemProcess.Defined() { + if p.SystemProcess.External() { block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) if err != nil { lang.ShellProcess.Stderr.Writeln([]byte(err.Error())) diff --git a/version.svg b/version.svg index 0d278a233..e5df03834 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0497Version6.3.0497 +Version: 6.3.0587Version6.3.0587 From c73f53f2135ec92134ea2b9d45f7e59aaa4eaaf2 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 20:28:17 +0100 Subject: [PATCH 075/142] job-control: move session into its own package #863 --- app/app.go | 2 +- lang/exec_unix.go | 17 +++++++++++------ {lang => shell/session}/session_fallback.go | 4 ++-- {lang => shell/session}/session_unix.go | 4 ++-- shell/shell.go | 4 +++- version.svg | 2 +- 6 files changed, 20 insertions(+), 13 deletions(-) rename {lang => shell/session}/session_fallback.go (71%) rename {lang => shell/session}/session_unix.go (86%) diff --git a/app/app.go b/app/app.go index d13c30604..2b6cf08ee 100644 --- a/app/app.go +++ b/app/app.go @@ -17,7 +17,7 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 587 + Revision = 588 Branch = "863/job-control" ) diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 248f7b074..aa065a661 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -81,11 +81,7 @@ func osExecFork(p *Process, argv []string) error { sysProc := sysProcUnixT{p: unixProcess} p.SystemProcess.Set(&sysProc) - //signal.Ignore(syscall.SIGTTOU) - //defer signal.Reset(syscall.SIGTTOU) UnixPidToFg(sysProc.p.Pid) - //signalhandler.Register(Interactive) - //defer UnixPidToFg(0) return sysProc.wait() /*if err != nil { @@ -135,11 +131,21 @@ func (sp *sysProcUnixT) wait() error { func UnixPidToFg(pid int) { if pid == 0 { pid = syscall.Getpgrp() - //pid = syscall.Getpid() } err := unixPidToFg(pid, int(os.Stdin.Fd())) if err != nil { + // Opening /dev/tty feels like a bit of a kludge when we already know + // the tty of stdin. However we often see the following error when + // attempting to tcsetpgrp the file descriptor of stdin: + // + // inappropriate ioctl for device + // + // Where as opening /dev/tty and using that file descriptor resolves + // that error. + // + // So this is used as a fallback in case os.Stdin.Fd() fails. Between + // these two attempts, one _should_ work correctly. tty, err := os.Open("/dev/tty") if err != nil && debug.Enabled { debug.Log(fmt.Sprintf("!!! UnixPidToFg(%d)->os.Open(/dev/tty): %s\n", pid, err.Error())) @@ -151,7 +157,6 @@ func UnixPidToFg(pid int) { } func unixPidToFg(pid int, tty int) error { - //err := syscall.Setpgid(int(os.Stdin.Fd()), pid) err := unix.IoctlSetPointerInt(tty, unix.TIOCSPGRP, pid) if err != nil && debug.Enabled { debug.Log(fmt.Sprintf("!!! unixPidToFg(%d, %d): %s\n", pid, tty, err.Error())) diff --git a/lang/session_fallback.go b/shell/session/session_fallback.go similarity index 71% rename from lang/session_fallback.go rename to shell/session/session_fallback.go index 379b22afa..1bca7b2de 100644 --- a/lang/session_fallback.go +++ b/shell/session/session_fallback.go @@ -1,8 +1,8 @@ //go:build js || windows || plan9 // +build js windows plan9 -package lang +package session -func UnixCreateSession() { +func UnixSetSid() { // not supported on this platform } diff --git a/lang/session_unix.go b/shell/session/session_unix.go similarity index 86% rename from lang/session_unix.go rename to shell/session/session_unix.go index ca81a291e..d9fc76cd3 100644 --- a/lang/session_unix.go +++ b/shell/session/session_unix.go @@ -1,13 +1,13 @@ //go:build !js && !windows && !plan9 // +build !js,!windows,!plan9 -package lang +package session import "syscall" //var UnixSessionID int -func UnixCreateSession() { +func UnixSetSid() { /*var err error UnixSessionID, err = syscall.Setsid() if err != nil { diff --git a/shell/shell.go b/shell/shell.go index b2d08955f..65e008bb9 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -19,6 +19,7 @@ import ( "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/shell/autocomplete" "github.com/lmorg/murex/shell/history" + "github.com/lmorg/murex/shell/session" signalhandler "github.com/lmorg/murex/shell/signal_handler" "github.com/lmorg/murex/utils" "github.com/lmorg/murex/utils/ansi" @@ -59,7 +60,8 @@ func callEventsPreview(ctx context.Context, interrupt string, previewItem string // Start the interactive shell func Start() { defer crash.Handler() - lang.UnixCreateSession() + + session.UnixSetSid() whatsnew.Display() diff --git a/version.svg b/version.svg index e5df03834..9db8ac5d3 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0587Version6.3.0587 +Version: 6.3.0588Version6.3.0588 From 2cc515ae8c0877c886cc084229a456cc7ed862af Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 20:37:00 +0100 Subject: [PATCH 076/142] docgen: sort Documents --- docs/commands/README.md | 8 +- gen/vuepress/commands_generated.json | 492 +++++++++++++-------------- utils/docgen/api/render.go | 2 + 3 files changed, 252 insertions(+), 250 deletions(-) diff --git a/docs/commands/README.md b/docs/commands/README.md index 033fb6370..5155235e2 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -423,12 +423,12 @@ Tools for providing help and hints, useful when working inside the interactive s ### Uncategorised -* [`murex-parser`](../commands/murex-parser.md): - Runs the Murex parser against a block of code -* [`let`](../commands/let.md): - Evaluate a mathematical function and assign to variable (deprecated) * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) +* [`let`](../commands/let.md): + Evaluate a mathematical function and assign to variable (deprecated) +* [`murex-parser`](../commands/murex-parser.md): + Runs the Murex parser against a block of code ## Optional Builtins diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index c3a42b9ee..c9ae4817a 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -1,6 +1,18 @@ [ { "children": [ + { + "link": "commands/pipe.html", + "text": "Create Named Pipe (pipe)" + }, + { + "link": "commands/err.html", + "text": "Error String (err)" + }, + { + "link": "commands/pt.html", + "text": "Get Pipe Status (pt)" + }, { "link": "commands/out.html", "text": "Output String (out)" @@ -10,16 +22,12 @@ "text": "Output With Type Annotation (tout)" }, { - "link": "parser/brace-quote-func.html", - "text": "(brace quote)" - }, - { - "link": "commands/err.html", - "text": "Error String (err)" + "link": "parser/namedpipe.html", + "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { - "link": "commands/pt.html", - "text": "Get Pipe Status (pt)" + "link": "parser/stdin.html", + "text": "Read From Stdin (\u003cstdin\u003e)" }, { "link": "commands/read.html", @@ -34,16 +42,8 @@ "text": "Render Image In Terminal (open-image)" }, { - "link": "parser/namedpipe.html", - "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" - }, - { - "link": "parser/stdin.html", - "text": "Read From Stdin (\u003cstdin\u003e)" - }, - { - "link": "commands/pipe.html", - "text": "Create Named Pipe (pipe)" + "link": "parser/brace-quote-func.html", + "text": "(brace quote)" } ], "collapsible": true, @@ -53,36 +53,36 @@ { "children": [ { - "link": "commands/f.html", - "text": "List Filesystem Objects (f)" - }, - { - "link": "parser/file-truncate.html", - "text": "Truncate File (\u003e)" + "link": "commands/tmp.html", + "text": "Create Temporary File (tmp)" }, { "link": "commands/g.html", "text": "Globbing (g)" }, { - "link": "commands/lockfile.html", - "text": "Lock Files (lockfile)" - }, - { - "link": "commands/rx.html", - "text": "Regex Matches (rx)" + "link": "commands/f.html", + "text": "List Filesystem Objects (f)" }, { - "link": "commands/tmp.html", - "text": "Create Temporary File (tmp)" + "link": "commands/lockfile.html", + "text": "Lock Files (lockfile)" }, { "link": "commands/open.html", "text": "Open File (open)" }, + { + "link": "commands/rx.html", + "text": "Regex Matches (rx)" + }, { "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" + }, + { + "link": "parser/file-truncate.html", + "text": "Truncate File (\u003e)" } ], "collapsible": true, @@ -92,16 +92,8 @@ { "children": [ { - "link": "commands/expr.html", - "text": "Expressions (expr)" - }, - { - "link": "commands/out.html", - "text": "Output String (out)" - }, - { - "link": "commands/read.html", - "text": "Read User Input (read)" + "link": "commands/alias.html", + "text": "Alias Pointer (alias)" }, { "link": "commands/cd.html", @@ -111,25 +103,33 @@ "link": "commands/type.html", "text": "Display Command Type (type)" }, + { + "link": "commands/expr.html", + "text": "Expressions (expr)" + }, + { + "link": "commands/false.html", + "text": "False (false)" + }, { "link": "commands/which.html", "text": "Location Of Command (which)" }, { - "link": "commands/alias.html", - "text": "Alias Pointer (alias)" + "link": "commands/out.html", + "text": "Output String (out)" }, { "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { - "link": "commands/true.html", - "text": "True (true)" + "link": "commands/read.html", + "text": "Read User Input (read)" }, { - "link": "commands/false.html", - "text": "False (false)" + "link": "commands/true.html", + "text": "True (true)" } ], "collapsible": true, @@ -139,16 +139,12 @@ { "children": [ { - "link": "commands/count.html", - "text": "Count (count)" - }, - { - "link": "parser/item-index.html", - "text": "Get Item ([ Index ])" + "link": "commands/prefix.html", + "text": "Add Prefix (prefix)" }, { - "link": "commands/prepend.html", - "text": "Prepend To List (prepend)" + "link": "commands/suffix.html", + "text": "Add Suffix (suffix)" }, { "link": "commands/append.html", @@ -159,64 +155,68 @@ "text": "Change Text Case (list.case)" }, { - "link": "commands/mjoin.html", - "text": "Join Array To String (mjoin)" + "link": "commands/count.html", + "text": "Count (count)" }, { - "link": "commands/msort.html", - "text": "Sort Array (msort)" + "link": "commands/ja.html", + "text": "Create JSON Array (ja)" }, { - "link": "commands/mtac.html", - "text": "Reverse Array (mtac)" + "link": "commands/ta.html", + "text": "Create New Array (ta)" }, { - "link": "commands/left.html", - "text": "Left Sub-String (left)" + "link": "parser/range.html", + "text": "Filter By Range [ ..Range ]" }, { - "link": "commands/right.html", - "text": "Right Sub-String (right)" + "link": "commands/foreach.html", + "text": "For Each In List (foreach)" }, { - "link": "commands/prefix.html", - "text": "Add Prefix (prefix)" + "link": "parser/item-index.html", + "text": "Get Item ([ Index ])" }, { - "link": "commands/suffix.html", - "text": "Add Suffix (suffix)" + "link": "commands/mjoin.html", + "text": "Join Array To String (mjoin)" + }, + { + "link": "commands/left.html", + "text": "Left Sub-String (left)" }, { "link": "commands/match.html", "text": "Match String (match)" }, { - "link": "commands/regexp.html", - "text": "Regex Operations (regexp)" + "link": "commands/prepend.html", + "text": "Prepend To List (prepend)" }, { - "link": "commands/a.html", - "text": "Stream New List (a)" + "link": "commands/format.html", + "text": "Reformat Data type (format)" }, { - "link": "commands/ja.html", - "text": "Create JSON Array (ja)" + "link": "commands/regexp.html", + "text": "Regex Operations (regexp)" }, { - "link": "commands/ta.html", - "text": "Create New Array (ta)" + "link": "commands/mtac.html", + "text": "Reverse Array (mtac)" }, { - "link": "parser/range.html", - "text": "Filter By Range [ ..Range ]" + "link": "commands/right.html", + "text": "Right Sub-String (right)" }, { - "link": "commands/foreach.html", - "text": "For Each In List (foreach)" + "link": "commands/msort.html", + "text": "Sort Array (msort)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (format)" + "link": "commands/a.html", + "text": "Stream New List (a)" } ], "collapsible": true, @@ -226,56 +226,56 @@ { "children": [ { - "link": "commands/escape.html", - "text": "Quote String (escape)" - }, - { - "link": "commands/eschtml.html", - "text": "Escape HTML (eschtml)" + "link": "commands/list.case.html", + "text": "Change Text Case (list.case)" }, { - "link": "commands/escurl.html", - "text": "Escape URL (escurl)" + "link": "commands/datetime.html", + "text": "Date And Time Conversion (datetime)" }, { "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { - "link": "commands/list.case.html", - "text": "Change Text Case (list.case)" + "link": "commands/eschtml.html", + "text": "Escape HTML (eschtml)" }, { - "link": "commands/jsplit.html", - "text": "Split String (jsplit)" + "link": "commands/escurl.html", + "text": "Escape URL (escurl)" + }, + { + "link": "commands/rand.html", + "text": "Generate Random Sequence (rand)" }, { "link": "commands/left.html", "text": "Left Sub-String (left)" }, { - "link": "commands/right.html", - "text": "Right Sub-String (right)" + "link": "commands/pretty.html", + "text": "Prettify JSON" }, { - "link": "commands/regexp.html", - "text": "Regex Operations (regexp)" + "link": "commands/escape.html", + "text": "Quote String (escape)" }, { - "link": "commands/pretty.html", - "text": "Prettify JSON" + "link": "commands/format.html", + "text": "Reformat Data type (format)" }, { - "link": "commands/rand.html", - "text": "Generate Random Sequence (rand)" + "link": "commands/regexp.html", + "text": "Regex Operations (regexp)" }, { - "link": "commands/datetime.html", - "text": "Date And Time Conversion (datetime)" + "link": "commands/right.html", + "text": "Right Sub-String (right)" }, { - "link": "commands/format.html", - "text": "Reformat Data type (format)" + "link": "commands/jsplit.html", + "text": "Split String (jsplit)" } ], "collapsible": true, @@ -303,14 +303,6 @@ }, { "children": [ - { - "link": "commands/2darray.html", - "text": "Create 2d Array (2darray)" - }, - { - "link": "commands/map.html", - "text": "Create Map (map)" - }, { "link": "commands/alter.html", "text": "Alter Data Structure (alter)" @@ -320,28 +312,36 @@ "text": "Count (count)" }, { - "link": "commands/struct-keys.html", - "text": "Print Map / Structure Keys (struct-keys)" + "link": "commands/2darray.html", + "text": "Create 2d Array (2darray)" }, { - "link": "parser/element.html", - "text": "Get Nested Element ([[ Element ]])" + "link": "commands/map.html", + "text": "Create Map (map)" + }, + { + "link": "commands/formap.html", + "text": "For Each In Map (formap)" }, { "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "link": "commands/formap.html", - "text": "For Each In Map (formap)" + "link": "parser/element.html", + "text": "Get Nested Element ([[ Element ]])" }, { - "link": "commands/tabulate.html", - "text": "Transformation Tools (tabulate)" + "link": "commands/struct-keys.html", + "text": "Print Map / Structure Keys (struct-keys)" }, { "link": "commands/format.html", "text": "Reformat Data type (format)" + }, + { + "link": "commands/tabulate.html", + "text": "Transformation Tools (tabulate)" } ], "collapsible": true, @@ -359,16 +359,16 @@ "text": "For Each In Map (formap)" }, { - "link": "commands/tabulate.html", - "text": "Transformation Tools (tabulate)" + "link": "optional/select.html", + "text": "Inline SQL (select)" }, { "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "link": "optional/select.html", - "text": "Inline SQL (select)" + "link": "commands/tabulate.html", + "text": "Transformation Tools (tabulate)" } ], "collapsible": true, @@ -377,10 +377,6 @@ }, { "children": [ - { - "link": "commands/os.html", - "text": "Operating System (os)" - }, { "link": "commands/cpuarch.html", "text": "CPU Architecture (cpuarch)" @@ -392,6 +388,10 @@ { "link": "commands/export.html", "text": "Define Environmental Variable (export)" + }, + { + "link": "commands/os.html", + "text": "Operating System (os)" } ], "collapsible": true, @@ -401,77 +401,77 @@ { "children": [ { - "link": "commands/autocomplete.html", - "text": "Tab Autocompletion (autocomplete)" + "link": "commands/alias.html", + "text": "Alias Pointer (alias)" }, { - "link": "commands/config.html", - "text": "Shell Configuration And Settings (config)" + "link": "commands/history.html", + "text": "Command Line History (history)" }, { - "link": "commands/debug.html", - "text": "Debugging Mode (debug)" + "link": "commands/pipe.html", + "text": "Create Named Pipe (pipe)" }, { - "link": "commands/fexec.html", - "text": "Execute Shell Function or Builtin (fexec)" + "link": "commands/debug.html", + "text": "Debugging Mode (debug)" }, { - "link": "commands/murex-update-exe-list.html", - "text": "Re-Scan $PATH For Executables" + "link": "commands/openagent.html", + "text": "Define Handlers For \"open\" (openagent)" }, { - "link": "commands/history.html", - "text": "Command Line History (history)" + "link": "commands/method.html", + "text": "Define Method Relationships (method)" }, { - "link": "commands/summary.html", - "text": "Set Command Summary Hint (summary)" + "link": "commands/fexec.html", + "text": "Execute Shell Function or Builtin (fexec)" }, { "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, - { - "link": "commands/version.html", - "text": "Murex Version (version)" - }, { "link": "commands/murex-package.html", "text": "Murex Package Management (murex-package)" }, { - "link": "commands/openagent.html", - "text": "Define Handlers For \"open\" (openagent)" + "link": "commands/version.html", + "text": "Murex Version (version)" }, { - "link": "commands/pipe.html", - "text": "Create Named Pipe (pipe)" + "link": "commands/private.html", + "text": "Private Function (private)" }, { - "link": "commands/runtime.html", - "text": "Shell Runtime (runtime)" + "link": "commands/function.html", + "text": "Public Function (function)" }, { - "link": "commands/alias.html", - "text": "Alias Pointer (alias)" + "link": "commands/murex-update-exe-list.html", + "text": "Re-Scan $PATH For Executables" }, { - "link": "commands/function.html", - "text": "Public Function (function)" + "link": "commands/summary.html", + "text": "Set Command Summary Hint (summary)" }, { - "link": "commands/private.html", - "text": "Private Function (private)" + "link": "commands/config.html", + "text": "Shell Configuration And Settings (config)" }, { - "link": "commands/method.html", - "text": "Define Method Relationships (method)" + "link": "commands/runtime.html", + "text": "Shell Runtime (runtime)" }, { "link": "commands/test.html", "text": "Shell Script Tests (test)" }, + { + "link": "commands/autocomplete.html", + "text": "Tab Autocompletion (autocomplete)" + }, { "link": "commands/event.html", "text": "event" @@ -484,8 +484,12 @@ { "children": [ { - "link": "commands/escape.html", - "text": "Quote String (escape)" + "link": "commands/key-code.html", + "text": "ASCII And ANSI Escape Sequences (key-code)" + }, + { + "link": "commands/esccli.html", + "text": "Escape Command Line String (esccli)" }, { "link": "commands/eschtml.html", @@ -496,12 +500,8 @@ "text": "Escape URL (escurl)" }, { - "link": "commands/esccli.html", - "text": "Escape Command Line String (esccli)" - }, - { - "link": "commands/key-code.html", - "text": "ASCII And ANSI Escape Sequences (key-code)" + "link": "commands/escape.html", + "text": "Quote String (escape)" } ], "collapsible": true, @@ -511,48 +511,48 @@ { "children": [ { - "link": "commands/exitnum.html", - "text": "Get Exit Code (exitnum)" + "link": "commands/bg.html", + "text": "Background Process (bg)" }, { "link": "commands/bexists.html", "text": "Check Builtin Exists (bexists)" }, { - "link": "commands/source.html", - "text": "Include / Evaluate Murex Code (source)" - }, - { - "link": "commands/which.html", - "text": "Location Of Command (which)" + "link": "commands/fid-list.html", + "text": "Display Running Functions (fid-list)" }, { - "link": "commands/bg.html", - "text": "Background Process (bg)" + "link": "commands/exec.html", + "text": "Execute External Command (exec)" }, { "link": "commands/fg.html", "text": "Foreground Process (fg)" }, { - "link": "commands/fid-list.html", - "text": "Display Running Functions (fid-list)" + "link": "commands/exitnum.html", + "text": "Get Exit Code (exitnum)" }, { - "link": "commands/fid-kill.html", - "text": "Kill Function (fid-kill)" + "link": "commands/source.html", + "text": "Include / Evaluate Murex Code (source)" }, { "link": "commands/fid-killall.html", "text": "Kill All In Session (fid-killall)" }, { - "link": "commands/time.html", - "text": "Processes Execution Time (time)" + "link": "commands/fid-kill.html", + "text": "Kill Function (fid-kill)" }, { - "link": "commands/exec.html", - "text": "Execute External Command (exec)" + "link": "commands/which.html", + "text": "Location Of Command (which)" + }, + { + "link": "commands/time.html", + "text": "Processes Execution Time (time)" }, { "link": "commands/signal.html", @@ -565,37 +565,37 @@ }, { "children": [ - { - "link": "commands/expr.html", - "text": "Expressions (expr)" - }, { "link": "commands/args.html", "text": "Define Function Arguments (args)" }, { - "link": "commands/and.html", - "text": "Logic And Statements (and)" + "link": "commands/global.html", + "text": "Define Global (global)" }, { - "link": "commands/or.html", - "text": "Logic Or Statements (or)" + "link": "commands/cast.html", + "text": "Define Type (cast)" }, { - "link": "commands/return.html", - "text": "Exit Function (return)" + "link": "commands/set.html", + "text": "Define Variable (set)" }, { "link": "commands/break.html", "text": "Exit Block (break)" }, { - "link": "commands/continue.html", - "text": "Next Iteration (continue)" + "link": "commands/return.html", + "text": "Exit Function (return)" }, { - "link": "commands/for.html", - "text": "For Loop (for)" + "link": "commands/exit.html", + "text": "Exit Murex (exit)" + }, + { + "link": "commands/expr.html", + "text": "Expressions (expr)" }, { "link": "commands/foreach.html", @@ -606,56 +606,56 @@ "text": "For Each In Map (formap)" }, { - "link": "commands/function.html", - "text": "Public Function (function)" + "link": "commands/for.html", + "text": "For Loop (for)" }, { - "link": "commands/private.html", - "text": "Private Function (private)" + "link": "commands/get-type.html", + "text": "Get Data Type (get-type)" }, { "link": "commands/if.html", "text": "If Conditional (if)" }, { - "link": "commands/switch.html", - "text": "Switch Conditional (switch)" - }, - { - "link": "commands/while.html", - "text": "Loop While (while)" + "link": "commands/is-null.html", + "text": "Is Value Null (is-null)" }, { - "link": "commands/get-type.html", - "text": "Get Data Type (get-type)" + "link": "commands/and.html", + "text": "Logic And Statements (and)" }, { - "link": "commands/is-null.html", - "text": "Is Value Null (is-null)" + "link": "commands/or.html", + "text": "Logic Or Statements (or)" }, { - "link": "commands/exit.html", - "text": "Exit Murex (exit)" + "link": "commands/while.html", + "text": "Loop While (while)" }, { - "link": "commands/devnull.html", - "text": "Null (null)" + "link": "commands/continue.html", + "text": "Next Iteration (continue)" }, { "link": "commands/not-func.html", "text": "Not (!)" }, { - "link": "commands/cast.html", - "text": "Define Type (cast)" + "link": "commands/devnull.html", + "text": "Null (null)" }, { - "link": "commands/set.html", - "text": "Define Variable (set)" + "link": "commands/private.html", + "text": "Private Function (private)" }, { - "link": "commands/global.html", - "text": "Define Global (global)" + "link": "commands/function.html", + "text": "Public Function (function)" + }, + { + "link": "commands/switch.html", + "text": "Switch Conditional (switch)" } ], "collapsible": true, @@ -664,33 +664,33 @@ }, { "children": [ + { + "link": "commands/catch.html", + "text": "Caught Error Block (catch)" + }, { "link": "commands/unsafe.html", "text": "Disable Error Handling In Block (unsafe)" }, { - "link": "commands/try.html", - "text": "Try Block (try)" + "link": "commands/runmode.html", + "text": "Function / Module Defaults (runmode)" }, { "link": "commands/trypipe.html", "text": "Pipe Fail (trypipe)" }, { - "link": "commands/catch.html", - "text": "Caught Error Block (catch)" - }, - { - "link": "commands/runmode.html", - "text": "Function / Module Defaults (runmode)" + "link": "commands/trypipeerr.html", + "text": "Stderr Checking In Pipes (trypipeerr)" }, { "link": "commands/tryerr.html", "text": "Stderr Checking In TTY (tryerr)" }, { - "link": "commands/trypipeerr.html", - "text": "Stderr Checking In Pipes (trypipeerr)" + "link": "commands/try.html", + "text": "Try Block (try)" } ], "collapsible": true, @@ -704,16 +704,16 @@ "text": "Man-Page Summary (man-summary)" }, { - "link": "commands/summary.html", - "text": "Set Command Summary Hint (summary)" + "link": "commands/murex-docs.html", + "text": "Murex's Offline Documentation (murex-docs)" }, { "link": "commands/man-get-flags.html", "text": "Parse Man-Page For Flags (man-get-flags)" }, { - "link": "commands/murex-docs.html", - "text": "Murex's Offline Documentation (murex-docs)" + "link": "commands/summary.html", + "text": "Set Command Summary Hint (summary)" } ], "collapsible": true, @@ -721,15 +721,15 @@ "text": "Help and Hint Tools" }, { - "link": "commands/murex-parser.html", - "text": "murex-parser" + "link": "commands/die.html", + "text": "die" }, { "link": "commands/let.html", "text": "let" }, { - "link": "commands/die.html", - "text": "die" + "link": "commands/murex-parser.html", + "text": "murex-parser" } ] \ No newline at end of file diff --git a/utils/docgen/api/render.go b/utils/docgen/api/render.go index a119fe341..8065c03e5 100644 --- a/utils/docgen/api/render.go +++ b/utils/docgen/api/render.go @@ -6,6 +6,7 @@ import ( "io" golog "log" "os" + "sort" ) var ( @@ -30,6 +31,7 @@ func Render() (err error) { }() walkSourcePath(Config.SourcePath) + sort.Sort(Documents) if !unique() { golog.Print("[ERROR] duplicate DocumentID found") From c62b1c2b4b9d0b88ebad914873b61baa8f3b9d38 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 22:57:25 +0100 Subject: [PATCH 077/142] debug: support for io.writer --- app/app.go | 3 ++- debug/debug.go | 14 ++++++++++++++ docs/changelog/v2.7.md | 2 +- version.svg | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index 2b6cf08ee..c8d9859ee 100644 --- a/app/app.go +++ b/app/app.go @@ -17,8 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 588 + Revision = 591 Branch = "863/job-control" + DateTime = "2024-09-01 22:57:26" ) // Copyright is the copyright owner string diff --git a/debug/debug.go b/debug/debug.go index 5ac7c26c9..d8272446f 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -2,7 +2,9 @@ package debug import ( "encoding/json" + "io" "log" + "os" ) // Enabled is a flag used for debugging murex code. This can be enabled at @@ -34,3 +36,15 @@ func Dump() interface{} { Debug: Enabled, } } + +func init() { + f, err := os.OpenFile("/home/lau/dev/go/src/github.com/lmorg/murex/debug.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) + if err != nil { + panic(err.Error()) + } + LogWriter(f) +} + +func LogWriter(w io.Writer) { + log.SetOutput(w) +} diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index a93a5c249..9adc45a6c 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -66,7 +66,7 @@ This update has introduced another potential breaking change for your safety: ze * `count` should check if it is a method -* AST cache now checked more regukarly. This is to reduce the risk of memory leaks during fuzz or load testing +* AST cache now checked more regularly. This is to reduce the risk of memory leaks during fuzz or load testing * `murex-docs` still referred to `len` builtin. That should be changed to `count` diff --git a/version.svg b/version.svg index 9db8ac5d3..7229a790b 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0588Version6.3.0588 +Version: 6.3.0591Version6.3.0591 From b37820f2fbff259fca36d62ff14f92c1c9ebe21b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 22:58:19 +0100 Subject: [PATCH 078/142] version: datetime added --- .gitignore | 1 + app/app.go | 4 ++-- app/update-version.mx | 2 ++ builtins/core/management/version.go | 7 ++++++- gen/changelog/v2.7_doc.yaml | 2 +- version.svg | 2 +- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 27acbbfcd..0c11715cc 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ wasm_exec.js *.test *.prof *.pprof +debug.log # IDE .idea/ diff --git a/app/app.go b/app/app.go index c8d9859ee..0143ce7ba 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 591 + Revision = 592 Branch = "863/job-control" - DateTime = "2024-09-01 22:57:26" + DateTime = "2024-09-01 22:58:20" ) // Copyright is the copyright owner string diff --git a/app/update-version.mx b/app/update-version.mx index 85092d18b..15677edce 100755 --- a/app/update-version.mx +++ b/app/update-version.mx @@ -15,10 +15,12 @@ function get_branch_name { $rev = get_revision_number() $branch = get_branch_name() +$date = datetime(--in {now} --out "{go}2006-01-02 15:04:05") open $GLOBAL.APP_GO \ -> :str: regexp %(s/Revision\s+=\s+[0-9]+/Revision = $rev) \ -> regexp %(s#Branch\s+=\s+".*?"#Branch = "$branch"#) \ +-> regexp %(s#DateTime\s+=\s+".*?"#DateTime = "$date"#) \ -> set app_go $app_go |> $GLOBAL.APP_GO diff --git a/builtins/core/management/version.go b/builtins/core/management/version.go index 4a8297e8e..ef5025372 100644 --- a/builtins/core/management/version.go +++ b/builtins/core/management/version.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "regexp" + "strings" "github.com/lmorg/murex/app" "github.com/lmorg/murex/config/defaults" @@ -54,7 +55,11 @@ func cmdVersion(p *lang.Process) error { case "": p.Stdout.SetDataType(types.String) - v := fmt.Sprintf("%s: %s\n%s\n%s", app.Name, app.Version(), app.License, app.Copyright) + v := fmt.Sprintf( + "%s: %s\nBuilt: %s\n%s\n%s", + strings.Title(app.Name), app.Version(), + app.DateTime, + app.License, app.Copyright) _, err := p.Stdout.Writeln([]byte(v)) return err diff --git a/gen/changelog/v2.7_doc.yaml b/gen/changelog/v2.7_doc.yaml index 3f036dd6f..53b9ce775 100644 --- a/gen/changelog/v2.7_doc.yaml +++ b/gen/changelog/v2.7_doc.yaml @@ -72,7 +72,7 @@ * `count` should check if it is a method - * AST cache now checked more regukarly. This is to reduce the risk of memory leaks during fuzz or load testing + * AST cache now checked more regularly. This is to reduce the risk of memory leaks during fuzz or load testing * `murex-docs` still referred to `len` builtin. That should be changed to `count` diff --git a/version.svg b/version.svg index 7229a790b..64cb0fea6 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0591Version6.3.0591 +Version: 6.3.0592Version6.3.0592 From 65dbc719994d7727f9970d8bd3bdb293d039cad4 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 22:59:02 +0100 Subject: [PATCH 079/142] remove deprecated instances of `=` from linux profile --- app/app.go | 4 ++-- config/defaults/profile_linux.mx | 15 +++++++-------- version.svg | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/app.go b/app/app.go index 0143ce7ba..0c4588e22 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 592 + Revision = 593 Branch = "863/job-control" - DateTime = "2024-09-01 22:58:20" + DateTime = "2024-09-01 22:59:04" ) // Copyright is the copyright owner string diff --git a/config/defaults/profile_linux.mx b/config/defaults/profile_linux.mx index 528185f7b..445b4a876 100644 --- a/config/defaults/profile_linux.mx +++ b/config/defaults/profile_linux.mx @@ -1,18 +1,17 @@ function progress { # Pulls the read progress of a Linux pid via /proc/$pid/fdinfo (only runs on Linux) - if { ${os}=="linux" } then { - #params -> [ 1 ] -> set pid + if { os linux } then { $1 -> set pid - g /proc/$pid/fd/* -> regexp (f,/proc/[0-9]+/fd/([0-9]+)) -> foreach fd { + g /proc/$(pid)/fd/* -> regexp (f,/proc/[0-9]+/fd/([0-9]+)) -> foreach fd { trypipe { - open /proc/$pid/fdinfo/$fd -> cast yaml -> [ pos ] -> set pos - readlink: /proc/$pid/fd/$fd -> set file + open /proc/$(pid)/fdinfo/$(fd) -> :yaml: [ pos ] -> set pos + readlink /proc/$(pid)/fd/$(fd) -> set file du -b $file -> [ :0 ] -> set int size - if { = size > 0 } then { - = ($pos/$size)*100 -> set int percent - out "$percent% ($pos/$size) $file" + if { $size > 0 } then { + ($pos/$size)*100 -> set int percent + out "$(percent)% ($(pos)/$(size)) $file" } } } diff --git a/version.svg b/version.svg index 64cb0fea6..877b75b9d 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0592Version6.3.0592 +Version: 6.3.0593Version6.3.0593 From c798b99e36c5727951f6f2658c2f4e0fe142a337 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 22:59:36 +0100 Subject: [PATCH 080/142] tidy up debugging --- app/app.go | 4 ++-- lang/exec_unix.go | 4 ++-- lang/process_structs.go | 8 -------- shell/session/session_unix.go | 18 ++++++++++-------- utils/readline/read_tty.go | 17 +++++++++++++++-- version.svg | 2 +- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/app.go b/app/app.go index 0c4588e22..fac864634 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 593 + Revision = 594 Branch = "863/job-control" - DateTime = "2024-09-01 22:59:04" + DateTime = "2024-09-01 22:59:37" ) // Copyright is the copyright owner string diff --git a/lang/exec_unix.go b/lang/exec_unix.go index aa065a661..820d3eed5 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -148,7 +148,7 @@ func UnixPidToFg(pid int) { // these two attempts, one _should_ work correctly. tty, err := os.Open("/dev/tty") if err != nil && debug.Enabled { - debug.Log(fmt.Sprintf("!!! UnixPidToFg(%d)->os.Open(/dev/tty): %s\n", pid, err.Error())) + debug.Log(fmt.Sprintf("!!! UnixPidToFg(%d)->os.Open(/dev/tty): %s", pid, err.Error())) return } unixPidToFg(pid, int(tty.Fd())) @@ -159,7 +159,7 @@ func UnixPidToFg(pid int) { func unixPidToFg(pid int, tty int) error { err := unix.IoctlSetPointerInt(tty, unix.TIOCSPGRP, pid) if err != nil && debug.Enabled { - debug.Log(fmt.Sprintf("!!! unixPidToFg(%d, %d): %s\n", pid, tty, err.Error())) + debug.Log(fmt.Sprintf("!!! unixPidToFg(%d, %d): %s", pid, tty, err.Error())) } return err diff --git a/lang/process_structs.go b/lang/process_structs.go index 128cda5c3..6ca2ba4c4 100644 --- a/lang/process_structs.go +++ b/lang/process_structs.go @@ -8,7 +8,6 @@ import ( "github.com/lmorg/murex/builtins/pipes/streams" "github.com/lmorg/murex/config" - "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/parameters" "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/ref" @@ -239,10 +238,6 @@ func newForegroundProc() *foregroundProc { func (fp *foregroundProc) Get() *Process { fp.mutex.Lock() p := fp.p - debug.Log("foregroundProc.Get()", p.Name.String(), p.Parameters.StringAll()) - //if p == nil { - // panic("Get() retrieved p") - //} fp.mutex.Unlock() return p @@ -250,12 +245,9 @@ func (fp *foregroundProc) Get() *Process { func (fp *foregroundProc) Set(p *Process) { fp.mutex.Lock() - debug.Log("foregroundProc.Set()", p.Name.String()) if p == nil { panic("nil p in (fp *foregroundProc) Set(p *Process)") } fp.p = p - //debug.Json("fp.Set", p) - //debug.Json("fp.p", fp.p) fp.mutex.Unlock() } diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index d9fc76cd3..1e024dac4 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -3,17 +3,19 @@ package session -import "syscall" +import ( + "fmt" + "syscall" -//var UnixSessionID int + "github.com/lmorg/murex/debug" +) func UnixSetSid() { - /*var err error - UnixSessionID, err = syscall.Setsid() - if err != nil { - panic(err) - }*/ + var err error // Create a new session - _, _ = syscall.Setsid() + _, err = syscall.Setsid() + if err != nil { + debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed: %s", err.Error())) + } } diff --git a/utils/readline/read_tty.go b/utils/readline/read_tty.go index 2d70c38cb..ad25867c6 100644 --- a/utils/readline/read_tty.go +++ b/utils/readline/read_tty.go @@ -3,8 +3,21 @@ package readline -import "os" +import ( + "fmt" + "os" + + "github.com/lmorg/murex/debug" +) func read(b []byte) (int, error) { - return os.Stdin.Read(b) + i, err := os.Stdin.Read(b) + + if err != nil && debug.Enabled { + s := fmt.Sprintf("!!! cannot read from stdin: %s", err.Error()) + debug.Log(s) + panic(s) + } + + return i, err } diff --git a/version.svg b/version.svg index 877b75b9d..3a13de098 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0593Version6.3.0593 +Version: 6.3.0594Version6.3.0594 From 36974115704c036491f7a5fa4fa8973955c74bab Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 1 Sep 2024 23:22:48 +0100 Subject: [PATCH 081/142] add logfile to gitignore --- .gitignore | 4 +++- app/app.go | 4 ++-- debug/debug.go | 14 +++++--------- version.svg | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 0c11715cc..be7d7d104 100644 --- a/.gitignore +++ b/.gitignore @@ -23,12 +23,14 @@ wasm_exec.js # optional builtins /builtins/imports_build -# test working directories +# test and debugging files /deleteme /test/tmp *.test *.prof *.pprof +/debug/logfile.go + debug.log # IDE diff --git a/app/app.go b/app/app.go index fac864634..c8da84af9 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 594 + Revision = 598 Branch = "863/job-control" - DateTime = "2024-09-01 22:59:37" + DateTime = "2024-09-01 23:32:12" ) // Copyright is the copyright owner string diff --git a/debug/debug.go b/debug/debug.go index d8272446f..eaa50dca3 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -2,7 +2,6 @@ package debug import ( "encoding/json" - "io" "log" "os" ) @@ -37,14 +36,11 @@ func Dump() interface{} { } } -func init() { - f, err := os.OpenFile("/home/lau/dev/go/src/github.com/lmorg/murex/debug.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) +func LogWriter(path string) error { + f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) if err != nil { - panic(err.Error()) + return err } - LogWriter(f) -} - -func LogWriter(w io.Writer) { - log.SetOutput(w) + log.SetOutput(f) + return nil } diff --git a/version.svg b/version.svg index 3a13de098..70450a132 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0594Version6.3.0594 +Version: 6.3.0598Version6.3.0598 From 5a8fa6dbb9e6ca68beac5ca819ac33da89e28be6 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 2 Sep 2024 12:15:25 +0100 Subject: [PATCH 082/142] wip: session reporting + pty --- app/app.go | 4 +-- shell/session/session_fallback.go | 2 ++ shell/session/session_unix.go | 41 ++++++++++++++++++++++++++++--- version.svg | 2 +- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/app.go b/app/app.go index c8da84af9..ff062823f 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 598 + Revision = 612 Branch = "863/job-control" - DateTime = "2024-09-01 23:32:12" + DateTime = "2024-09-02 12:15:35" ) // Copyright is the copyright owner string diff --git a/shell/session/session_fallback.go b/shell/session/session_fallback.go index 1bca7b2de..9f302360c 100644 --- a/shell/session/session_fallback.go +++ b/shell/session/session_fallback.go @@ -6,3 +6,5 @@ package session func UnixSetSid() { // not supported on this platform } + +func UnixIsSession() bool { return false } diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index 1e024dac4..5812e1dc1 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -10,12 +10,47 @@ import ( "github.com/lmorg/murex/debug" ) +var unixSid int + func UnixSetSid() { var err error // Create a new session - _, err = syscall.Setsid() - if err != nil { - debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed: %s", err.Error())) + unixSid, err = syscall.Setsid() + if err == nil { + return } + + debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed: %s", err.Error())) + } + +func UnixIsSession() bool { + return unixSid > 0 +} + +/* + p, t, err := pty.Open() + if err != nil { + debug.Log(fmt.Sprintf(`!!! pty.Open() failed: %s`, err.Error())) + return + } + + f, err := os.Open("/dev/tty") + if err != nil { + debug.Log(fmt.Sprintf(`!!! os.Open("/dev/tty") failed: %s`, err.Error())) + return + } + + os.Stdin = p + os.Stderr = p + os.Stdout = p + + go io.Copy(os.Stdout, t) + go io.Copy(os.Stdin, f) + + _, err = syscall.Setsid() + if err == nil { + debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed again: %s", err.Error())) + } +*/ diff --git a/version.svg b/version.svg index 70450a132..96e02c452 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0598Version6.3.0598 +Version: 6.3.0612Version6.3.0612 From be9aa4066877d69cb0d7c5c45c586cf59a6735b6 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 2 Sep 2024 12:19:42 +0100 Subject: [PATCH 083/142] website: missing titles on two docs --- builtins/docs/summaries.go | 20 +++++++++---------- builtins/events/events_doc.yaml | 4 ++-- .../events/onSignalReceived/signal_doc.yaml | 2 +- docs/changelog/v2.7.md | 4 ++-- docs/changelog/v4.3.md | 4 ++-- docs/changelog/v4.4.md | 4 ++-- docs/changelog/v5.0.md | 8 ++++---- docs/changelog/v6.1.md | 4 ++-- docs/commands/README.md | 6 +++--- docs/commands/config.md | 4 ++-- docs/commands/event.md | 4 ++-- docs/commands/fexec.md | 4 ++-- docs/commands/key-code.md | 4 ++-- docs/commands/runmode.md | 4 ++-- docs/commands/runtime.md | 4 ++-- docs/commands/signal.md | 6 +++--- docs/events/oncommandcompletion.md | 4 ++-- docs/events/onfilesystemchange.md | 4 ++-- docs/events/onkeypress.md | 4 ++-- docs/events/onpreview.md | 4 ++-- docs/events/onprompt.md | 4 ++-- docs/events/onsecondselapsed.md | 4 ++-- docs/events/onsignalreceived.md | 8 ++++---- docs/integrations/chatgpt.md | 4 ++-- docs/integrations/cheatsh.md | 4 ++-- docs/integrations/man-pages.md | 4 ++-- docs/user-guide/README.md | 8 ++++---- docs/user-guide/scoping.md | 4 ++-- docs/variables/event_return.md | 2 +- gen/vuepress/commands_generated.json | 10 +++++----- version.svg | 2 +- 31 files changed, 78 insertions(+), 78 deletions(-) diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 6f3b9dd14..6d19733c7 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -78,6 +78,7 @@ func init() { "while": "Loop until condition false", "man-summary": "Outputs a man page summary of a command", "match": "Match an exact value in an array", + "event": "Event driven programming for shell scripts", "murex-package": "Murex's package manager", "version": "Get Murex version", "murex-docs": "Displays the man pages for Murex builtins", @@ -108,6 +109,7 @@ func init() { "mtac": "Reverse the order of an array", "right": "Right substring every item in a list", "round": "Round a number by a user defined precision", + "signal": "Sends a signal RPC", "summary": "Defines a summary help text for a command", "config": "Query or define Murex runtime settings", "runtime": "Returns runtime information on the internal state of Murex", @@ -123,10 +125,8 @@ func init() { "true": "Returns a `true` value", "try": "Handles non-zero exits inside a block of code", "die": "Terminate murex with an exit number of 1 (deprecated)", - "event": "Event driven programming for shell scripts", "let": "Evaluate a mathematical function and assign to variable (deprecated)", "murex-parser": "Runs the Murex parser against a block of code", - "signal": "Sends a signal RPC", "select": "Inlining SQL into shell pipelines", "bz2": "Decompress a bz2 file", @@ -207,6 +207,7 @@ func init() { "commands/while": "Loop until condition false", "commands/man-summary": "Outputs a man page summary of a command", "commands/match": "Match an exact value in an array", + "commands/event": "Event driven programming for shell scripts", "commands/murex-package": "Murex's package manager", "commands/version": "Get Murex version", "commands/murex-docs": "Displays the man pages for Murex builtins", @@ -237,6 +238,7 @@ func init() { "commands/mtac": "Reverse the order of an array", "commands/right": "Right substring every item in a list", "commands/round": "Round a number by a user defined precision", + "commands/signal": "Sends a signal RPC", "commands/summary": "Defines a summary help text for a command", "commands/config": "Query or define Murex runtime settings", "commands/runtime": "Returns runtime information on the internal state of Murex", @@ -252,10 +254,8 @@ func init() { "commands/true": "Returns a `true` value", "commands/try": "Handles non-zero exits inside a block of code", "commands/die": "Terminate murex with an exit number of 1 (deprecated)", - "commands/event": "Event driven programming for shell scripts", "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", "commands/murex-parser": "Runs the Murex parser against a block of code", - "commands/signal": "Sends a signal RPC", "mkarray/date": "Create arrays of dates", "mkarray/character": "Making character arrays (a to z)", "mkarray/decimal": "Create arrays of decimal integers", @@ -526,6 +526,8 @@ func init() { "!match": "match", "list.str": "match", "!list.str": "match", + "event": "event", + "!event": "event", "murex-package": "murex-package", "version": "version", "murex-docs": "murex-docs", @@ -570,6 +572,7 @@ func init() { "list.right": "right", "round": "round", "num.round": "round", + "signal": "signal", "summary": "summary", "!summary": "summary", "config": "config", @@ -593,11 +596,8 @@ func init() { "true": "true", "try": "try", "die": "die", - "event": "event", - "!event": "event", "let": "let", "murex-parser": "murex-parser", - "signal": "signal", "select": "optional/select", "table.select": "optional/select", @@ -768,6 +768,8 @@ func init() { "commands/!match": "commands/match", "commands/list.str": "commands/match", "commands/!list.str": "commands/match", + "commands/event": "commands/event", + "commands/!event": "commands/event", "commands/murex-package": "commands/murex-package", "commands/version": "commands/version", "commands/murex-docs": "commands/murex-docs", @@ -812,6 +814,7 @@ func init() { "commands/list.right": "commands/right", "commands/round": "commands/round", "commands/num.round": "commands/round", + "commands/signal": "commands/signal", "commands/summary": "commands/summary", "commands/!summary": "commands/summary", "commands/config": "commands/config", @@ -835,11 +838,8 @@ func init() { "commands/true": "commands/true", "commands/try": "commands/try", "commands/die": "commands/die", - "commands/event": "commands/event", - "commands/!event": "commands/event", "commands/let": "commands/let", "commands/murex-parser": "commands/murex-parser", - "commands/signal": "commands/signal", "mkarray/date": "mkarray/date", "mkarray/character": "mkarray/character", "mkarray/decimal": "mkarray/decimal", diff --git a/builtins/events/events_doc.yaml b/builtins/events/events_doc.yaml index 5ebf455c1..00de94b92 100644 --- a/builtins/events/events_doc.yaml +++ b/builtins/events/events_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: event Title: >+ - `event` + Murex Event Subsystem (`event`) CategoryID: commands SubCategoryIDs: [ commands.shell ] Summary: >- @@ -42,7 +42,7 @@ ``` event onSecondsElapsed autoquit=60 { - out "You're 60 second timeout has elapsed. Quitting murex" + out "Your 60 second timeout has elapsed. Quitting murex" exit 1 } ``` diff --git a/builtins/events/onSignalReceived/signal_doc.yaml b/builtins/events/onSignalReceived/signal_doc.yaml index 405f73ea3..e928a6ad2 100644 --- a/builtins/events/onSignalReceived/signal_doc.yaml +++ b/builtins/events/onSignalReceived/signal_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: signal Title: >+ - `signal` + Send Signal IPC (`signal`) CategoryID: commands SubCategoryIDs: [ commands.proc ] Summary: >- diff --git a/docs/changelog/v2.7.md b/docs/changelog/v2.7.md index 568251290..8a32d4304 100644 --- a/docs/changelog/v2.7.md +++ b/docs/changelog/v2.7.md @@ -80,6 +80,8 @@ Published: 15.05.2022 at 22:49 * [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): Creates a handler function for `open` +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Public Function (`function`)](../commands/function.md): Define a function block * [Read User Input (`read`)](../commands/read.md): @@ -90,8 +92,6 @@ Published: 15.05.2022 at 22:49 Query or define Murex runtime settings * [`&&` And Logical Operator](../parser/logical-and.md): Continues next operation if previous operation passes -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`||` Or Logical Operator](../parser/logical-or.md): Continues next operation only if previous operation fails diff --git a/docs/changelog/v4.3.md b/docs/changelog/v4.3.md index 6b9ab77b3..175691a0d 100644 --- a/docs/changelog/v4.3.md +++ b/docs/changelog/v4.3.md @@ -28,12 +28,12 @@ Published: 02.07.2023 at 09:55 ## See Also +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell diff --git a/docs/changelog/v4.4.md b/docs/changelog/v4.4.md index d1fc8d5cb..3939684cc 100644 --- a/docs/changelog/v4.4.md +++ b/docs/changelog/v4.4.md @@ -140,6 +140,8 @@ Published: 27.07.2023 at 23:12 Expressions: mathematical, string comparisons, logical operators * [FileRef](../user-guide/fileref.md): How to track what code was loaded and from where +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Parse Man-Page For Flags (`man-get-flags`)](../commands/man-get-flags.md): Parses man page files for command line flags * [Private Function (`private`)](../commands/private.md): @@ -156,8 +158,6 @@ Published: 27.07.2023 at 23:12 Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`int`](../types/int.md): Whole number (primitive) * [`num` (number)](../types/num.md): diff --git a/docs/changelog/v5.0.md b/docs/changelog/v5.0.md index 3a9330d1c..66174d51b 100644 --- a/docs/changelog/v5.0.md +++ b/docs/changelog/v5.0.md @@ -93,10 +93,14 @@ Published: 07.09.2023 at 00:12 Locate command origin * [Modules And Packages](../user-guide/modules.md): An introduction to Murex modules and packages +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins +* [Send Signal IPC (`signal`)](../commands/signal.md): + Sends a signal RPC * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): @@ -111,14 +115,10 @@ Published: 07.09.2023 at 00:12 Meta information about the running scope. * [`csv`](../types/csv.md): CSV files (and other character delimited tables) -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`float` (floating point number)](../types/float.md): Floating point number (primitive) * [`onSignalReceived`](../events/onsignalreceived.md): Trap OS signals -* [`signal`](../commands/signal.md): - Sends a signal RPC
diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index 184767485..fd0584517 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -162,6 +162,8 @@ Published: 17.06.2024 at 22:54 What's different about Murex's interactive shell? * [Man-Page Summary (`man-summary`)](../commands/man-summary.md): Outputs a man page summary of a command +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Post Request (`post`)](../commands/post.md): HTTP POST request with a JSON-parsable return * [Shell Runtime (`runtime`)](../commands/runtime.md): @@ -170,8 +172,6 @@ Published: 17.06.2024 at 22:54 Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros * [`onPreview`](../events/onpreview.md): diff --git a/docs/commands/README.md b/docs/commands/README.md index 5155235e2..c3629367d 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -271,6 +271,8 @@ Commands to manage the Murex shell session. Execute a command or function, bypassing the usual order of precedence. * [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager * [Murex Version (`version`)](../commands/version.md): @@ -291,8 +293,6 @@ Commands to manage the Murex shell session. Murex's test framework - define tests, run tests and debug shell scripts * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`event`](../commands/event.md): - Event driven programming for shell scripts ### String Escaping / Character Codes @@ -335,7 +335,7 @@ Management of system processes and Murex FIDs. Locate command origin * [Processes Execution Time (`time`)](../commands/time.md): Returns the execution run time of a command or block -* [`signal`](../commands/signal.md): +* [Send Signal IPC (`signal`)](../commands/signal.md): Sends a signal RPC ### Language And Scripting diff --git a/docs/commands/config.md b/docs/commands/config.md index 40d37516f..67ab40d4a 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -249,6 +249,8 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Makes a standard HTTP request and returns the result as a JSON object * [Match String (`match`)](../commands/match.md): Match an exact value in an array +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [Post Request (`post`)](../commands/post.md): @@ -259,8 +261,6 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, Returns runtime information on the internal state of Murex * [`%{}` Object Builder](../parser/create-object.md): Quickly generate objects (dictionaries / maps) -* [`event`](../commands/event.md): - Event driven programming for shell scripts
diff --git a/docs/commands/event.md b/docs/commands/event.md index daaea2732..fc8219866 100644 --- a/docs/commands/event.md +++ b/docs/commands/event.md @@ -1,4 +1,4 @@ -# `event` +# Murex Event Subsystem (`event`) > Event driven programming for shell scripts @@ -44,7 +44,7 @@ event event-type name=interrupt { code block } ``` event onSecondsElapsed autoquit=60 { - out "You're 60 second timeout has elapsed. Quitting murex" + out "Your 60 second timeout has elapsed. Quitting murex" exit 1 } ``` diff --git a/docs/commands/fexec.md b/docs/commands/fexec.md index 225e6c2f3..ff6e3c21f 100644 --- a/docs/commands/fexec.md +++ b/docs/commands/fexec.md @@ -92,6 +92,8 @@ alias to `fexec builtin` Sends a background process into the foreground * [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [Private Function (`private`)](../commands/private.md): @@ -102,8 +104,6 @@ alias to `fexec builtin` Returns runtime information on the internal state of Murex * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`event`](../commands/event.md): - Event driven programming for shell scripts
diff --git a/docs/commands/key-code.md b/docs/commands/key-code.md index c92ed2239..11325e389 100644 --- a/docs/commands/key-code.md +++ b/docs/commands/key-code.md @@ -59,10 +59,10 @@ event onKeyPress close=$key { * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Output With Type Annotation (`tout`)](../commands/tout.md): Print a string to the stdout and set it's data-type -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onKeyPress`](../events/onkeypress.md): Custom definable key bindings and macros diff --git a/docs/commands/runmode.md b/docs/commands/runmode.md index 074b47613..7577b1988 100644 --- a/docs/commands/runmode.md +++ b/docs/commands/runmode.md @@ -89,6 +89,8 @@ if `runmode ... module` is set. Execute a block of code, always returning a zero exit number * [Display Running Functions (`fid-list`)](../commands/fid-list.md): Lists all running functions within the current Murex session +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character * [Pipe Fail (`trypipe`)](../commands/trypipe.md): @@ -111,8 +113,6 @@ if `runmode ... module` is set. Set definitions for tab-completion in the command line * [Try Block (`try`)](../commands/try.md): Handles non-zero exits inside a block of code -* [`event`](../commands/event.md): - Event driven programming for shell scripts
diff --git a/docs/commands/runtime.md b/docs/commands/runtime.md index 9a076fb9a..6809be751 100644 --- a/docs/commands/runtime.md +++ b/docs/commands/runtime.md @@ -312,6 +312,8 @@ functions. Import Murex code from another file or code block * [Integrations](../user-guide/integrations.md): Default integrations shipped with Murex +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [Prettify JSON](../commands/pretty.md): @@ -328,8 +330,6 @@ functions. Murex's test framework - define tests, run tests and debug shell scripts * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) diff --git a/docs/commands/signal.md b/docs/commands/signal.md index 5ba4c9d12..396214b5a 100644 --- a/docs/commands/signal.md +++ b/docs/commands/signal.md @@ -1,4 +1,4 @@ -# `signal` +# Send Signal IPC (`signal`) > Sends a signal RPC @@ -166,12 +166,12 @@ Signals can be caught (often referred to as "trapped") in Murex with an event: What's different about Murex's interactive shell? * [MUREX_EXE](../variables/murex_exe.md): Absolute path to running shell +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [onSignalReceived](../events/onsignalreceived.md): Trap OS signals diff --git a/docs/events/oncommandcompletion.md b/docs/events/oncommandcompletion.md index 9575f2d47..5564f5bdb 100644 --- a/docs/events/oncommandcompletion.md +++ b/docs/events/oncommandcompletion.md @@ -121,6 +121,8 @@ Stdout and stderr are both written to the terminal's stderr. Create an alias for a command * [If Conditional (`if`)](../commands/if.md): Conditional statement to execute different blocks of code depending on the result of the condition +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Named Pipes](../user-guide/namedpipes.md): A detailed breakdown of named pipes in Murex * [Public Function (`function`)](../commands/function.md): @@ -133,8 +135,6 @@ Stdout and stderr are both written to the terminal's stderr. Query or define Murex runtime settings * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell * [read-named-pipe](../parser/namedpipe.md): diff --git a/docs/events/onfilesystemchange.md b/docs/events/onfilesystemchange.md index f25f8a6c3..f92d7f159 100644 --- a/docs/events/onfilesystemchange.md +++ b/docs/events/onfilesystemchange.md @@ -89,10 +89,10 @@ event to Linux, macOS and UNIX systems instead. ## See Also +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [`event`](../commands/event.md): - Event driven programming for shell scripts
diff --git a/docs/events/onkeypress.md b/docs/events/onkeypress.md index 6c5f7e531..917468fac 100644 --- a/docs/events/onkeypress.md +++ b/docs/events/onkeypress.md @@ -253,12 +253,12 @@ from different interrupts). * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onPreview`](../events/onpreview.md): diff --git a/docs/events/onpreview.md b/docs/events/onpreview.md index 76b08e4cb..38abc0d24 100644 --- a/docs/events/onpreview.md +++ b/docs/events/onpreview.md @@ -166,6 +166,8 @@ from different interrupts). What's different about Murex's interactive shell? * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Public Function (`function`)](../commands/function.md): @@ -174,8 +176,6 @@ from different interrupts). Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onKeyPress`](../events/onkeypress.md): diff --git a/docs/events/onprompt.md b/docs/events/onprompt.md index 27259a286..71cb5e56b 100644 --- a/docs/events/onprompt.md +++ b/docs/events/onprompt.md @@ -125,12 +125,12 @@ from different interrupts). * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onKeyPress`](../events/onkeypress.md): diff --git a/docs/events/onsecondselapsed.md b/docs/events/onsecondselapsed.md index 441f6683a..d9cde125f 100644 --- a/docs/events/onsecondselapsed.md +++ b/docs/events/onsecondselapsed.md @@ -58,10 +58,10 @@ Stdout and stderr are both written to the terminal. ## See Also +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [`event`](../commands/event.md): - Event driven programming for shell scripts
diff --git a/docs/events/onsignalreceived.md b/docs/events/onsignalreceived.md index 4a68dc9e1..f2e93f522 100644 --- a/docs/events/onsignalreceived.md +++ b/docs/events/onsignalreceived.md @@ -149,16 +149,16 @@ legitimately want the same name for different interrupts. * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts +* [Send Signal IPC (`signal`)](../commands/signal.md): + Sends a signal RPC * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onPrompt`](../events/onprompt.md): Events triggered by changes in state of the interactive shell -* [`signal`](../commands/signal.md): - Sends a signal RPC
diff --git a/docs/integrations/chatgpt.md b/docs/integrations/chatgpt.md index 70180af0f..058ddef2b 100644 --- a/docs/integrations/chatgpt.md +++ b/docs/integrations/chatgpt.md @@ -127,6 +127,8 @@ under `/integrations`. * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Profile Files](../user-guide/profile.md): @@ -135,8 +137,6 @@ under `/integrations`. Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): diff --git a/docs/integrations/cheatsh.md b/docs/integrations/cheatsh.md index 4d8d54f23..439fb1388 100644 --- a/docs/integrations/cheatsh.md +++ b/docs/integrations/cheatsh.md @@ -32,6 +32,8 @@ under `/integrations`. How to enable ChatGPT hints * [Man Pages (POSIX)](../integrations/man-pages.md): Linux/UNIX `man` page integrations +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Profile Files](../user-guide/profile.md): @@ -40,8 +42,6 @@ under `/integrations`. Query or define Murex runtime settings * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation diff --git a/docs/integrations/man-pages.md b/docs/integrations/man-pages.md index 0e4d6e5db..252dec9e3 100644 --- a/docs/integrations/man-pages.md +++ b/docs/integrations/man-pages.md @@ -44,14 +44,14 @@ That command will generally be pulled from its accompanying `man` page. * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`onPreview`](../events/onpreview.md): Full screen previews for files and command documentation * [cheat.sh](../integrations/cheatsh.md): diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index b80f0f9d8..e6dc16d26 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -293,6 +293,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Outputs a man page summary of a command * [Match String (`match`)](../commands/match.md): Match an exact value in an array +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager * [Murex Version (`version`)](../commands/version.md): @@ -353,6 +355,8 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Right substring every item in a list * [Round Number (`round`)](../commands/round.md): Round a number by a user defined precision +* [Send Signal IPC (`signal`)](../commands/signal.md): + Sends a signal RPC * [Set Command Summary Hint (`summary`)](../commands/summary.md): Defines a summary help text for a command * [Shell Configuration And Settings (`config`)](../commands/config.md): @@ -383,14 +387,10 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Handles non-zero exits inside a block of code * [`die`](../commands/die.md): Terminate murex with an exit number of 1 (deprecated) -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) * [`murex-parser`](../commands/murex-parser.md): Runs the Murex parser against a block of code -* [`signal`](../commands/signal.md): - Sends a signal RPC ### Optional Builtins diff --git a/docs/user-guide/scoping.md b/docs/user-guide/scoping.md index ea251bc22..d70519add 100644 --- a/docs/user-guide/scoping.md +++ b/docs/user-guide/scoping.md @@ -61,6 +61,8 @@ scope. Subshells also do not create a new scope either. Conditional statement to execute different blocks of code depending on the result of the condition * [Include / Evaluate Murex Code (`source`)](../commands/source.md): Import Murex code from another file or code block +* [Murex Event Subsystem (`event`)](../commands/event.md): + Event driven programming for shell scripts * [Private Function (`private`)](../commands/private.md): Define a private function block * [Public Function (`function`)](../commands/function.md): @@ -73,8 +75,6 @@ scope. Subshells also do not create a new scope either. Blocks of cascading conditionals * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [`event`](../commands/event.md): - Event driven programming for shell scripts * [`let`](../commands/let.md): Evaluate a mathematical function and assign to variable (deprecated) diff --git a/docs/variables/event_return.md b/docs/variables/event_return.md index f67510af8..933fdcfe1 100644 --- a/docs/variables/event_return.md +++ b/docs/variables/event_return.md @@ -54,7 +54,7 @@ the respective event document for details on using this variable. ## See Also -* [`event`](../commands/event.md): +* [Murex Event Subsystem (`event`)](../commands/event.md): Event driven programming for shell scripts * [`json`](../types/json.md): JavaScript Object Notation (JSON) diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index c9ae4817a..23cf8afb4 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -432,6 +432,10 @@ "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, + { + "link": "commands/event.html", + "text": "Murex Event Subsystem (event)" + }, { "link": "commands/murex-package.html", "text": "Murex Package Management (murex-package)" @@ -471,10 +475,6 @@ { "link": "commands/autocomplete.html", "text": "Tab Autocompletion (autocomplete)" - }, - { - "link": "commands/event.html", - "text": "event" } ], "collapsible": true, @@ -556,7 +556,7 @@ }, { "link": "commands/signal.html", - "text": "signal" + "text": "Send Signal IPC (signal)" } ], "collapsible": true, diff --git a/version.svg b/version.svg index 18ace1a5c..5e016d156 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.3200Version6.3.3200 +Version: Version From c7c28af0d24112ec9209a6863d167c1a1132fd68 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 2 Sep 2024 12:41:03 +0100 Subject: [PATCH 084/142] stringer compile to go generate + non-unix signals --- .gitignore | 3 ++- app/app.go | 4 ++-- go.mod | 7 ++++--- go.sum | 17 +++++++++-------- main.go | 16 +++------------- main_js.go | 6 ++++++ main_plan9.go | 17 +++++++++++++++++ main_unix.go | 20 ++++++++++++++++++++ main_windows.go | 18 ++++++++++++++++++ version.svg | 2 +- 10 files changed, 82 insertions(+), 28 deletions(-) create mode 100644 main_plan9.go create mode 100644 main_unix.go create mode 100644 main_windows.go diff --git a/.gitignore b/.gitignore index be7d7d104..d0924791f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ murex.exe murex.upx /docgen /docgen.exe +/stringer +/stringer.exe bin/ VERSION deleteme.db @@ -44,7 +46,6 @@ murex.iml /vendor.new /pkg /src -/gen/docs-test/ # Misc .DS_Store diff --git a/app/app.go b/app/app.go index ff062823f..6f0efc4fd 100644 --- a/app/app.go +++ b/app/app.go @@ -17,9 +17,9 @@ const ( version = "%d.%d.%04d" Major = 6 Minor = 3 - Revision = 612 + Revision = 613 Branch = "863/job-control" - DateTime = "2024-09-02 12:15:35" + DateTime = "2024-09-02 12:41:08" ) // Copyright is the copyright owner string diff --git a/go.mod b/go.mod index b8bd81803..0344e652b 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/pelletier/go-toml v1.9.5 github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee - golang.org/x/sys v0.8.0 + golang.org/x/sys v0.23.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.25.0 ) @@ -31,8 +31,9 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/stretchr/testify v1.8.2 // indirect golang.org/x/image v0.18.0 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/tools v0.24.0 // indirect lukechampine.com/uint128 v1.2.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect modernc.org/ccgo/v3 v3.16.13 // indirect diff --git a/go.sum b/go.sum index c888a0a9f..c77cc4360 100644 --- a/go.sum +++ b/go.sum @@ -17,7 +17,7 @@ github.com/eliukblau/pixterm v1.3.1 h1:XeouQViH+lmzCa7sMUoK2cd7qlgHYGLIjwRKaOdJb github.com/eliukblau/pixterm v1.3.1/go.mod h1:on5ueknFt+ZFVvIVVzQ7/JXwPjv5fJd8Q1Ybh7XixfU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -60,19 +60,20 @@ golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 452ee2a16..86bcdf344 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,9 @@ //go:build !js // +build !js +//go:generate go get golang.org/x/tools/cmd/stringer +//go:generate go build golang.org/x/tools/cmd/stringer + package main import ( @@ -15,8 +18,6 @@ import ( "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/shell" - signalhandler "github.com/lmorg/murex/shell/signal_handler" - "github.com/lmorg/murex/shell/signal_handler/sigfns" "github.com/lmorg/murex/utils/cache" "github.com/lmorg/murex/utils/readline" ) @@ -165,14 +166,3 @@ func startMurex() { registerSignalHandlers(interactive) shell.Start() } - -func registerSignalHandlers(interactiveMode bool) { - signalhandler.Handlers = &signalhandler.SignalFunctionsT{ - Sigint: sigfns.Sigint, - Sigterm: sigfns.Sigterm, - Sigquit: sigfns.Sigquit, - Sigtstp: sigfns.Sigtstp, - Sigchld: sigfns.Sigchld, - } - signalhandler.EventLoop(interactiveMode) -} diff --git a/main_js.go b/main_js.go index 18f1e0464..9c4307242 100644 --- a/main_js.go +++ b/main_js.go @@ -12,6 +12,7 @@ import ( "github.com/lmorg/murex/config/defaults" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/shell" + signalhandler "github.com/lmorg/murex/shell/signal_handler" "github.com/lmorg/murex/utils/ansi" "github.com/lmorg/murex/utils/readline" ) @@ -121,3 +122,8 @@ func wasmKeyPress() js.Func { return promiseConstructor.New(handler) }) } + +func registerSignalHandlers(interactiveMode bool) { + signalhandler.Handlers = &signalhandler.SignalFunctionsT{} + signalhandler.EventLoop(interactiveMode) +} diff --git a/main_plan9.go b/main_plan9.go new file mode 100644 index 000000000..634683752 --- /dev/null +++ b/main_plan9.go @@ -0,0 +1,17 @@ +//go:build plan9 +// +build plan9 + +package main + +import ( + signalhandler "github.com/lmorg/murex/shell/signal_handler" + "github.com/lmorg/murex/shell/signal_handler/sigfns" +) + +func registerSignalHandlers(interactiveMode bool) { + signalhandler.Handlers = &signalhandler.SignalFunctionsT{ + Sigint: sigfns.Sigint, + Sigterm: sigfns.Sigterm, + } + signalhandler.EventLoop(interactiveMode) +} diff --git a/main_unix.go b/main_unix.go new file mode 100644 index 000000000..66245f1d3 --- /dev/null +++ b/main_unix.go @@ -0,0 +1,20 @@ +//go:build !js && !windows && !plan9 +// +build !js,!windows,!plan9 + +package main + +import ( + signalhandler "github.com/lmorg/murex/shell/signal_handler" + "github.com/lmorg/murex/shell/signal_handler/sigfns" +) + +func registerSignalHandlers(interactiveMode bool) { + signalhandler.Handlers = &signalhandler.SignalFunctionsT{ + Sigint: sigfns.Sigint, + Sigterm: sigfns.Sigterm, + Sigquit: sigfns.Sigquit, + Sigtstp: sigfns.Sigtstp, + Sigchld: sigfns.Sigchld, + } + signalhandler.EventLoop(interactiveMode) +} diff --git a/main_windows.go b/main_windows.go new file mode 100644 index 000000000..4df847f52 --- /dev/null +++ b/main_windows.go @@ -0,0 +1,18 @@ +//go:build windows +// +build windows + +package main + +import ( + signalhandler "github.com/lmorg/murex/shell/signal_handler" + "github.com/lmorg/murex/shell/signal_handler/sigfns" +) + +func registerSignalHandlers(interactiveMode bool) { + signalhandler.Handlers = &signalhandler.SignalFunctionsT{ + Sigint: sigfns.Sigint, + Sigterm: sigfns.Sigterm, + Sigquit: sigfns.Sigquit, + } + signalhandler.EventLoop(interactiveMode) +} diff --git a/version.svg b/version.svg index 96e02c452..88df0c10c 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0612Version6.3.0612 +Version: 6.3.0613Version6.3.0613 From d7963544e812c8c61a0624908265e4acc1447ead Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 4 Sep 2024 21:44:43 +0100 Subject: [PATCH 085/142] version: new flags --- app/app.go | 35 ++++++++----------- app/app_test.go | 25 +++++++------- app/update-version.mx | 6 ++-- builtins/core/management/version.go | 42 +++++++++++++++-------- builtins/core/management/version_doc.yaml | 19 ++++++++-- docs/commands/version.md | 19 ++++++++-- license.go | 14 ++++++++ version.svg | 2 +- 8 files changed, 105 insertions(+), 57 deletions(-) create mode 100644 license.go diff --git a/app/app.go b/app/app.go index 6f0efc4fd..e0f3ef2de 100644 --- a/app/app.go +++ b/app/app.go @@ -12,38 +12,33 @@ import ( const Name = "murex" // Version number of $SHELL -// Format of version string should be "(major).(minor).(revision) BRANCH-NAME" +// Format of version string should be "$(Major).$(Minor).$(Revision) ($Branch)" const ( - version = "%d.%d.%04d" - Major = 6 - Minor = 3 - Revision = 613 - Branch = "863/job-control" - DateTime = "2024-09-02 12:41:08" + Major = 6 + Minor = 3 + Revision = 690 + Branch = "863/job-control" + BuildDate = "2024-09-04 21:44:47" ) // Copyright is the copyright owner string -const Copyright = "© 2018-2024 Laurence Morgan" +const Copyright = "2018-2024 Laurence Morgan" // License is the projects software license -const License = "License GPL v2" +const License = "GPL v2" -// ShellModule is the name of the module that REPL code gets imported into -var ShellModule = Name + "/shell" +var licenseFull string -func init() { - v = fmt.Sprintf(version, Major, Minor, Revision) - sv, _ = semver.Parse(v) -} +func GetLicenseFull() string { return licenseFull } +func SetLicenseFull(s string) { licenseFull = s } -var v string +// ShellModule is the name of the module that REPL code gets imported into +var ShellModule = Name + "/shell" func Version() string { - return fmt.Sprintf("%s %s", v, Branch) + return fmt.Sprintf("%d.%d.%04d (%s)", Major, Minor, Revision, Branch) } -var sv *semver.Version - func Semver() *semver.Version { - return sv + return &semver.Version{Major, Minor, Revision} } diff --git a/app/app_test.go b/app/app_test.go index 004f973a0..662248f45 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -1,4 +1,4 @@ -package app +package app_test import ( "fmt" @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/lmorg/murex/app" "github.com/lmorg/murex/test/count" "github.com/lmorg/murex/utils/semver" ) @@ -13,41 +14,41 @@ import ( func TestAppName(t *testing.T) { count.Tests(t, 1) - if Name == "" { + if app.Name == "" { t.Error("Name isn't valid:") - t.Log(" Name:", Name) + t.Log(" Name:", app.Name) } } func TestVersion(t *testing.T) { count.Tests(t, 1) - rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( ([-._/a-zA-Z0-9]+))?$`) + rx := regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+( \(([-._/a-zA-Z0-9]+)\))?$`) - if !rx.MatchString(Version()) { + if !rx.MatchString(app.Version()) { t.Error("Release version doesn't contain a valid string:") - t.Log(" Version:", Version()) + t.Log(" Version:", app.Version()) } } func TestCopyright(t *testing.T) { count.Tests(t, 1) - rx := regexp.MustCompile(fmt.Sprintf(`^(\(c\)|©) [0-9]{4}-%s .*$`, time.Now().Format("2006"))) + rx := regexp.MustCompile(fmt.Sprintf(`^[0-9]{4}-%s .*$`, time.Now().Format("2006"))) - if !rx.MatchString(Copyright) { + if !rx.MatchString(app.Copyright) { t.Error("Copyright string doesn't contain a valid string (possibly out of date?):") - t.Log(" Copyright:", Copyright) + t.Log(" Copyright:", app.Copyright) } } func TestLicense(t *testing.T) { - if License == "" { + if app.License == "" { t.Error("License isn't valid:") - t.Log(" License:", License) + t.Log(" License:", app.License) } } func TestSemVer(t *testing.T) { - _, err := semver.Parse(v) + _, err := semver.Parse(fmt.Sprintf("%d.%d.%d", app.Major, app.Minor, app.Revision)) if err != nil { t.Error(err) } diff --git a/app/update-version.mx b/app/update-version.mx index 15677edce..4f8707aeb 100755 --- a/app/update-version.mx +++ b/app/update-version.mx @@ -17,10 +17,10 @@ $rev = get_revision_number() $branch = get_branch_name() $date = datetime(--in {now} --out "{go}2006-01-02 15:04:05") -open $GLOBAL.APP_GO \ --> :str: regexp %(s/Revision\s+=\s+[0-9]+/Revision = $rev) \ +open $GLOBAL.APP_GO -> cast str \ +-> regexp %(s/Revision\s+=\s+[0-9]+/Revision = $rev) \ -> regexp %(s#Branch\s+=\s+".*?"#Branch = "$branch"#) \ --> regexp %(s#DateTime\s+=\s+".*?"#DateTime = "$date"#) \ +-> regexp %(s#BuildDate\s+=\s+".*?"#BuildDate = "$date"#) \ -> set app_go $app_go |> $GLOBAL.APP_GO diff --git a/builtins/core/management/version.go b/builtins/core/management/version.go index ef5025372..8c85af119 100644 --- a/builtins/core/management/version.go +++ b/builtins/core/management/version.go @@ -1,9 +1,7 @@ package management import ( - "errors" "fmt" - "regexp" "strings" "github.com/lmorg/murex/app" @@ -16,14 +14,15 @@ func init() { lang.DefineFunction("version", cmdVersion, types.String) defaults.AppendProfile(` - autocomplete set version { [{ - "Flags": [ "--short", "--no-app-name", "--license", "--copyright" ] - }] } + autocomplete set version %[{ + Flags: [ + --short --no-app-name --license --license-full + --copyright --build-date --branch + ] + }] `) } -var rxVersionNum = regexp.MustCompile(`^[0-9]+\.[0-9]+`) - func cmdVersion(p *lang.Process) error { s, _ := p.Parameters.String(0) @@ -31,11 +30,8 @@ func cmdVersion(p *lang.Process) error { case "--short": p.Stdout.SetDataType(types.Number) - num := rxVersionNum.FindStringSubmatch(app.Version()) - if len(num) != 1 { - return errors.New("unable to extract version number from string") - } - _, err := p.Stdout.Write([]byte(num[0])) + version := fmt.Sprintf("%d.%d", app.Major, app.Minor) + _, err := p.Stdout.Write([]byte(version)) return err case "--no-app-name": @@ -48,18 +44,34 @@ func cmdVersion(p *lang.Process) error { _, err := p.Stdout.Writeln([]byte(app.License)) return err + case "--license-full": + p.Stdout.SetDataType(types.String) + _, err := p.Stdout.Writeln([]byte(app.GetLicenseFull())) + return err + case "--copyright": p.Stdout.SetDataType(types.String) _, err := p.Stdout.Writeln([]byte(app.Copyright)) return err + case "--build-date": + p.Stdout.SetDataType(types.String) + _, err := p.Stdout.Writeln([]byte(app.BuildDate)) + return err + + case "--branch": + p.Stdout.SetDataType(types.String) + _, err := p.Stdout.Writeln([]byte(app.Branch)) + return err + case "": p.Stdout.SetDataType(types.String) v := fmt.Sprintf( - "%s: %s\nBuilt: %s\n%s\n%s", + "%s: %s\nBuilt: %s\nLicense: %s\nCopyright: %s", strings.Title(app.Name), app.Version(), - app.DateTime, - app.License, app.Copyright) + app.BuildDate, + app.License, + app.Copyright) _, err := p.Stdout.Writeln([]byte(v)) return err diff --git a/builtins/core/management/version_doc.yaml b/builtins/core/management/version_doc.yaml index d9a4a41c7..eb4dc357c 100644 --- a/builtins/core/management/version_doc.yaml +++ b/builtins/core/management/version_doc.yaml @@ -15,27 +15,40 @@ ``` » version - murex: 0.51.1200 BETA + Murex: 6.3.0687 (863/job-control) + Built: 2024-09-04 19:43:47 + License: GPL v2 + Copyright: 2018-2024 Laurence Morgan ``` ### --no-app-name ``` » version --no-app-name - 0.51.1200 BETA + 6.3.0688 (863/job-control) ``` ### --short ``` » version --short - 0.51 + 6.3 ``` Flags: --short: >- Returns only the major and minor version as a `num` data-type --no-app-name: >- Returns full version string minus app name + --license: >- + Just print the license name + --license-full: >- + Prints the full license terms + --copyright: >- + Prints copyright holder(s) + --build-date: >- + Date of last code generation. This usually happens are part of the compilation process + --branch: >- + The source code branch used in this build. This will typically be `master` Detail: Synonyms: Related: diff --git a/docs/commands/version.md b/docs/commands/version.md index 16a85a263..37f93e754 100644 --- a/docs/commands/version.md +++ b/docs/commands/version.md @@ -18,25 +18,38 @@ version [ flags ] -> ``` » version -murex: 0.51.1200 BETA +Murex: 6.3.0687 (863/job-control) +Built: 2024-09-04 19:43:47 +License: GPL v2 +Copyright: 2018-2024 Laurence Morgan ``` ### --no-app-name ``` » version --no-app-name -0.51.1200 BETA +6.3.0688 (863/job-control) ``` ### --short ``` » version --short -0.51 +6.3 ``` ## Flags +* `--branch` + The source code branch used in this build. This will typically be `master` +* `--build-date` + Date of last code generation. This usually happens are part of the compilation process +* `--copyright` + Prints copyright holder(s) +* `--license` + Just print the license name +* `--license-full` + Prints the full license terms * `--no-app-name` Returns full version string minus app name * `--short` diff --git a/license.go b/license.go new file mode 100644 index 000000000..b504c3645 --- /dev/null +++ b/license.go @@ -0,0 +1,14 @@ +package main + +import ( + _ "embed" + + "github.com/lmorg/murex/app" +) + +//go:embed LICENSE +var license string + +func init() { + app.SetLicenseFull(license) +} diff --git a/version.svg b/version.svg index 88df0c10c..21b6804f0 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0613Version6.3.0613 +Version: 6.3.0690Version6.3.0690 From 04a651d71735c464ce81073984fffe39b2fb4581 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 4 Sep 2024 21:46:07 +0100 Subject: [PATCH 086/142] flags: MUREX_DEBUG --- app/app.go | 4 ++-- debug/debug.go | 8 ++++++++ flags.go | 4 ++++ main.go | 1 - version.svg | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index e0f3ef2de..75f7e5903 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 690 + Revision = 691 Branch = "863/job-control" - BuildDate = "2024-09-04 21:44:47" + BuildDate = "2024-09-04 21:46:09" ) // Copyright is the copyright owner string diff --git a/debug/debug.go b/debug/debug.go index eaa50dca3..9d54763c7 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -2,6 +2,7 @@ package debug import ( "encoding/json" + "fmt" "log" "os" ) @@ -17,6 +18,13 @@ func Log(data ...interface{}) { } } +// Logf writes a debug message using [fmt.Printf] arguments. +func Logf(format string, v ...interface{}) { + if Enabled { + log.Println(fmt.Sprintf(format, v...)) + } +} + // Json encode an object then write it as a debug message func Json(context string, data interface{}) { if Enabled { diff --git a/flags.go b/flags.go index b0179ad4e..b3af3ebf0 100644 --- a/flags.go +++ b/flags.go @@ -76,5 +76,9 @@ func readFlags() { Global: true, }) + if os.Getenv("MUREX_DEBUG") == "true" { + debug.Enabled = true + } + fSource = flag.Args() } diff --git a/main.go b/main.go index 86bcdf344..60306b1ee 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ //go:build !js // +build !js -//go:generate go get golang.org/x/tools/cmd/stringer //go:generate go build golang.org/x/tools/cmd/stringer package main diff --git a/version.svg b/version.svg index 21b6804f0..f002a0c69 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0690Version6.3.0690 +Version: 6.3.0691Version6.3.0691 From ace0985d91bf36471ee0a336ca49ccbe81acd9b3 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 4 Sep 2024 21:52:02 +0100 Subject: [PATCH 087/142] #863 job-control: session now works for most macOS instances --- app/app.go | 4 +- lang/exec.go | 4 +- lang/exec_unix.go | 107 ++++++++++++++++------------------ shell/session/session_unix.go | 84 ++++++++++++++++++++------ version.svg | 2 +- 5 files changed, 120 insertions(+), 81 deletions(-) diff --git a/app/app.go b/app/app.go index 75f7e5903..fc4073a35 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 691 + Revision = 692 Branch = "863/job-control" - BuildDate = "2024-09-04 21:46:09" + BuildDate = "2024-09-04 21:52:05" ) // Copyright is the copyright owner string diff --git a/lang/exec.go b/lang/exec.go index 1f5a3f963..36363aec7 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -181,6 +181,8 @@ func execForkFallback(p *Process, argv []string) error { //} } + p.SystemProcess.Set(&sysProcT{cmd}) + // *** // Get murex data type // *** @@ -210,8 +212,6 @@ func execForkFallback(p *Process, argv []string) error { ///////// - p.SystemProcess.Set(&sysProcT{cmd}) - /*if err := mxdtW.Close(); err != nil { tty.Stderr.WriteString("error closing murex data type output file write pipe:" + err.Error() + "\n") }*/ diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 820d3eed5..2daeef143 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -11,12 +11,18 @@ import ( "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang/state" + "github.com/lmorg/murex/shell/session" "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/which" "golang.org/x/sys/unix" ) func osExecFork(p *Process, argv []string) error { + if !session.UnixIsSession() { + debug.Logf("!!! session not defined, falling back to non-unix ttys") + return execForkFallback(p, argv) + } + if p.HasCancelled() { return nil } @@ -37,40 +43,7 @@ func osExecFork(p *Process, argv []string) error { } p.State.Set(state.Executing) - - unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, &os.ProcAttr{ - //Dir: pwd, - Files: []*os.File{ - os.Stdin, - os.Stdout, - os.Stderr, - //p.Stdin.File(), - //p.Stdout.File(), - //p.Stderr.File(), - }, - Env: p.Envs, - Sys: &syscall.SysProcAttr{ - //Setsid: true, // Create session. - // Setpgid sets the process group ID of the child to Pgid, - // or, if Pgid == 0, to the new child's process ID. - Setpgid: true, - // Setctty sets the controlling terminal of the child to - // file descriptor Ctty. Ctty must be a descriptor number - // in the child process: an index into ProcAttr.Files. - // This is only meaningful if Setsid is true. - //Setctty: true, - //Noctty: true, // Detach fd 0 from controlling terminal - //Ctty: int(os.Stdin.Fd()), // Controlling TTY fd - // Foreground places the child process group in the foreground. - // This implies Setpgid. The Ctty field must be set to - // the descriptor of the controlling TTY. - // Unlike Setctty, in this case Ctty must be a descriptor - // number in the parent process. - //Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. - }, - }) - + unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, unixProcAttr(p.Envs)) if err != nil { return fmt.Errorf("failed fork in os.StartProcess -> osExecFork()...\n%s\nargv: %s", err.Error(), @@ -82,7 +55,6 @@ func osExecFork(p *Process, argv []string) error { p.SystemProcess.Set(&sysProc) UnixPidToFg(sysProc.p.Pid) - return sysProc.wait() /*if err != nil { //if !strings.HasPrefix(err.Error(), "signal:") { @@ -129,36 +101,29 @@ func (sp *sysProcUnixT) wait() error { // UnixPidToFg brings a UNIX process to the foreground. // If pid == 0 then UnixPidToFg will assume Murex Pid instead. func UnixPidToFg(pid int) { - if pid == 0 { - pid = syscall.Getpgrp() + var err error + + pid, err = syscall.Getpgid(unix.Getpid()) + if err != nil { + debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) + pid = syscall.Getpid() } - err := unixPidToFg(pid, int(os.Stdin.Fd())) + err = unixPidToFg(pid, int(os.Stdin.Fd())) + if err == nil { + // success, no need to retry + return + } + + err = unixPidToFg(pid, int(session.UnixTTY().Fd())) if err != nil { - // Opening /dev/tty feels like a bit of a kludge when we already know - // the tty of stdin. However we often see the following error when - // attempting to tcsetpgrp the file descriptor of stdin: - // - // inappropriate ioctl for device - // - // Where as opening /dev/tty and using that file descriptor resolves - // that error. - // - // So this is used as a fallback in case os.Stdin.Fd() fails. Between - // these two attempts, one _should_ work correctly. - tty, err := os.Open("/dev/tty") - if err != nil && debug.Enabled { - debug.Log(fmt.Sprintf("!!! UnixPidToFg(%d)->os.Open(/dev/tty): %s", pid, err.Error())) - return - } - unixPidToFg(pid, int(tty.Fd())) - tty.Close() + debug.Logf("!!! UnixPidToFg(%d)->session.UnixTTY(): %s", pid, err.Error()) } } func unixPidToFg(pid int, tty int) error { err := unix.IoctlSetPointerInt(tty, unix.TIOCSPGRP, pid) - if err != nil && debug.Enabled { + if err != nil { debug.Log(fmt.Sprintf("!!! unixPidToFg(%d, %d): %s", pid, tty, err.Error())) } @@ -189,3 +154,31 @@ func osSysProcAttr(fd int) *syscall.SysProcAttr { //Pgid: 0, // Child's process group ID if Setpgid. } } + +func unixProcAttr(envs []string) *os.ProcAttr { + return &os.ProcAttr{ + //Files: []*os.File{session.UnixTTY(), session.UnixTTY(), session.UnixTTY()}, + Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, + Env: envs, + Sys: &syscall.SysProcAttr{ + //Setsid: true, // Create session. + // Setpgid sets the process group ID of the child to Pgid, + // or, if Pgid == 0, to the new child's process ID. + Setpgid: true, + // Setctty sets the controlling terminal of the child to + // file descriptor Ctty. Ctty must be a descriptor number + // in the child process: an index into ProcAttr.Files. + // This is only meaningful if Setsid is true. + //Setctty: true, + //Noctty: true, // Detach fd 0 from controlling terminal + //Ctty: 0, // Controlling TTY fd + // Foreground places the child process group in the foreground. + // This implies Setpgid. The Ctty field must be set to + // the descriptor of the controlling TTY. + // Unlike Setctty, in this case Ctty must be a descriptor + // number in the parent process. + //Foreground: true, + Pgid: 0, // Child's process group ID if Setpgid. + }, + } +} diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index 5812e1dc1..6fe70814e 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -4,53 +4,99 @@ package session import ( - "fmt" + "os" "syscall" "github.com/lmorg/murex/debug" + signalhandler "github.com/lmorg/murex/shell/signal_handler" ) -var unixSid int +var ( + unixSid int + tty = os.Stdin +) func UnixSetSid() { + debug.Log("!!! Entering UnixSetSid()") + var err error + pid := os.Getpid() + + // create a new group + err = syscall.Setpgid(pid, os.Getppid()) + if err != nil { + debug.Logf("!!! UnixSetSid()->syscall.Setpgid() failed: %s", err.Error()) + } + // Create a new session unixSid, err = syscall.Setsid() - if err == nil { - return + if err != nil { + debug.Logf("!!! UnixSetSid()->syscall.Setsid() failed: %s", err.Error()) } - debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed: %s", err.Error())) + // Opening /dev/tty feels like a bit of a kludge when we already know + // the tty of stdin. However we often see the following error when + // attempting to tcsetpgrp the file descriptor of stdin: + // + // inappropriate ioctl for device + // + // Where as opening /dev/tty and using that file descriptor resolves + // that error. + tty, err = os.Open(`/dev/tty`) + if err != nil { + debug.Logf("!!! UnixSetSid()->os.Open(`/dev/tty`) failed: %s", err.Error()) + } else { + debug.Log("!!! UnixSetSid()->os.Open(`/dev/tty`) success") + } + signalhandler.Register(true) } func UnixIsSession() bool { return unixSid > 0 } +func UnixTTY() *os.File { + return tty +} + /* - p, t, err := pty.Open() +func relaunchMurex() error { + if os.Getenv("MUREX_SESSION") != "" { + return fmt.Errorf("session already nested") + } + + cmd := exec.Command(which.WhichIgnoreFail(os.Args[0]), os.Args[1:]...) + cmd.Env = append(os.Environ(), fmt.Sprintf("MUREX_SESSION=%d", os.Getpid())) + cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + + size, err := pty.GetsizeFull(UnixTTY()) + if err != nil { + return fmt.Errorf("cannot get size of terminal: %s", err.Error()) + } + + tty, err := pty.StartWithSize(cmd, size) if err != nil { - debug.Log(fmt.Sprintf(`!!! pty.Open() failed: %s`, err.Error())) - return + return fmt.Errorf("error starting process: %s", err.Error()) } - f, err := os.Open("/dev/tty") + mxState, err := readline.MakeRaw(int(os.Stdin.Fd())) if err != nil { - debug.Log(fmt.Sprintf(`!!! os.Open("/dev/tty") failed: %s`, err.Error())) - return + return fmt.Errorf("cannot put TTY into raw mode: %s", err.Error()) } - os.Stdin = p - os.Stderr = p - os.Stdout = p + defer readline.Restore(int(os.Stdin.Fd()), mxState) - go io.Copy(os.Stdout, t) - go io.Copy(os.Stdin, f) + go io.Copy(os.Stdout, tty) + go io.Copy(tty, os.Stdin) - _, err = syscall.Setsid() - if err == nil { - debug.Log(fmt.Sprintf("!!! syscall.Setsid() failed again: %s", err.Error())) + err = cmd.Wait() + if err != nil { + return err } + + os.Exit(0) + return nil // this is silly but go doesn't compile without it +} */ diff --git a/version.svg b/version.svg index f002a0c69..5ae7baeaf 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0691Version6.3.0691 +Version: 6.3.0692Version6.3.0692 From d5c8e1ea874f772aa00e24297914fbc327ac1a50 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 4 Sep 2024 22:25:57 +0100 Subject: [PATCH 088/142] version: fix version builtin test --- app/app.go | 4 ++-- builtins/core/management/version_test.go | 6 +++--- version.svg | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/app.go b/app/app.go index fc4073a35..1bd183929 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 692 + Revision = 693 Branch = "863/job-control" - BuildDate = "2024-09-04 21:52:05" + BuildDate = "2024-09-04 22:25:59" ) // Copyright is the copyright owner string diff --git a/builtins/core/management/version_test.go b/builtins/core/management/version_test.go index cec4b146b..dc1dd575a 100644 --- a/builtins/core/management/version_test.go +++ b/builtins/core/management/version_test.go @@ -11,15 +11,15 @@ func TestVersion(t *testing.T) { tests := []test.MurexTest{ { Block: `version`, - Stdout: `murex: [0-9]+\.[0-9]+\.[0-9]+( (.*?))?\nLicense .*?\n© 2018-[0-9]{4} Laurence Morgan\n`, + Stdout: `Murex: [0-9]+\.[0-9]+\.[0-9]+( (.*?))?\nBuilt: .*?\nLicense: .*?\nCopyright: 2018-[0-9]{4} Laurence Morgan\n`, }, { Block: `version: --copyright`, - Stdout: `© 2018-[0-9]{4} Laurence Morgan\n`, + Stdout: `2018-[0-9]{4} Laurence Morgan\n`, }, { Block: `version: --license`, - Stdout: `License .*?\n`, + Stdout: `^GPL v2\n$`, }, { Block: `version: --no-app-name`, diff --git a/version.svg b/version.svg index 5ae7baeaf..9f5fd2032 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0692Version6.3.0692 +Version: 6.3.0693Version6.3.0693 From 6b8c1f01e49d0386864ed425fca09563cf17a501 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 5 Sep 2024 00:06:35 +0100 Subject: [PATCH 089/142] regexp: `M/` matches & includes heading --- app/app.go | 4 +-- builtins/core/lists/regexp.go | 44 +++++++++++++++++++++++++---- builtins/core/lists/regexp_doc.yaml | 27 +++++++++++++----- docs/commands/regexp.md | 17 +++++++++-- integrations/helix-editor_posix.mx | 2 +- version.svg | 2 +- 6 files changed, 78 insertions(+), 18 deletions(-) diff --git a/app/app.go b/app/app.go index 1bd183929..59bf11c12 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 693 + Revision = 699 Branch = "863/job-control" - BuildDate = "2024-09-04 22:25:59" + BuildDate = "2024-09-05 00:06:37" ) // Copyright is the copyright owner string diff --git a/builtins/core/lists/regexp.go b/builtins/core/lists/regexp.go index bd4deb606..8b57baf34 100644 --- a/builtins/core/lists/regexp.go +++ b/builtins/core/lists/regexp.go @@ -52,6 +52,11 @@ func cmdMatch(p *lang.Process) error { return aw.Close() } +const ( + _WITH_HEADING = true + _WITHOUT_HEADING = false +) + func cmdRegexp(p *lang.Process) (err error) { dt := p.Stdin.GetDataType() p.Stdout.SetDataType(dt) @@ -90,7 +95,10 @@ func cmdRegexp(p *lang.Process) (err error) { switch sRegex[0][0] { case 'm': - return regexMatch(p, rx, dt) + return regexMatch(p, rx, dt, _WITHOUT_HEADING) + + case 'M': + return regexMatch(p, rx, dt, _WITH_HEADING) case 's': if p.IsNot { @@ -170,14 +178,20 @@ func splitRegexDefault(regex []byte) (s []string, _ error) { // -------- regex functions -------- -func regexMatch(p *lang.Process, rx *regexp.Regexp, dt string) error { +func regexMatch(p *lang.Process, rx *regexp.Regexp, dt string, withHeading bool) error { aw, err := p.Stdout.WriteArray(dt) if err != nil { return err } - var count int - p.Stdin.ReadArray(p.Context, func(b []byte) { + var ( + count int + fn func([]byte) + ) + + callback := func(b []byte) { fn(b) } + + readArray := func(b []byte) { matched := rx.Match(b) if (matched && !p.IsNot) || (!matched && p.IsNot) { @@ -189,7 +203,27 @@ func regexMatch(p *lang.Process, rx *regexp.Regexp, dt string) error { } } - }) + } + + readHeading := func(b []byte) { + err = aw.Write(b) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + fn = readArray + } + + // this is a bit of a kludge to allow us to read the heading and run one + // type of function against it, but then process the rest of the array + // differently. The aim of this is to avoid having `if` blocks inside the + // `ReadArray()` loop. + if withHeading { + fn = readHeading + } else { + callback = readArray + } + p.Stdin.ReadArray(p.Context, callback) if p.HasCancelled() { return err diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index cc15b909f..f16e298c9 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -114,7 +114,7 @@ ### Match elements - ### Elements containing + #### Elements containing ``` » ja [monday..sunday] -> regexp 'm/(mon|fri|sun)day/' @@ -137,6 +137,17 @@ ] ``` + #### Include heading + + ``` + » ps -fe -> regexp 'M/murex/' + UID PID PPID C STIME TTY TIME CMD + 501 39631 39630 0 6:48pm ?? 0:04.31 -murex + 501 57496 17220 0 11:59pm ?? 0:02.90 ./murex + 501 41982 17219 0 10:53pm ttys000 0:39.73 -murex + 501 17220 17219 0 2:09pm ttys002 1:44.06 -murex + ``` + ### Substitute expression ``` @@ -152,12 +163,14 @@ ] ``` Flags: - f: output found expressions - (doesn't support bang prefix) - m: output elements that match expression - (supports bang prefix) - s: output all elements - substituting elements that match expression - (doesn't support bang prefix) + f: >- + output found expressions (doesn't support bang prefix) + m: >- + output elements that match expression (supports bang prefix) + M: >- + output first element (eg table headings), followed by any elements that match (supports bang prefix) + s: >- + output all elements, substituting elements that match expression (doesn't support bang prefix) Detail: |- `regexp` is data-type aware so will work against lists or arrays of whichever Murex data-type is passed to it via stdin and return the output in the diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index afe1a0da7..9a930b271 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -32,7 +32,7 @@ characters because those are inside the parenthesis. ### Match elements -### Elements containing +#### Elements containing ``` » ja [monday..sunday] -> regexp 'm/(mon|fri|sun)day/' @@ -55,6 +55,17 @@ characters because those are inside the parenthesis. ] ``` +#### Include heading + +``` +» ps -fe -> regexp 'M/murex/' +UID PID PPID C STIME TTY TIME CMD +501 39631 39630 0 6:48pm ?? 0:04.31 -murex +501 57496 17220 0 11:59pm ?? 0:02.90 ./murex +501 41982 17219 0 10:53pm ttys000 0:39.73 -murex +501 17220 17219 0 2:09pm ttys002 1:44.06 -murex +``` + ### Substitute expression ``` @@ -72,12 +83,14 @@ characters because those are inside the parenthesis. ## Flags +* `M` + output first element (eg table headings), followed by any elements that match (supports bang prefix) * `f` output found expressions (doesn't support bang prefix) * `m` output elements that match expression (supports bang prefix) * `s` - output all elements - substituting elements that match expression (doesn't support bang prefix) + output all elements, substituting elements that match expression (doesn't support bang prefix) ## Detail diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 8711335af..303ebb5fc 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -2,6 +2,6 @@ return } -define-force-tty-func hx +#define-force-tty-func hx summary hx "Helix: a post-modern text editor" diff --git a/version.svg b/version.svg index 9f5fd2032..975199ab3 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0693Version6.3.0693 +Version: 6.3.0699Version6.3.0699 From ec8a27b6154073d5993570825fc76ad2c332c4bf Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 5 Sep 2024 00:18:50 +0100 Subject: [PATCH 090/142] integration: orbstack --- app/app.go | 4 ++-- integrations/orbstack_darwin.mx | 20 ++++++++++++++++++++ version.svg | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 integrations/orbstack_darwin.mx diff --git a/app/app.go b/app/app.go index 59bf11c12..667dbe10b 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 699 + Revision = 701 Branch = "863/job-control" - BuildDate = "2024-09-05 00:06:37" + BuildDate = "2024-09-05 00:18:51" ) // Copyright is the copyright owner string diff --git a/integrations/orbstack_darwin.mx b/integrations/orbstack_darwin.mx new file mode 100644 index 000000000..2076fff53 --- /dev/null +++ b/integrations/orbstack_darwin.mx @@ -0,0 +1,20 @@ +if { which orb } then { + return +} + +autocomplete set orb %[ + { + DynamicDesc: '{ + config set proc strict-arrays false + exec orbctl @PARAMS --help -> tabulate --split-comma --map + }' + } +] + +autocomplete get orb -> autocomplete set orbctl + +define-force-tty-func orb +define-force-tty-func orbctl + +summary orb "OrbStack: K8s, Docker and Linux virtualization" +summary orbctl ${ runtime --summaries -> [orb] } \ No newline at end of file diff --git a/version.svg b/version.svg index 975199ab3..38708f949 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0699Version6.3.0699 +Version: 6.3.0701Version6.3.0701 From ded09cbc8f51a83e62d3e9aeaccea64932d91368 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 5 Sep 2024 08:43:38 +0100 Subject: [PATCH 091/142] `regexp`: support for headings & unicode separators --- app/app.go | 4 +- app/update-version.mx | 6 +- builtins/core/lists/match.go | 49 ++++++ builtins/core/lists/match_doc.yaml | 82 +++++++++ builtins/core/lists/match_test.go | 43 +++++ builtins/core/lists/regexp.go | 217 +----------------------- builtins/core/lists/regexp_doc.yaml | 100 ++--------- builtins/core/lists/regexp_functions.go | 124 ++++++++++++++ builtins/core/lists/regexp_params.go | 68 ++++++++ builtins/core/lists/regexp_test.go | 55 +++--- docs/commands/match.md | 2 +- docs/commands/regexp.md | 17 ++ integrations/orbstack_darwin.mx | 2 +- lang/parameters/get.go | 8 + version.svg | 2 +- 15 files changed, 435 insertions(+), 344 deletions(-) create mode 100644 builtins/core/lists/match.go create mode 100644 builtins/core/lists/match_doc.yaml create mode 100644 builtins/core/lists/match_test.go create mode 100644 builtins/core/lists/regexp_functions.go create mode 100644 builtins/core/lists/regexp_params.go diff --git a/app/app.go b/app/app.go index 667dbe10b..dc99e5187 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 701 + Revision = 706 Branch = "863/job-control" - BuildDate = "2024-09-05 00:18:51" + BuildDate = "2024-09-05 08:43:40" ) // Copyright is the copyright owner string diff --git a/app/update-version.mx b/app/update-version.mx index 4f8707aeb..70e3eede4 100755 --- a/app/update-version.mx +++ b/app/update-version.mx @@ -18,9 +18,9 @@ $branch = get_branch_name() $date = datetime(--in {now} --out "{go}2006-01-02 15:04:05") open $GLOBAL.APP_GO -> cast str \ --> regexp %(s/Revision\s+=\s+[0-9]+/Revision = $rev) \ --> regexp %(s#Branch\s+=\s+".*?"#Branch = "$branch"#) \ --> regexp %(s#BuildDate\s+=\s+".*?"#BuildDate = "$date"#) \ +-> regexp s %(Revision\s+=\s+[0-9]+) %(Revision = $rev) \ +-> regexp s %(Branch\s+=\s+".*?") %(Branch = "$branch") \ +-> regexp s %(BuildDate\s+=\s+".*?") %(BuildDate = "$date") \ -> set app_go $app_go |> $GLOBAL.APP_GO diff --git a/builtins/core/lists/match.go b/builtins/core/lists/match.go new file mode 100644 index 000000000..6ff78bd69 --- /dev/null +++ b/builtins/core/lists/match.go @@ -0,0 +1,49 @@ +package lists + +import ( + "bytes" + "errors" + + "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/types" +) + +func init() { + lang.DefineMethod("match", cmdMatch, types.ReadArray, types.WriteArray) + lang.DefineMethod("!match", cmdMatch, types.ReadArray, types.WriteArray) +} + +func cmdMatch(p *lang.Process) error { + dt := p.Stdin.GetDataType() + p.Stdout.SetDataType(dt) + + if err := p.ErrIfNotAMethod(); err != nil { + return err + } + + if p.Parameters.StringAll() == "" { + return errors.New("no parameters supplied") + } + + aw, err := p.Stdout.WriteArray(dt) + if err != nil { + return err + } + + p.Stdin.ReadArray(p.Context, func(b []byte) { + matched := bytes.Contains(b, p.Parameters.ByteAll()) + if (matched && !p.IsNot) || (!matched && p.IsNot) { + err = aw.Write(b) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + } + }) + + if p.HasCancelled() { + return err + } + + return aw.Close() +} diff --git a/builtins/core/lists/match_doc.yaml b/builtins/core/lists/match_doc.yaml new file mode 100644 index 000000000..781ff8ab3 --- /dev/null +++ b/builtins/core/lists/match_doc.yaml @@ -0,0 +1,82 @@ +- DocumentID: match + Title: >+ + `match` + CategoryID: commands + Summary: >- + Match an exact value in an array + Description: |- + `match` takes input from stdin and returns any array items / lines which + contain an exact match of the parameters supplied. + + When multiple parameters are supplied they are concatenated into the search + string and white space delimited. eg all three of the below are the same: + + ``` + match "a b c" + match a\sb\sc + match a b c + match a b c + ``` + + If you want to return everything except the search string then use `!match` + Usage: |- + Match every occurrence of search string + + ``` + -> match search string -> + ``` + + Match everything except search string + + ``` + -> !match search string -> + ``` + Examples: |- + ### Return matched + + Match **Wed** + + ``` + » ja [Monday..Friday] -> match Wed + [ + "Wednesday" + ] + ``` + + ### Ignore matched + + Match everything except **Wed** + + ``` + » ja [Monday..Friday] -> !match Wed + [ + "Monday", + "Tuesday", + "Thursday", + "Friday" + ] + ``` + Flags: + Detail: |- + `match` is data-type aware so will work against lists or arrays of whichever + Murex data-type is passed to it via stdin and return the output in the + same data-type. + Synonyms: + - match + - "!match" + - list.string + Related: + - a + - ja + - ta + - count + - 2darray + - append + - prepend + - suffix + - prefix + - jsplit + - msort + - pretty + - map + - regexp diff --git a/builtins/core/lists/match_test.go b/builtins/core/lists/match_test.go new file mode 100644 index 000000000..f0de4fea3 --- /dev/null +++ b/builtins/core/lists/match_test.go @@ -0,0 +1,43 @@ +package lists_test + +import ( + "testing" + + "github.com/lmorg/murex/test" +) + +func TestMatchPositive(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `ja: [Monday..Wednesday] -> match s`, + Stdout: `["Tuesday","Wednesday"]`, + }, + { + Block: `ja: [Monday..Wednesday] -> !match s`, + Stdout: `["Monday"]`, + }, + { + Block: `ja: [Monday..Wednesday] -> !match S`, + Stdout: `["Monday","Tuesday","Wednesday"]`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestMatchNegative(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `ja: [Monday..Wednesday] -> match S`, + Stderr: "no data returned\n", + ExitNum: 1, + }, + { + Block: `ja: [Monday..Wednesday] -> !match day`, + Stderr: "no data returned\n", + ExitNum: 1, + }, + } + + test.RunMurexTestsRx(tests, t) +} diff --git a/builtins/core/lists/regexp.go b/builtins/core/lists/regexp.go index 8b57baf34..8bef6cf49 100644 --- a/builtins/core/lists/regexp.go +++ b/builtins/core/lists/regexp.go @@ -1,7 +1,6 @@ package lists import ( - "bytes" "errors" "fmt" "regexp" @@ -11,47 +10,10 @@ import ( ) func init() { - lang.DefineMethod("match", cmdMatch, types.ReadArray, types.WriteArray) - lang.DefineMethod("!match", cmdMatch, types.ReadArray, types.WriteArray) lang.DefineMethod("regexp", cmdRegexp, types.ReadArray, types.WriteArray) lang.DefineMethod("!regexp", cmdRegexp, types.ReadArray, types.WriteArray) } -func cmdMatch(p *lang.Process) error { - dt := p.Stdin.GetDataType() - p.Stdout.SetDataType(dt) - - if err := p.ErrIfNotAMethod(); err != nil { - return err - } - - if p.Parameters.StringAll() == "" { - return errors.New("no parameters supplied") - } - - aw, err := p.Stdout.WriteArray(dt) - if err != nil { - return err - } - - p.Stdin.ReadArray(p.Context, func(b []byte) { - matched := bytes.Contains(b, p.Parameters.ByteAll()) - if (matched && !p.IsNot) || (!matched && p.IsNot) { - err = aw.Write(b) - if err != nil { - p.Stdin.ForceClose() - p.Done() - } - } - }) - - if p.HasCancelled() { - return err - } - - return aw.Close() -} - const ( _WITH_HEADING = true _WITHOUT_HEADING = false @@ -71,7 +33,7 @@ func cmdRegexp(p *lang.Process) (err error) { var sRegex []string if p.Parameters.Len() == 1 { - sRegex, err = splitRegexParams(p.Parameters.ByteAll()) + sRegex, err = splitRegexParams(p.Parameters.RuneAll()) if err != nil { return err } @@ -116,180 +78,3 @@ func cmdRegexp(p *lang.Process) (err error) { return errors.New("invalid regexp. Please use either match (m), substitute (s) or find (f)") } } - -func splitRegexParams(regex []byte) ([]string, error) { - if len(regex) < 2 { - return nil, fmt.Errorf("invalid regexp (too few characters) in: `%s`", string(regex)) - } - - switch regex[1] { - default: - return splitRegexDefault(regex) - - case '{': - return nil, fmt.Errorf("the `{` character is not supported for separating regex parameters in: `%s`", string(regex)) - //return splitRegexBraces(regex) - - case '\\': - return nil, fmt.Errorf("the `\\` character is not valid for separating regex parameters in: `%s`", string(regex)) - } -} - -func splitRegexDefault(regex []byte) (s []string, _ error) { - var ( - param []byte - escaped bool - token = regex[1] - ) - - for _, c := range regex { - switch c { - default: - if escaped { - param = append(param, '\\', c) - escaped = false - continue - } - param = append(param, c) - - case '\\': - if escaped { - param = append(param, '\\', c) - escaped = false - continue - } - escaped = true - - case token: - if escaped { - escaped = false - param = append(param, c) - continue - } - - s = append(s, string(param)) - param = []byte{} - } - } - s = append(s, string(param)) - - return -} - -// -------- regex functions -------- - -func regexMatch(p *lang.Process, rx *regexp.Regexp, dt string, withHeading bool) error { - aw, err := p.Stdout.WriteArray(dt) - if err != nil { - return err - } - - var ( - count int - fn func([]byte) - ) - - callback := func(b []byte) { fn(b) } - - readArray := func(b []byte) { - matched := rx.Match(b) - if (matched && !p.IsNot) || (!matched && p.IsNot) { - - count++ - err = aw.Write(b) - if err != nil { - p.Stdin.ForceClose() - p.Done() - } - - } - } - - readHeading := func(b []byte) { - err = aw.Write(b) - if err != nil { - p.Stdin.ForceClose() - p.Done() - } - fn = readArray - } - - // this is a bit of a kludge to allow us to read the heading and run one - // type of function against it, but then process the rest of the array - // differently. The aim of this is to avoid having `if` blocks inside the - // `ReadArray()` loop. - if withHeading { - fn = readHeading - } else { - callback = readArray - } - p.Stdin.ReadArray(p.Context, callback) - - if p.HasCancelled() { - return err - } - - if count == 0 { - return fmt.Errorf("nothing matched: %s", rx.String()) - } - - return aw.Close() -} - -func regexSubstitute(p *lang.Process, rx *regexp.Regexp, sRegex []string, dt string) error { - if len(sRegex) < 3 { - return fmt.Errorf("invalid regex: too few parameters\nexpecting s/find/substitute/ in: `%s`", p.Parameters.StringAll()) - } - - aw, err := p.Stdout.WriteArray(dt) - if err != nil { - return err - } - - sub := []byte(sRegex[2]) - - p.Stdin.ReadArray(p.Context, func(b []byte) { - err = aw.Write(rx.ReplaceAll(b, sub)) - if err != nil { - p.Stdin.ForceClose() - p.Done() - } - }) - - if p.HasCancelled() { - return err - } - - return aw.Close() -} - -func regexFind(p *lang.Process, rx *regexp.Regexp, dt string) error { - aw, err := p.Stdout.WriteArray(dt) - if err != nil { - return err - } - - p.Stdin.ReadArray(p.Context, func(b []byte) { - match := rx.FindAllStringSubmatch(string(b), -1) - for _, found := range match { - if len(found) > 1 { - - for i := 1; i < len(found); i++ { - err = aw.WriteString(found[i]) - if err != nil { - p.Stdin.ForceClose() - p.Done() - } - - } - - } - } - }) - - if p.HasCancelled() { - return err - } - - return aw.Close() -} diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index f16e298c9..34a86c866 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -1,101 +1,33 @@ -- DocumentID: match +- DocumentID: regexp Title: >+ - `match` + `regexp` CategoryID: commands Summary: >- - Match an exact value in an array + Regexp tools for arrays / lists of strings Description: |- - `match` takes input from stdin and returns any array items / lines which - contain an exact match of the parameters supplied. - - When multiple parameters are supplied they are concatenated into the search - string and white space delimited. eg all three of the below are the same: - - ``` - match "a b c" - match a\sb\sc - match a b c - match a b c - ``` - - If you want to return everything except the search string then use `!match` + `regexp` provides a few tools for text matching and manipulation against an + array or list of strings - thus `regexp` is Murex data-type aware. Usage: |- - Match every occurrence of search string - - ``` - -> match search string -> - ``` - - Match everything except search string - ``` - -> !match search string -> + -> regexp expression -> ``` - Examples: |- - ### Return matched - Match **Wed** + Where _expression_ consists of the following ``` - » ja [Monday..Friday] -> match Wed - [ - "Wednesday" - ] + function separator pattern [ separator parameter2 ] ``` - ### Ignore matched + * _function_: single alphabetic character (eg, `m`, `s` or `f`) + + * _separator_: typically a single unicode character (eg, `/`, `#`, `▷`, `🙂`) + however `regexp` _parameters_ can also be passed as shell parameters (eg + `s search replace`) - Match everything except **Wed** + * _pattern_: regexp pattern - ``` - » ja [Monday..Friday] -> !match Wed - [ - "Monday", - "Tuesday", - "Thursday", - "Friday" - ] - ``` - Flags: - Detail: |- - `match` is data-type aware so will work against lists or arrays of whichever - Murex data-type is passed to it via stdin and return the output in the - same data-type. - Synonyms: - - match - - "!match" - - list.string - Related: - - a - - ja - - ta - - count - - 2darray - - append - - prepend - - suffix - - prefix - - jsplit - - msort - - pretty - - map - - regexp - - - -- DocumentID: regexp - Title: >+ - `regexp` - CategoryID: commands - Summary: >- - Regexp tools for arrays / lists of strings - Description: |- - `regexp` provides a few tools for text matching and manipulation against an - array or list of strings - thus `regexp` is Murex data-type aware. - Usage: |- - ``` - -> regexp expression -> - ``` + * _parameter2_: any extra operations to perform. For example a string to + replace matched patterns when using the regexp substitution function Examples: |- ### Find elements diff --git a/builtins/core/lists/regexp_functions.go b/builtins/core/lists/regexp_functions.go new file mode 100644 index 000000000..2f8de0a71 --- /dev/null +++ b/builtins/core/lists/regexp_functions.go @@ -0,0 +1,124 @@ +package lists + +import ( + "fmt" + "regexp" + + "github.com/lmorg/murex/lang" +) + +func regexMatch(p *lang.Process, rx *regexp.Regexp, dt string, withHeading bool) error { + aw, err := p.Stdout.WriteArray(dt) + if err != nil { + return err + } + + var ( + count int + fn func([]byte) + ) + + callback := func(b []byte) { fn(b) } + + readArray := func(b []byte) { + matched := rx.Match(b) + if (matched && !p.IsNot) || (!matched && p.IsNot) { + + count++ + err = aw.Write(b) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + + } + } + + readHeading := func(b []byte) { + err = aw.Write(b) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + fn = readArray + } + + // this is a bit of a kludge to allow us to read the heading and run one + // type of function against it, but then process the rest of the array + // differently. The aim of this is to avoid having `if` blocks inside the + // `ReadArray()` loop. + if withHeading { + fn = readHeading + } else { + callback = readArray + } + p.Stdin.ReadArray(p.Context, callback) + + if p.HasCancelled() { + return err + } + + if count == 0 { + return fmt.Errorf("nothing matched: %s", rx.String()) + } + + return aw.Close() +} + +func regexSubstitute(p *lang.Process, rx *regexp.Regexp, sRegex []string, dt string) error { + if len(sRegex) < 3 { + return fmt.Errorf("invalid regex: too few parameters\nexpecting s/find/substitute/ in: `%s`", p.Parameters.StringAll()) + } + + aw, err := p.Stdout.WriteArray(dt) + if err != nil { + return err + } + + sub := []byte(sRegex[2]) + + p.Stdin.ReadArray(p.Context, func(b []byte) { + err = aw.Write(rx.ReplaceAll(b, sub)) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + }) + + if p.HasCancelled() { + return err + } + + return aw.Close() +} + +func regexFind(p *lang.Process, rx *regexp.Regexp, dt string) error { + aw, err := p.Stdout.WriteArray(dt) + if err != nil { + return err + } + + p.Stdin.ReadArray(p.Context, func(b []byte) { + match := rx.FindAllStringSubmatch(string(b), -1) + for _, found := range match { + if len(found) > 1 { + + for i := 1; i < len(found); i++ { + err = aw.WriteString(found[i]) + if err != nil { + p.Stdin.ForceClose() + p.Done() + } + + } + + } + } + }) + + if p.HasCancelled() { + return err + } + + return aw.Close() +} diff --git a/builtins/core/lists/regexp_params.go b/builtins/core/lists/regexp_params.go new file mode 100644 index 000000000..31de02c55 --- /dev/null +++ b/builtins/core/lists/regexp_params.go @@ -0,0 +1,68 @@ +package lists + +import ( + "errors" + "fmt" +) + +func splitRegexParams(regex []rune) ([]string, error) { + if len(regex) < 2 { + return nil, fmt.Errorf("invalid regexp (too few characters) in: `%s`", string(regex)) + } + + switch regex[1] { + default: + return splitRegexDefault(regex) + + case '{': + return splitRegexBraces(regex) + + case '\\': + return nil, fmt.Errorf("the `\\` character is not valid for separating regex parameters in: `%s`", string(regex)) + } +} + +func splitRegexDefault(regex []rune) (s []string, _ error) { + var ( + param []rune + escaped bool + token = regex[1] + ) + + for _, c := range regex { + switch c { + default: + if escaped { + param = append(param, '\\', c) + escaped = false + continue + } + param = append(param, c) + + case '\\': + if escaped { + param = append(param, '\\', c) + escaped = false + continue + } + escaped = true + + case token: + if escaped { + escaped = false + param = append(param, c) + continue + } + + s = append(s, string(param)) + param = []rune{} + } + } + s = append(s, string(param)) + + return +} + +func splitRegexBraces(regex []rune) ([]string, error) { + return nil, errors.New("TODO") +} diff --git a/builtins/core/lists/regexp_test.go b/builtins/core/lists/regexp_test.go index c2298a626..64b4d3ec4 100644 --- a/builtins/core/lists/regexp_test.go +++ b/builtins/core/lists/regexp_test.go @@ -6,42 +6,6 @@ import ( "github.com/lmorg/murex/test" ) -func TestMatchPositive(t *testing.T) { - tests := []test.MurexTest{ - { - Block: `ja: [Monday..Wednesday] -> match s`, - Stdout: `["Tuesday","Wednesday"]`, - }, - { - Block: `ja: [Monday..Wednesday] -> !match s`, - Stdout: `["Monday"]`, - }, - { - Block: `ja: [Monday..Wednesday] -> !match S`, - Stdout: `["Monday","Tuesday","Wednesday"]`, - }, - } - - test.RunMurexTests(tests, t) -} - -func TestMatchNegative(t *testing.T) { - tests := []test.MurexTest{ - { - Block: `ja: [Monday..Wednesday] -> match S`, - Stderr: "no data returned\n", - ExitNum: 1, - }, - { - Block: `ja: [Monday..Wednesday] -> !match day`, - Stderr: "no data returned\n", - ExitNum: 1, - }, - } - - test.RunMurexTestsRx(tests, t) -} - func TestRegexpMatchPositive(t *testing.T) { tests := []test.MurexTest{ { @@ -249,3 +213,22 @@ func TestRegexpErrors(t *testing.T) { test.RunMurexTestsRx(tests, t) } + +func TestRegexpRuneSeparator(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `ja: [Monday..Wednesday] -> regexp %(s🙂day🙂night)`, + Stdout: `["Monnight","Tuesnight","Wednesnight"]`, + }, + { + Block: `ja: [Monday..Wednesday] -> regexp %(s▷day▷night)`, + Stdout: `["Monnight","Tuesnight","Wednesnight"]`, + }, + { + Block: `ja: [Monday..Wednesday] -> regexp %(s:day:night)`, + Stdout: `["Monnight","Tuesnight","Wednesnight"]`, + }, + } + + test.RunMurexTests(tests, t) +} \ No newline at end of file diff --git a/docs/commands/match.md b/docs/commands/match.md index 42a1ddf98..7b4300371 100644 --- a/docs/commands/match.md +++ b/docs/commands/match.md @@ -106,4 +106,4 @@ same data-type.
-This document was generated from [builtins/core/lists/regexp_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/lists/regexp_doc.yaml). \ No newline at end of file +This document was generated from [builtins/core/lists/match_doc.yaml](https://github.com/lmorg/murex/blob/master/builtins/core/lists/match_doc.yaml). \ No newline at end of file diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 9a930b271..8c2cf954a 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -13,6 +13,23 @@ array or list of strings - thus `regexp` is Murex data-type aware. -> regexp expression -> ``` +Where _expression_ consists of the following + +``` +function separator pattern [ separator parameter2 ] +``` + +* _function_: single alphabetic character (eg, `m`, `s` or `f`) + +* _separator_: typically a single unicode character (eg, `/`, `#`, `▷`, `🙂`) + however `regexp` _parameters_ can also be passed as shell parameters (eg + `s search replace`) + +* _pattern_: regexp pattern + +* _parameter2_: any extra operations to perform. For example a string to + replace matched patterns when using the regexp substitution function + ## Examples ### Find elements diff --git a/integrations/orbstack_darwin.mx b/integrations/orbstack_darwin.mx index 2076fff53..b8c364484 100644 --- a/integrations/orbstack_darwin.mx +++ b/integrations/orbstack_darwin.mx @@ -16,5 +16,5 @@ autocomplete get orb -> autocomplete set orbctl define-force-tty-func orb define-force-tty-func orbctl -summary orb "OrbStack: K8s, Docker and Linux virtualization" +summary orb "OrbStack: K8s, Docker and Linux virtualization" summary orbctl ${ runtime --summaries -> [orb] } \ No newline at end of file diff --git a/lang/parameters/get.go b/lang/parameters/get.go index 703068a28..65751b778 100644 --- a/lang/parameters/get.go +++ b/lang/parameters/get.go @@ -59,6 +59,14 @@ func (p *Parameters) RuneArray() [][]rune { return r } +// RuneAll returns all parameters as one space-delimited array of runes +func (p *Parameters) RuneAll() []rune { + p.mutex.RLock() + defer p.mutex.RUnlock() + + return []rune(strings.Join(p.params, " ")) +} + // String gets a single parameter as string func (p *Parameters) String(pos int) (string, error) { p.mutex.RLock() diff --git a/version.svg b/version.svg index 38708f949..a94762a7f 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0701Version6.3.0701 +Version: 6.3.0706Version6.3.0706 From 382e72f993bd50f063ef2c4aa22ff1dc6198c838 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 5 Sep 2024 22:02:49 +0100 Subject: [PATCH 092/142] job-control: session archive before code removal --- app/app.go | 4 +- builtins/core/io/g_doc.yaml | 10 +- builtins/core/lists/regexp_doc.yaml | 157 +++++++++++++++++++++ builtins/core/processes/bgfg_unix.go | 4 +- docs/commands/g.md | 10 +- docs/commands/regexp.md | 157 +++++++++++++++++++++ lang/exec.go | 6 +- lang/exec_js.go | 4 +- lang/exec_plan9.go | 4 +- lang/exec_unix.go | 70 +++++---- lang/exec_windows.go | 4 +- main.go | 2 +- shell/session/session_unix.go | 56 ++++++-- shell/signal_handler/sigfns/sigfns_unix.go | 2 +- shell/signal_handler/signals_unix.go | 1 + version.svg | 2 +- 16 files changed, 424 insertions(+), 69 deletions(-) diff --git a/app/app.go b/app/app.go index dc99e5187..4b8eb11ce 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 706 + Revision = 738 Branch = "863/job-control" - BuildDate = "2024-09-05 08:43:40" + BuildDate = "2024-09-05 22:02:51" ) // Copyright is the copyright owner string diff --git a/builtins/core/io/g_doc.yaml b/builtins/core/io/g_doc.yaml index 1d81063ef..f582f0965 100644 --- a/builtins/core/io/g_doc.yaml +++ b/builtins/core/io/g_doc.yaml @@ -73,7 +73,7 @@ Detail: |- ### Pattern Reference - Murex globbing is based on [Go's stdlib Match library](https://pkg.go.dev/path/filepath#Match) + Murex globbing is based on [Go's stdlib Match library](https://pkg.go.dev/path/filepath#Match). #### pattern @@ -97,14 +97,10 @@ ### Inverse Matches If you want to exclude any matches based on wildcards, rather than include - them, then you can use the bang prefix. eg + them, then you can use the bang prefix. For example, here we use an asterisks + to exclude everything: ``` - » g READ* - [ - "README.md" - ] - » !g * Error in `!g` (1,1): No data returned. ``` diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index 34a86c866..c9fe83f03 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -104,9 +104,166 @@ s: >- output all elements, substituting elements that match expression (doesn't support bang prefix) Detail: |- + ### Data Types + `regexp` is data-type aware so will work against lists or arrays of whichever Murex data-type is passed to it via stdin and return the output in the same data-type. + + ### Inverse Matches + + If you want to exclude any matches based on wildcards, rather than include + them, then you can use the bang prefix. For example if you wanted to exclude + any days of the week that contained the letter `s`: + + ``` + » %[Monday..Friday] -> !regexp m/s/ + [ + "Monday", + "Friday" + ] + ``` + + ## Expression Syntax + + Murex regex expressions are based on [Go's stdlib regexp library](https://pkg.go.dev/regexp). + + > The syntax of the regular expressions accepted is the same general syntax + > used by Perl, Python, and other languages. More precisely, it is the syntax + > accepted by RE2 and described at https://golang.org/s/re2syntax, except for + > `\C`. + > + > The regexp implementation provided by this package is guaranteed to run in + > time linear in the size of the input. (This is a property not guaranteed by + > most open source implementations of regular expressions.) For more + > information about this property, see https://swtch.com/~rsc/regexp/regexp1.html + > or any book about automata theory. + > + > All characters are UTF-8-encoded code points. Each byte of an invalid UTF-8 + > sequence is treated as if it encoded as **U+FFFD**. + + ### Single characters + + . any character, possibly including newline (flag s=true) + [xyz] character class + [^xyz] negated character class + \d Perl character class + \D negated Perl character class + [[:alpha:]] ASCII character class + [[:^alpha:]] negated ASCII character class + \pN Unicode character class (one-letter name) + \p{Greek} Unicode character class + \PN negated Unicode character class (one-letter name) + \P{Greek} negated Unicode character class + + ### Composites + + xy x followed by y + x|y x or y (prefer x) + + ### Repetitions + + x* zero or more x, prefer more + x+ one or more x, prefer more + x? zero or one x, prefer one + x{n,m} n or n+1 or ... or m x, prefer more + x{n,} n or more x, prefer more + x{n} exactly n x + x*? zero or more x, prefer fewer + x+? one or more x, prefer fewer + x?? zero or one x, prefer zero + x{n,m}? n or n+1 or ... or m x, prefer fewer + x{n,}? n or more x, prefer fewer + x{n}? exactly n x + + Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject + forms that create a minimum or maximum repetition count above 1000. Unlimited + repetitions are not subject to this restriction. + + ### Grouping + + (re) numbered capturing group (submatch) + (?Pre) named & numbered capturing group (submatch) + (?re) named & numbered capturing group (submatch) + (?:re) non-capturing group + (?flags) set flags within current group; non-capturing + (?flags:re) set flags during re; non-capturing + + Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are: + + i case-insensitive (default false) + m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false) + s let . match \n (default false) + U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false) + + ### Empty strings + + ^ at beginning of text or line (flag m=true) + $ at end of text (like \z not \Z) or line (flag m=true) + \A at beginning of text + \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) + \B not at ASCII word boundary + \z at end of text + + ### Escape sequences + + \a bell (== \007) + \f form feed (== \014) + \t horizontal tab (== \011) + \n newline (== \012) + \r carriage return (== \015) + \v vertical tab character (== \013) + \* literal *, for any punctuation character * + \123 octal character code (up to three digits) + \x7F hex character code (exactly two digits) + \x{10FFFF} hex character code + \Q...\E literal text ... even if ... has punctuation + + ### Character class elements + + x single character + A-Z character range (inclusive) + \d Perl character class + [:foo:] ASCII character class foo + \p{Foo} Unicode character class Foo + \pF Unicode character class F (one-letter name) + + ### Named character classes as character class elements + + [\d] digits (== \d) + [^\d] not digits (== \D) + [\D] not digits (== \D) + [^\D] not not digits (== \d) + [[:name:]] named ASCII class inside character class (== [:name:]) + [^[:name:]] named ASCII class inside negated character class (== [:^name:]) + [\p{Name}] named Unicode property inside character class (== \p{Name}) + [^\p{Name}] named Unicode property inside negated character class (== \P{Name}) + + ### Perl character classes (all ASCII-only) + + \d digits (== [0-9]) + \D not digits (== [^0-9]) + \s whitespace (== [\t\n\f\r ]) + \S not whitespace (== [^\t\n\f\r ]) + \w word characters (== [0-9A-Za-z_]) + \W not word characters (== [^0-9A-Za-z_]) + + ### ASCII character classes + + [[:alnum:]] alphanumeric (== [0-9A-Za-z]) + [[:alpha:]] alphabetic (== [A-Za-z]) + [[:ascii:]] ASCII (== [\x00-\x7F]) + [[:blank:]] blank (== [\t ]) + [[:cntrl:]] control (== [\x00-\x1F\x7F]) + [[:digit:]] digits (== [0-9]) + [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]) + [[:lower:]] lower case (== [a-z]) + [[:print:]] printable (== [ -~] == [ [:graph:]]) + [[:punct:]] punctuation (== [!-/:-@[-`{-~]) + [[:space:]] whitespace (== [\t\n\v\f\r ]) + [[:upper:]] upper case (== [A-Z]) + [[:word:]] word characters (== [0-9A-Za-z_]) + [[:xdigit:]] hex digit (== [0-9A-Fa-f]) Synonyms: - regexp - "!regexp" diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index 863dac248..c2da0b6fa 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -64,8 +64,8 @@ func cmdForeground(p *lang.Process) error { f.State.Set(state.Executing) if f.SystemProcess.External() { - if f.SystemProcess.ForcedTTY() { - lang.UnixPidToFg(f.SystemProcess.Pid()) + if p.SystemProcess.ForcedTTY() { + lang.UnixPidToFg(f) } err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { diff --git a/docs/commands/g.md b/docs/commands/g.md index 1504d49a3..25d0bcc90 100644 --- a/docs/commands/g.md +++ b/docs/commands/g.md @@ -78,7 +78,7 @@ g [aeiou]*/* ### Pattern Reference -Murex globbing is based on [Go's stdlib Match library](https://pkg.go.dev/path/filepath#Match) +Murex globbing is based on [Go's stdlib Match library](https://pkg.go.dev/path/filepath#Match). #### pattern @@ -102,14 +102,10 @@ Murex globbing is based on [Go's stdlib Match library](https://pkg.go.dev/path/f ### Inverse Matches If you want to exclude any matches based on wildcards, rather than include -them, then you can use the bang prefix. eg +them, then you can use the bang prefix. For example, here we use an asterisks +to exclude everything: ``` -» g READ* -[ - "README.md" -] - » !g * Error in `!g` (1,1): No data returned. ``` diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 8c2cf954a..06a422ccd 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -111,10 +111,167 @@ UID PID PPID C STIME TTY TIME CMD ## Detail +### Data Types + `regexp` is data-type aware so will work against lists or arrays of whichever Murex data-type is passed to it via stdin and return the output in the same data-type. +### Inverse Matches + +If you want to exclude any matches based on wildcards, rather than include +them, then you can use the bang prefix. For example if you wanted to exclude +any days of the week that contained the letter `s`: + +``` +» %[Monday..Friday] -> !regexp m/s/ +[ + "Monday", + "Friday" +] +``` + +## Expression Syntax + +Murex regex expressions are based on [Go's stdlib regexp library](https://pkg.go.dev/regexp). + +> The syntax of the regular expressions accepted is the same general syntax +> used by Perl, Python, and other languages. More precisely, it is the syntax +> accepted by RE2 and described at https://golang.org/s/re2syntax, except for +> `\C`. +> +> The regexp implementation provided by this package is guaranteed to run in +> time linear in the size of the input. (This is a property not guaranteed by +> most open source implementations of regular expressions.) For more +> information about this property, see https://swtch.com/~rsc/regexp/regexp1.html +> or any book about automata theory. +> +> All characters are UTF-8-encoded code points. Each byte of an invalid UTF-8 +> sequence is treated as if it encoded as **U+FFFD**. + +### Single characters + + . any character, possibly including newline (flag s=true) + [xyz] character class + [^xyz] negated character class + \d Perl character class + \D negated Perl character class + [[:alpha:]] ASCII character class + [[:^alpha:]] negated ASCII character class + \pN Unicode character class (one-letter name) + \p{Greek} Unicode character class + \PN negated Unicode character class (one-letter name) + \P{Greek} negated Unicode character class + +### Composites + + xy x followed by y + x|y x or y (prefer x) + +### Repetitions + + x* zero or more x, prefer more + x+ one or more x, prefer more + x? zero or one x, prefer one + x{n,m} n or n+1 or ... or m x, prefer more + x{n,} n or more x, prefer more + x{n} exactly n x + x*? zero or more x, prefer fewer + x+? one or more x, prefer fewer + x?? zero or one x, prefer zero + x{n,m}? n or n+1 or ... or m x, prefer fewer + x{n,}? n or more x, prefer fewer + x{n}? exactly n x + +Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject +forms that create a minimum or maximum repetition count above 1000. Unlimited +repetitions are not subject to this restriction. + +### Grouping + + (re) numbered capturing group (submatch) + (?Pre) named & numbered capturing group (submatch) + (?re) named & numbered capturing group (submatch) + (?:re) non-capturing group + (?flags) set flags within current group; non-capturing + (?flags:re) set flags during re; non-capturing + + Flag syntax is xyz (set) or -xyz (clear) or xy-z (set xy, clear z). The flags are: + + i case-insensitive (default false) + m multi-line mode: ^ and $ match begin/end line in addition to begin/end text (default false) + s let . match \n (default false) + U ungreedy: swap meaning of x* and x*?, x+ and x+?, etc (default false) + +### Empty strings + + ^ at beginning of text or line (flag m=true) + $ at end of text (like \z not \Z) or line (flag m=true) + \A at beginning of text + \b at ASCII word boundary (\w on one side and \W, \A, or \z on the other) + \B not at ASCII word boundary + \z at end of text + +### Escape sequences + + \a bell (== \007) + \f form feed (== \014) + \t horizontal tab (== \011) + \n newline (== \012) + \r carriage return (== \015) + \v vertical tab character (== \013) + \* literal *, for any punctuation character * + \123 octal character code (up to three digits) + \x7F hex character code (exactly two digits) + \x{10FFFF} hex character code + \Q...\E literal text ... even if ... has punctuation + +### Character class elements + + x single character + A-Z character range (inclusive) + \d Perl character class + [:foo:] ASCII character class foo + \p{Foo} Unicode character class Foo + \pF Unicode character class F (one-letter name) + +### Named character classes as character class elements + + [\d] digits (== \d) + [^\d] not digits (== \D) + [\D] not digits (== \D) + [^\D] not not digits (== \d) + [[:name:]] named ASCII class inside character class (== [:name:]) + [^[:name:]] named ASCII class inside negated character class (== [:^name:]) + [\p{Name}] named Unicode property inside character class (== \p{Name}) + [^\p{Name}] named Unicode property inside negated character class (== \P{Name}) + +### Perl character classes (all ASCII-only) + + \d digits (== [0-9]) + \D not digits (== [^0-9]) + \s whitespace (== [\t\n\f\r ]) + \S not whitespace (== [^\t\n\f\r ]) + \w word characters (== [0-9A-Za-z_]) + \W not word characters (== [^0-9A-Za-z_]) + +### ASCII character classes + + [[:alnum:]] alphanumeric (== [0-9A-Za-z]) + [[:alpha:]] alphabetic (== [A-Za-z]) + [[:ascii:]] ASCII (== [\x00-\x7F]) + [[:blank:]] blank (== [\t ]) + [[:cntrl:]] control (== [\x00-\x1F\x7F]) + [[:digit:]] digits (== [0-9]) + [[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]) + [[:lower:]] lower case (== [a-z]) + [[:print:]] printable (== [ -~] == [ [:graph:]]) + [[:punct:]] punctuation (== [!-/:-@[-`{-~]) + [[:space:]] whitespace (== [\t\n\v\f\r ]) + [[:upper:]] upper case (== [A-Z]) + [[:word:]] word characters (== [0-9A-Za-z_]) + [[:xdigit:]] hex digit (== [0-9A-Fa-f]) + ## Synonyms * `regexp` diff --git a/lang/exec.go b/lang/exec.go index 36363aec7..90c29c419 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -78,7 +78,9 @@ func execForkFallback(p *Process, argv []string) error { } err := cmd.Process.Signal(syscall.SIGTERM) - UnixPidToFg(0) + if p.SystemProcess.ForcedTTY() { + UnixPidToFg(nil) + } if err != nil { if err.Error() == os.ErrProcessDone.Error() { return @@ -128,7 +130,7 @@ func execForkFallback(p *Process, argv []string) error { if p.Stdout.IsTTY() { // If Stdout is a TTY then set the appropriate syscalls to allow the calling program to own the TTY.... - cmd.SysProcAttr = osSysProcAttr(int(p.Stdout.File().Fd())) + cmd.SysProcAttr = unixProcAttrFauxTTY(int(p.Stdout.File().Fd())) cmd.Stdout = p.Stdout.File() //} } else { diff --git a/lang/exec_js.go b/lang/exec_js.go index e7403afa8..0fc5e2ad1 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -11,8 +11,8 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func osSysProcAttr(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { return nil } -func UnixPidToFg(_ int) {} +func UnixPidToFg(_ *Process) {} diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index 93fc1c580..dd84927b8 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -11,8 +11,8 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func osSysProcAttr(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { return nil } -func UnixPidToFg(_ int) {} +func UnixPidToFg(_ *Process) {} diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 2daeef143..61b1817df 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -18,10 +18,10 @@ import ( ) func osExecFork(p *Process, argv []string) error { - if !session.UnixIsSession() { - debug.Logf("!!! session not defined, falling back to non-unix ttys") - return execForkFallback(p, argv) - } + //if !session.UnixIsSession() { + // debug.Logf("!!! session not defined, falling back to non-unix ttys") + // return execForkFallback(p, argv) + //} if p.HasCancelled() { return nil @@ -43,7 +43,7 @@ func osExecFork(p *Process, argv []string) error { } p.State.Set(state.Executing) - unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, unixProcAttr(p.Envs)) + unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, unixProcAttrRealTTY(p.Envs)) if err != nil { return fmt.Errorf("failed fork in os.StartProcess -> osExecFork()...\n%s\nargv: %s", err.Error(), @@ -53,8 +53,8 @@ func osExecFork(p *Process, argv []string) error { sysProc := sysProcUnixT{p: unixProcess} p.SystemProcess.Set(&sysProc) - - UnixPidToFg(sysProc.p.Pid) + defer setsid() + UnixPidToFg(p) return sysProc.wait() /*if err != nil { //if !strings.HasPrefix(err.Error(), "signal:") { @@ -88,33 +88,46 @@ func (sp *sysProcUnixT) wait() error { sp.mutex.Lock() sp.state = state sp.mutex.Unlock() - - /*if state.Sys().(syscall.WaitStatus).Stopped() { - syscallErr := syscall.Kill(syscall.Getpid(), syscall.SIGTSTP) - if err != nil { - return syscallErr - } - }*/ return err } // UnixPidToFg brings a UNIX process to the foreground. -// If pid == 0 then UnixPidToFg will assume Murex Pid instead. -func UnixPidToFg(pid int) { - var err error +// If p == nil then UnixPidToFg will assume Murex Pid instead. +func UnixPidToFg(p *Process) { + var ( + pid int + err error + ) + + if p == nil { // Put Murex in the foreground + pid, err = syscall.Getpgid(unix.Getpid()) + if err != nil { + debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) + pid = syscall.Getpid() + } - pid, err = syscall.Getpgid(unix.Getpid()) - if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) - pid = syscall.Getpid() + // This is only required because some badly behaving programs run + // setsid() themselves despite not technically needing to be a session + // leader eg shell. + syscall.Setsid() + + } else { // Put a system process in the foreground + pid = p.SystemProcess.Pid() + // Check if its system process, if not, then there's no point proceeding + if pid <= 0 { + return + } } err = unixPidToFg(pid, int(os.Stdin.Fd())) if err == nil { - // success, no need to retry + // Success, no need to retry with a different file descriptor return } + // fallback is to use /dev/tty. This seems the default recommendation in a + // lot of the example code and documentation on this topic but it still + // feels "wrong" not to at least try os.Stdin first. err = unixPidToFg(pid, int(session.UnixTTY().Fd())) if err != nil { debug.Logf("!!! UnixPidToFg(%d)->session.UnixTTY(): %s", pid, err.Error()) @@ -132,7 +145,7 @@ func unixPidToFg(pid int, tty int) error { ///// -func osSysProcAttr(fd int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY(fd int) *syscall.SysProcAttr { return &syscall.SysProcAttr{ //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, @@ -151,11 +164,11 @@ func osSysProcAttr(fd int) *syscall.SysProcAttr { // Unlike Setctty, in this case Ctty must be a descriptor // number in the parent process. //Foreground: true, - //Pgid: 0, // Child's process group ID if Setpgid. + //Pgid: 0, // Child's process group ID if Setpgid. } } -func unixProcAttr(envs []string) *os.ProcAttr { +func unixProcAttrRealTTY(envs []string) *os.ProcAttr { return &os.ProcAttr{ //Files: []*os.File{session.UnixTTY(), session.UnixTTY(), session.UnixTTY()}, Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, @@ -182,3 +195,10 @@ func unixProcAttr(envs []string) *os.ProcAttr { }, } } + +func setsid() { + _, err := syscall.Setsid() + if err != nil { + debug.Logf("!!! setsid()->syscall.Setsid() failed: %s", err.Error()) + } +} diff --git a/lang/exec_windows.go b/lang/exec_windows.go index fdcdde312..feedcbde3 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -17,8 +17,8 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func osSysProcAttr(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { return nil } -func UnixPidToFg(_ int) {} +func UnixPidToFg(_ *Process) {} diff --git a/main.go b/main.go index 60306b1ee..0d3adef09 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ //go:build !js // +build !js -//go:generate go build golang.org/x/tools/cmd/stringer +//go:generate go build -v golang.org/x/tools/cmd/stringer package main diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index 6fe70814e..8defbf3b7 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -17,40 +17,66 @@ var ( ) func UnixSetSid() { + var err error + debug.Enabled = true debug.Log("!!! Entering UnixSetSid()") - var err error + // Opening /dev/tty feels like a bit of a kludge when we already know + // the tty of stdin. However we often see the following error when + // attempting to tcsetpgrp the file descriptor of stdin: + // + // inappropriate ioctl for device + // + // Where as opening /dev/tty and using that file descriptor resolves + // that error. + tty, err = os.Open(`/dev/tty`) + if err != nil { + debug.Logf("!!! UnixSetSid()->os.Open(`/dev/tty`) failed: %s", err.Error()) + } else { + debug.Log("!!! UnixSetSid()->os.Open(`/dev/tty`) success") + } + pid := os.Getpid() + //sid, _ := syscall.Getsid(pid) + //if syscall.Getpgrp() == sid { + // return + //} + // create a new group err = syscall.Setpgid(pid, os.Getppid()) if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Setpgid() failed: %s", err.Error()) + debug.Logf("!!! UnixSetSid()->syscall.Setpgid():1 failed: %s", err.Error()) } // Create a new session unixSid, err = syscall.Setsid() if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Setsid() failed: %s", err.Error()) + debug.Logf("!!! UnixSetSid()->syscall.Setsid():1 failed: %s", err.Error()) } - // Opening /dev/tty feels like a bit of a kludge when we already know - // the tty of stdin. However we often see the following error when - // attempting to tcsetpgrp the file descriptor of stdin: - // - // inappropriate ioctl for device - // - // Where as opening /dev/tty and using that file descriptor resolves - // that error. - tty, err = os.Open(`/dev/tty`) + // create a new group + err = syscall.Setpgid(pid, pid) if err != nil { - debug.Logf("!!! UnixSetSid()->os.Open(`/dev/tty`) failed: %s", err.Error()) - } else { - debug.Log("!!! UnixSetSid()->os.Open(`/dev/tty`) success") + debug.Logf("!!! UnixSetSid()->syscall.Setpgid():2 failed: %s", err.Error()) + } + + // Create a new session + unixSid, err = syscall.Setsid() + if err != nil { + debug.Logf("!!! UnixSetSid()->syscall.Setsid():2 failed: %s", err.Error()) } signalhandler.Register(true) + + pgid, err := syscall.Getpgid(pid) + debug.Logf("pid: %d, ppid: %d, pgid: %d, err: %v", pid, os.Getppid(), pgid, err) + pgrp := syscall.Getpgrp() + debug.Logf("pid: %d, ppid: %d, pgid: %d, err: --", pid, os.Getppid(), pgrp) + sid, err := syscall.Getsid(pid) + debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err) + } func UnixIsSession() bool { diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 5d595917b..a91169352 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -32,7 +32,7 @@ func returnFromSigtstp(p *lang.Process) { p.State.Set(state.Stopped) if p.SystemProcess.ForcedTTY() { - lang.UnixPidToFg(0) + lang.UnixPidToFg(nil) } //debug.Log("returnFromSigtstp:1", p.Name.String(), p.Parameters.StringAll()) diff --git a/shell/signal_handler/signals_unix.go b/shell/signal_handler/signals_unix.go index 98eaaf010..b1814e13a 100644 --- a/shell/signal_handler/signals_unix.go +++ b/shell/signal_handler/signals_unix.go @@ -42,6 +42,7 @@ func EventLoop(interactive bool) { func Register(interactive bool) { if interactive { // Interactive, so we will handle stop + signal.Reset(syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP, syscall.SIGCHLD) signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) } else { diff --git a/version.svg b/version.svg index a94762a7f..c29ae2c31 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0706Version6.3.0706 +Version: 6.3.0738Version6.3.0738 From 3514e8bb95efbd63f2c0a96f16f74be8a354ce08 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 01:45:07 +0100 Subject: [PATCH 093/142] #863 job-control: --setsid flag --- app/app.go | 4 +- builtins/core/processes/bgfg_unix.go | 6 +- .../events/onSignalReceived/signal_posix.go | 8 +- flags.go | 31 +++--- lang/exec.go | 9 +- lang/exec_js.go | 2 +- lang/exec_plan9.go | 2 +- lang/exec_unix.go | 31 +++--- lang/exec_windows.go | 2 +- lang/process/sysproc.go | 11 --- lang/process/sysproc_test.go | 8 +- shell/session/session_fallback.go | 12 ++- shell/session/session_unix.go | 92 +++++------------ shell/shell.go | 2 +- shell/signal_handler/sigfns/sigfns_unix.go | 98 +++++++++++++++---- shell/signal_handler/signals.go | 10 +- shell/signal_handler/signals_unix.go | 3 +- utils/ansititle/ansititle_fuzz_test.go | 4 +- utils/ansititle/ansititle_test.go | 4 +- version.svg | 2 +- 20 files changed, 180 insertions(+), 161 deletions(-) diff --git a/app/app.go b/app/app.go index 4b8eb11ce..c73545446 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 738 + Revision = 788 Branch = "863/job-control" - BuildDate = "2024-09-05 22:02:51" + BuildDate = "2024-09-08 01:45:08" ) // Copyright is the copyright owner string diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index c2da0b6fa..f17334de6 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -64,9 +64,9 @@ func cmdForeground(p *lang.Process) error { f.State.Set(state.Executing) if f.SystemProcess.External() { - if p.SystemProcess.ForcedTTY() { - lang.UnixPidToFg(f) - } + //if p.SystemProcess.ForcedTTY() { + lang.UnixPidToFg(f) + //} err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { return err diff --git a/builtins/events/onSignalReceived/signal_posix.go b/builtins/events/onSignalReceived/signal_posix.go index 9a031a8eb..98357de6d 100644 --- a/builtins/events/onSignalReceived/signal_posix.go +++ b/builtins/events/onSignalReceived/signal_posix.go @@ -28,14 +28,14 @@ func cmdSendSignal(p *lang.Process) error { return err } + if !isValidInterrupt(sig) { + return fmt.Errorf("invalid signal name '%s'. Expecting something like 'SIGINT'", sig) + } + proc, err := os.FindProcess(pid) if err != nil { return err } - if !isValidInterrupt(sig) { - return fmt.Errorf("invalid signal name '%s'. Expecting something like 'SIGINT'", sig) - } - return proc.Signal(interrupts[sig]) } diff --git a/flags.go b/flags.go index b3af3ebf0..021eb1ae0 100644 --- a/flags.go +++ b/flags.go @@ -10,26 +10,29 @@ import ( "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/types" + "github.com/lmorg/murex/shell/session" ) var ( - fCommand string - fInteractive bool - fSource []string - fLoadMods bool - fEcho bool - fHelp1 bool - fHelp2 bool - fVersion1 bool - fVersion2 bool - fSh bool - fRunTests bool - fQuiet bool + fCommand string + fInteractive bool + fCreateSession bool + fSource []string + fLoadMods bool + fEcho bool + fHelp1 bool + fHelp2 bool + fVersion1 bool + fVersion2 bool + fSh bool + fRunTests bool + fQuiet bool ) func readFlags() { flag.StringVar(&fCommand, "c", "", "Run code block - read from parameters") flag.BoolVar(&fInteractive, "i", false, "Start interactive shell after -c execution") + flag.BoolVar(&fCreateSession, "setsid", false, "Set session ID: POSIX compatibility for job control (this will break support for some of Murex's job control features)") flag.BoolVar(&fLoadMods, "load-modules", false, "Load modules and profile when in non-interactive mode ") flag.BoolVar(&fHelp1, "h", false, "Help") @@ -80,5 +83,9 @@ func readFlags() { debug.Enabled = true } + if fCreateSession || os.Getenv("MUREX_CREATE_SESSION") == "true" { + session.UnixCreateSession() + } + fSource = flag.Args() } diff --git a/lang/exec.go b/lang/exec.go index 90c29c419..080d000df 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -77,10 +77,10 @@ func execForkFallback(p *Process, argv []string) error { defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway } + //if p.SystemProcess.ForcedTTY() { + UnixPidToFg(nil) + //} err := cmd.Process.Signal(syscall.SIGTERM) - if p.SystemProcess.ForcedTTY() { - UnixPidToFg(nil) - } if err != nil { if err.Error() == os.ErrProcessDone.Error() { return @@ -130,7 +130,7 @@ func execForkFallback(p *Process, argv []string) error { if p.Stdout.IsTTY() { // If Stdout is a TTY then set the appropriate syscalls to allow the calling program to own the TTY.... - cmd.SysProcAttr = unixProcAttrFauxTTY(int(p.Stdout.File().Fd())) + cmd.SysProcAttr = unixProcAttrFauxTTY() cmd.Stdout = p.Stdout.File() //} } else { @@ -244,4 +244,3 @@ func (sp *sysProcT) ExitNum() int { return sp.cmd.ProcessState.Exi func (sp *sysProcT) Kill() error { return sp.cmd.Process.Kill() } func (sp *sysProcT) Signal(sig os.Signal) error { return sp.cmd.Process.Signal(sig) } func (sp *sysProcT) State() *os.ProcessState { return sp.cmd.ProcessState } -func (sp *sysProcT) ForcedTTY() bool { return false } diff --git a/lang/exec_js.go b/lang/exec_js.go index 0fc5e2ad1..c448d3caf 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -11,7 +11,7 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index dd84927b8..d857a460b 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -11,7 +11,7 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 61b1817df..c718164f4 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -18,10 +18,10 @@ import ( ) func osExecFork(p *Process, argv []string) error { - //if !session.UnixIsSession() { - // debug.Logf("!!! session not defined, falling back to non-unix ttys") - // return execForkFallback(p, argv) - //} + if !session.UnixIsSession() { + debug.Logf("!!! session not defined, falling back to non-unix ttys") + return execForkFallback(p, argv) + } if p.HasCancelled() { return nil @@ -75,7 +75,6 @@ func (sp *sysProcUnixT) Pid() int { return sp.p.Pid } func (sp *sysProcUnixT) ExitNum() int { return sp.state.ExitCode() } func (sp *sysProcUnixT) Kill() error { return sp.p.Kill() } func (sp *sysProcUnixT) Signal(sig os.Signal) error { return sp.p.Signal(sig) } -func (sp *sysProcUnixT) ForcedTTY() bool { return true } func (sp *sysProcUnixT) State() *os.ProcessState { sp.mutex.Lock() @@ -94,12 +93,17 @@ func (sp *sysProcUnixT) wait() error { // UnixPidToFg brings a UNIX process to the foreground. // If p == nil then UnixPidToFg will assume Murex Pid instead. func UnixPidToFg(p *Process) { + if !session.UnixIsSession() { + return + } + var ( pid int err error ) if p == nil { // Put Murex in the foreground + pid, err = syscall.Getpgid(unix.Getpid()) if err != nil { debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) @@ -112,8 +116,9 @@ func UnixPidToFg(p *Process) { syscall.Setsid() } else { // Put a system process in the foreground - pid = p.SystemProcess.Pid() + // Check if its system process, if not, then there's no point proceeding + pid = p.SystemProcess.Pid() if pid <= 0 { return } @@ -130,7 +135,7 @@ func UnixPidToFg(p *Process) { // feels "wrong" not to at least try os.Stdin first. err = unixPidToFg(pid, int(session.UnixTTY().Fd())) if err != nil { - debug.Logf("!!! UnixPidToFg(%d)->session.UnixTTY(): %s", pid, err.Error()) + debug.Logf("!!! UnixPidToFg(%d, session.UnixTTY()): %s", pid, err.Error()) } } @@ -145,7 +150,7 @@ func unixPidToFg(pid int, tty int) error { ///// -func unixProcAttrFauxTTY(fd int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY() *syscall.SysProcAttr { return &syscall.SysProcAttr{ //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, @@ -157,7 +162,7 @@ func unixProcAttrFauxTTY(fd int) *syscall.SysProcAttr { // This is only meaningful if Setsid is true. //Setctty: true, //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: fd, // Controlling TTY fd + //Ctty: 0, // Controlling TTY fd // Foreground places the child process group in the foreground. // This implies Setpgid. The Ctty field must be set to // the descriptor of the controlling TTY. @@ -170,9 +175,9 @@ func unixProcAttrFauxTTY(fd int) *syscall.SysProcAttr { func unixProcAttrRealTTY(envs []string) *os.ProcAttr { return &os.ProcAttr{ - //Files: []*os.File{session.UnixTTY(), session.UnixTTY(), session.UnixTTY()}, - Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, - Env: envs, + Files: []*os.File{session.UnixTTY(), session.UnixTTY(), session.UnixTTY()}, + //Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, + Env: envs, Sys: &syscall.SysProcAttr{ //Setsid: true, // Create session. // Setpgid sets the process group ID of the child to Pgid, @@ -184,7 +189,7 @@ func unixProcAttrRealTTY(envs []string) *os.ProcAttr { // This is only meaningful if Setsid is true. //Setctty: true, //Noctty: true, // Detach fd 0 from controlling terminal - //Ctty: 0, // Controlling TTY fd + Ctty: 0, // Controlling TTY fd // Foreground places the child process group in the foreground. // This implies Setpgid. The Ctty field must be set to // the descriptor of the controlling TTY. diff --git a/lang/exec_windows.go b/lang/exec_windows.go index feedcbde3..0ab372c96 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -17,7 +17,7 @@ func osExecFork(p *Process, argv []string) error { return execForkFallback(p, argv) } -func unixProcAttrFauxTTY(_ int) *syscall.SysProcAttr { +func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index 143335bc4..279fde434 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -12,7 +12,6 @@ type systemProcessInheritance interface { Pid() int ExitNum() int State() *os.ProcessState - ForcedTTY() bool } type SystemProcess struct { @@ -92,16 +91,6 @@ func (sp *SystemProcess) State() *os.ProcessState { return nil } -func (sp *SystemProcess) ForcedTTY() bool { - sp.mutex.Lock() - defer sp.mutex.Unlock() - - if sp.inheritance != nil { - return sp.inheritance.ForcedTTY() - } - return false -} - // WaitForPid should only be used in redirection.go func (sp *SystemProcess) WaitForPid() int { return <-sp.pid diff --git a/lang/process/sysproc_test.go b/lang/process/sysproc_test.go index 48e29529a..4df47506f 100644 --- a/lang/process/sysproc_test.go +++ b/lang/process/sysproc_test.go @@ -28,7 +28,7 @@ func (sp *sysProcTest2T) State() *os.ProcessState { return nil } func (sp *sysProcTest2T) ForcedTTY() bool { return true } func TestSystemProcess(t *testing.T) { - count.Tests(t, (6*2)+1) + count.Tests(t, (5*2)+1) p := lang.NewTestProcess() @@ -56,9 +56,6 @@ func TestSystemProcess(t *testing.T) { case p.SystemProcess.Signal(nil).Error() != "3": t.Errorf("invalid return for: p.SystemProcess.Signal(nil).Error() in test 1") - case p.SystemProcess.ForcedTTY() != false: - t.Errorf("invalid return for: p.SystemProcess.ForcedTTY() in test 1") - default: success = true } @@ -86,9 +83,6 @@ func TestSystemProcess(t *testing.T) { case p.SystemProcess.Signal(nil) != nil: t.Errorf("invalid return for: p.SystemProcess.Signal(nil).Error() in test 2") - case p.SystemProcess.ForcedTTY() != true: - t.Errorf("invalid return for: p.SystemProcess.ForcedTTY() in test 2") - default: success = true } diff --git a/shell/session/session_fallback.go b/shell/session/session_fallback.go index 9f302360c..0c5bdc0a2 100644 --- a/shell/session/session_fallback.go +++ b/shell/session/session_fallback.go @@ -3,8 +3,18 @@ package session -func UnixSetSid() { +import ( + "runtime" + + "github.com/lmorg/murex/debug" +) + +func UnixOpenTTY() { // not supported on this platform } func UnixIsSession() bool { return false } + +func UnixCreateSession() { + debug.Logf("!!! UnixCreateSession is not supported on %s", runtime.GOOS) +} diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index 8defbf3b7..df2a7706e 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -8,7 +8,6 @@ import ( "syscall" "github.com/lmorg/murex/debug" - signalhandler "github.com/lmorg/murex/shell/signal_handler" ) var ( @@ -16,10 +15,8 @@ var ( tty = os.Stdin ) -func UnixSetSid() { +func UnixOpenTTY() { var err error - debug.Enabled = true - debug.Log("!!! Entering UnixSetSid()") // Opening /dev/tty feels like a bit of a kludge when we already know // the tty of stdin. However we often see the following error when @@ -35,20 +32,27 @@ func UnixSetSid() { } else { debug.Log("!!! UnixSetSid()->os.Open(`/dev/tty`) success") } +} +func UnixIsSession() bool { + return unixSid > 0 +} - pid := os.Getpid() +func UnixTTY() *os.File { + return tty +} + +func UnixCreateSession() { + debug.Log("!!! Entering UnixSetSid()") - //sid, _ := syscall.Getsid(pid) - //if syscall.Getpgrp() == sid { - // return - //} + var err error + pid := os.Getpid() // create a new group - err = syscall.Setpgid(pid, os.Getppid()) + /*err = syscall.Setpgid(pid, os.Getpid()) if err != nil { debug.Logf("!!! UnixSetSid()->syscall.Setpgid():1 failed: %s", err.Error()) - } + }*/ // Create a new session unixSid, err = syscall.Setsid() @@ -56,73 +60,21 @@ func UnixSetSid() { debug.Logf("!!! UnixSetSid()->syscall.Setsid():1 failed: %s", err.Error()) } - // create a new group - err = syscall.Setpgid(pid, pid) - if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Setpgid():2 failed: %s", err.Error()) - } - - // Create a new session - unixSid, err = syscall.Setsid() - if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Setsid():2 failed: %s", err.Error()) - } - - signalhandler.Register(true) - pgid, err := syscall.Getpgid(pid) debug.Logf("pid: %d, ppid: %d, pgid: %d, err: %v", pid, os.Getppid(), pgid, err) pgrp := syscall.Getpgrp() debug.Logf("pid: %d, ppid: %d, pgid: %d, err: --", pid, os.Getppid(), pgrp) sid, err := syscall.Getsid(pid) debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err) - } -func UnixIsSession() bool { - return unixSid > 0 -} - -func UnixTTY() *os.File { - return tty -} - -/* -func relaunchMurex() error { - if os.Getenv("MUREX_SESSION") != "" { - return fmt.Errorf("session already nested") - } - - cmd := exec.Command(which.WhichIgnoreFail(os.Args[0]), os.Args[1:]...) - cmd.Env = append(os.Environ(), fmt.Sprintf("MUREX_SESSION=%d", os.Getpid())) - cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} - - size, err := pty.GetsizeFull(UnixTTY()) - if err != nil { - return fmt.Errorf("cannot get size of terminal: %s", err.Error()) - } - - tty, err := pty.StartWithSize(cmd, size) - if err != nil { - return fmt.Errorf("error starting process: %s", err.Error()) - } - - mxState, err := readline.MakeRaw(int(os.Stdin.Fd())) - if err != nil { - return fmt.Errorf("cannot put TTY into raw mode: %s", err.Error()) - } - - defer readline.Restore(int(os.Stdin.Fd()), mxState) - - go io.Copy(os.Stdout, tty) - go io.Copy(tty, os.Stdin) - - err = cmd.Wait() +/*func UnixCompareSid() bool { + pid := os.Getpid() + sid, err := syscall.Getsid(pid) + debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err) if err != nil { - return err + return true } - os.Exit(0) - return nil // this is silly but go doesn't compile without it -} -*/ + return sid == pid || sid == os.Getppid() +}*/ diff --git a/shell/shell.go b/shell/shell.go index 65e008bb9..62880f557 100644 --- a/shell/shell.go +++ b/shell/shell.go @@ -61,7 +61,7 @@ func callEventsPreview(ctx context.Context, interrupt string, previewItem string func Start() { defer crash.Handler() - session.UnixSetSid() + session.UnixOpenTTY() whatsnew.Display() diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index a91169352..aaf45b347 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -5,8 +5,10 @@ package sigfns import ( "fmt" + "os" "syscall" + "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" @@ -31,9 +33,9 @@ func returnFromSigtstp(p *lang.Process) { //debug.Log("returnFromSigtstp:0", p.Name.String(), p.Parameters.StringAll()) p.State.Set(state.Stopped) - if p.SystemProcess.ForcedTTY() { - lang.UnixPidToFg(nil) - } + //if p.SystemProcess.ForcedTTY() { + lang.UnixPidToFg(nil) + //} //debug.Log("returnFromSigtstp:1", p.Name.String(), p.Parameters.StringAll()) @@ -65,20 +67,80 @@ func Sigchld(interactive bool) { //debug.Log("Sigchld:1") p := lang.ForegroundProc.Get() + debug.Logf("!!! Sigchld(fid: %d)->session.UnixIsSession(fid: %d, pid: %d): %s %s", lang.ShellProcess.Id, p.Id, os.Getpid()) //, p, p.Parameters.StringAll()) + if p.Id == lang.ShellProcess.Id { + // Child already exited so we can ignore this signal + return + } + + /*debug.Logf("!!! Sigchld()->session.UnixIsSession(pid: %d) == %v", os.Getpid(), session.UnixIsSession()) + if !session.UnixIsSession() { + return + }*/ + + /*Logf("session.UnixCompareSid() == %v", session.UnixCompareSid()) + if !session.UnixCompareSid() { + return + }*/ + + debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d) == %v", p.SystemProcess.Pid(), p.SystemProcess.State()) + if p.SystemProcess.State() == nil { + sid, err := syscall.Getsid(p.SystemProcess.Pid()) + if err != nil { + debug.Logf("!!! Sigchld()->syscall.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) + return + } + /*pgid, err := syscall.Getpgid(p.SystemProcess.Pid()) + if err != nil { + debug.Logf("!!! Sigchld()->syscall.Getpgid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) + }*/ + + debug.Logf("!!! syscall.Getsid(p.SystemProcess.Pid: %d) == %d", p.SystemProcess.Pid(), sid) + if sid != p.SystemProcess.Pid() { + return + } + + if p.State.Get() == state.Stopped { + return + } + + debug.Log("!!! calling returnFromSigtstp(p)") + returnFromSigtstp(p) + debug.Log("!!! returned from returnFromSigtstp(p)") + /*err = p.SystemProcess.Signal(syscall.SIGSTOP) + if err != nil { + debug.Logf("!!! Sigchld()->p.SystemProcess.Signal(pid: %d, syscall.SIGSTOP) failed: %s", p.SystemProcess.Pid(), err.Error()) + }*/ + return + } - //debug.Log("Sigchld:2", p.Name.String(), p.Parameters.StringAll()) - if !p.SystemProcess.ForcedTTY() { + if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { + debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d).Sys().(syscall.WaitStatus).Exited() == true", os.Getpid()) return } + //if p.SystemProcess + + //if p.SystemProcess.Pid() + //debug.Log("Sigchld:3", p.Name.String(), p.Parameters.StringAll()) - if p.SystemProcess.State() == nil || p.SystemProcess.State().Sys().(syscall.WaitStatus).Stopped() { + /*if p.SystemProcess.State() == nil || p.SystemProcess.State().Sys().(syscall.WaitStatus).Stopped() { //debug.Log("Sigchld:4", p.Name.String(), p.Parameters.StringAll()) if p.State.Get() != state.Stopped { //debug.Log("Sigchld:5", p.Name.String(), p.Parameters.StringAll()) - returnFromSigtstp(p) + //returnFromSigtstp(p) + proc, err := os.FindProcess(os.Getppid()) + if err != nil { + debug.Logf("!!! Sigchld()->os.FindProcess(os.Getppid()) failed: %s", err.Error()) + return + } + debug.Logf("!!! Sigchld()->proc.Signal(Pppid: %d, syscall.SIGTSTP) invoked", proc.Pid) + err = proc.Signal(syscall.SIGTSTP) + if err != nil { + debug.Logf("!!! Sigchld()->proc.Signal(syscall.SIGTSTP) failed: %s", err.Error()) + } } - } + }*/ //debug.Log("Sigchld:6", p.Name.String(), p.Parameters.StringAll()) } @@ -99,13 +161,19 @@ func stopStatus(p *lang.Process) { stderrW, stderrR = p.Stderr.Stats() } - pipeStatus := fmt.Sprintf( - "\n!!! STDIN: %s written / %s read\n!!! STDOUT: %s written / %s read\n!!! STDERR: %s written / %s read", + lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( + "\n!!! FID %d has been stopped:\n!!! %s %s\n!!! Use `fg %d` / `bg %d` to manage the FID\n!!! ...or `jobs` to see a list of background and suspended functions", + p.Id, + p.Name.String(), p.Parameters.StringAll(), + p.Id, p.Id, + ))) + + lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( + "!!!\n!!! STDIN: %s written / %s read\n!!! STDOUT: %s written / %s read\n!!! STDERR: %s written / %s read", humannumbers.Bytes(stdinW), humannumbers.Bytes(stdinR), humannumbers.Bytes(stdoutW), humannumbers.Bytes(stdoutR), humannumbers.Bytes(stderrW), humannumbers.Bytes(stderrR), - ) - lang.ShellProcess.Stderr.Writeln([]byte(pipeStatus)) + ))) if p.SystemProcess.External() { block, fileRef, err := lang.ShellProcess.Config.GetFileRef("shell", "stop-status-func", types.CodeBlock) @@ -125,10 +193,4 @@ func stopStatus(p *lang.Process) { } } - lang.ShellProcess.Stderr.Writeln([]byte(fmt.Sprintf( - "!!! FID %d has been stopped:\n!!! %s %s\n!!! Use `fg %d` / `bg %d` to manage the FID\n!!! ...or `jobs` to see a list of background and suspended functions", - p.Id, - p.Name.String(), p.Parameters.StringAll(), - p.Id, p.Id, - ))) } diff --git a/shell/signal_handler/signals.go b/shell/signal_handler/signals.go index 2f2792a37..80924ea95 100644 --- a/shell/signal_handler/signals.go +++ b/shell/signal_handler/signals.go @@ -7,13 +7,15 @@ import ( var signalChan chan os.Signal = make(chan os.Signal, 1) const ( + // PromptEOF defines the string to write when ctrl+d is pressed + PromptEOF = "^D" + + // PromptSIGTSTP defines the string to write when ctrl+z is pressed + PromptSIGTSTP = "^Z" + // PromptSIGINT defines the string to write when ctrl+c is pressed PromptSIGINT = "^C" // PromptSIGQUIT defines the string to write when ctrl+\ is pressed PromptSIGQUIT = "^\\" - - // PromptEOF defines the string to write when ctrl+d is pressed - PromptEOF = "^D" ) - diff --git a/shell/signal_handler/signals_unix.go b/shell/signal_handler/signals_unix.go index b1814e13a..2f6f90fbd 100644 --- a/shell/signal_handler/signals_unix.go +++ b/shell/signal_handler/signals_unix.go @@ -42,8 +42,7 @@ func EventLoop(interactive bool) { func Register(interactive bool) { if interactive { // Interactive, so we will handle stop - signal.Reset(syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP, syscall.SIGCHLD) - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGTSTP, syscall.SIGCHLD) //, syscall.SIGTTIN, syscall.SIGTTOU) + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGCHLD, syscall.SIGTSTP) } else { // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us diff --git a/utils/ansititle/ansititle_fuzz_test.go b/utils/ansititle/ansititle_fuzz_test.go index 49a0e9771..8f4beecb7 100644 --- a/utils/ansititle/ansititle_fuzz_test.go +++ b/utils/ansititle/ansititle_fuzz_test.go @@ -1,5 +1,5 @@ -//go:build go1.18 && !js && !windows -// +build go1.18,!js,!windows +//go:build go1.18 && !js && !windows && !plan9 +// +build go1.18,!js,!windows,!plan9 package ansititle diff --git a/utils/ansititle/ansititle_test.go b/utils/ansititle/ansititle_test.go index 26d0a6a36..5bfd813ee 100644 --- a/utils/ansititle/ansititle_test.go +++ b/utils/ansititle/ansititle_test.go @@ -1,5 +1,5 @@ -//go:build !js && !windows -// +build !js,!windows +//go:build !js && !windows && !plan9 +// +build !js,!windows,!plan9 package ansititle diff --git a/version.svg b/version.svg index c29ae2c31..61cf88f84 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0738Version6.3.0738 +Version: 6.3.0788Version6.3.0788 From 66b59194bd4b0fa1b1021da7192a752b264ac51e Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 18:14:33 +0100 Subject: [PATCH 094/142] #863 job-control: added --execute flag + helix ^z support --- app/app.go | 4 +- builtins/core/processes/bgfg_unix.go | 3 ++ debug/debug.go | 1 + flags.go | 6 ++- integrations/helix-editor_posix.mx | 12 ++++-- lang/exec.go | 6 +-- lang/exec_unix.go | 3 +- main.go | 46 +++++++++++++--------- main_test.go | 27 ++++++++++++- main_unix.go | 1 + shell/signal_handler/sigfns/sigfns_unix.go | 12 +++++- shell/signal_handler/signals_unix.go | 6 ++- version.svg | 2 +- 13 files changed, 95 insertions(+), 34 deletions(-) diff --git a/app/app.go b/app/app.go index c73545446..73d82c74d 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 788 + Revision = 812 Branch = "863/job-control" - BuildDate = "2024-09-08 01:45:08" + BuildDate = "2024-09-08 18:14:35" ) // Copyright is the copyright owner string diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index f17334de6..d5649381c 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -5,11 +5,13 @@ package processes import ( "errors" + "os" "syscall" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" + "golang.org/x/sys/unix" ) func mkbg(p *lang.Process) error { @@ -71,6 +73,7 @@ func cmdForeground(p *lang.Process) error { if err != nil { return err } + unix.IoctlSetPointerInt(int(os.Stdin.Fd()), unix.TIOCSPGRP, f.SystemProcess.Pid()) } <-f.Context.Done() diff --git a/debug/debug.go b/debug/debug.go index 9d54763c7..9a25e2cb7 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -50,5 +50,6 @@ func LogWriter(path string) error { return err } log.SetOutput(f) + log.SetPrefix(fmt.Sprintf("[PID: %d] ", os.Getpid())) return nil } diff --git a/flags.go b/flags.go index 021eb1ae0..976521b91 100644 --- a/flags.go +++ b/flags.go @@ -14,8 +14,9 @@ import ( ) var ( - fCommand string fInteractive bool + fCommand string + fExecute bool fCreateSession bool fSource []string fLoadMods bool @@ -30,8 +31,9 @@ var ( ) func readFlags() { - flag.StringVar(&fCommand, "c", "", "Run code block - read from parameters") flag.BoolVar(&fInteractive, "i", false, "Start interactive shell after -c execution") + flag.StringVar(&fCommand, "c", "", "Run code block (str)") + flag.BoolVar(&fExecute, "execute", false, "Execute a command from tokenized parameters (argv[])") flag.BoolVar(&fCreateSession, "setsid", false, "Set session ID: POSIX compatibility for job control (this will break support for some of Murex's job control features)") flag.BoolVar(&fLoadMods, "load-modules", false, "Load modules and profile when in non-interactive mode ") diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 303ebb5fc..2d7635f5a 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -1,7 +1,11 @@ -!if { which hx } then { - return +if { which helix } then { + summary helix "Helix: a post-modern text editor" + + alias helix=exec $MUREX_EXE -quiet -setsid -execute exec helix } -#define-force-tty-func hx +if { which hx } then { + summary hx "Helix: a post-modern text editor" -summary hx "Helix: a post-modern text editor" + alias hx=exec $MUREX_EXE -setsid -quiet -execute exec hx +} diff --git a/lang/exec.go b/lang/exec.go index 080d000df..99a2380f7 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -59,9 +59,9 @@ func execute(p *Process) error { return fmt.Errorf("no parameters specified for `exec`\nExpecting a name of command to run") } - if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() && forceTTY(p) { - return osExecFork(p, argv) - } + //if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { + //return osExecFork(p, argv) + //} return execForkFallback(p, argv) } diff --git a/lang/exec_unix.go b/lang/exec_unix.go index c718164f4..9cbf6a97a 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -18,7 +18,7 @@ import ( ) func osExecFork(p *Process, argv []string) error { - if !session.UnixIsSession() { + if !session.UnixIsSession() || p.IsMethod || !p.Stdout.IsTTY() || !p.Stderr.IsTTY() { debug.Logf("!!! session not defined, falling back to non-unix ttys") return execForkFallback(p, argv) } @@ -26,6 +26,7 @@ func osExecFork(p *Process, argv []string) error { if p.HasCancelled() { return nil } + p.Kill = func() { if !debug.Enabled { defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway diff --git a/main.go b/main.go index 0d3adef09..9ecc3c9ec 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,9 @@ package main import ( + "flag" "os" + "strings" "time" _ "github.com/lmorg/murex/builtins" @@ -18,14 +20,10 @@ import ( "github.com/lmorg/murex/lang/ref" "github.com/lmorg/murex/shell" "github.com/lmorg/murex/utils/cache" + "github.com/lmorg/murex/utils/escape" "github.com/lmorg/murex/utils/readline" ) -const ( - interactive bool = true - nonInteractive bool = false -) - func main() { readFlags() @@ -34,13 +32,18 @@ func main() { runTests() case fCommand != "": - runCommandLine(fCommand) + runCommandString(fCommand) + + case fExecute: + argv := flag.Args() + cmdLine := argvToCmdLineStr(argv) + runCommandString(cmdLine) case len(fSource) > 0: runSource(fSource[0]) default: - startMurex() + startMurexRepl() } debug.Log("[FIN]") @@ -49,8 +52,8 @@ func main() { func runTests() error { lang.InitEnv() - defaults.Config(lang.ShellProcess.Config, nonInteractive) - registerSignalHandlers(nonInteractive) + defaults.Config(lang.ShellProcess.Config, fInteractive) + registerSignalHandlers(fInteractive) // compiled profile defaultProfile() @@ -81,12 +84,19 @@ func runTests() error { return nil } -func runCommandLine(commandLine string) { +func argvToCmdLineStr(argv []string) string { + cmdLine := make([]string, len(argv)) + copy(cmdLine, argv) + escape.CommandLine(cmdLine) + return strings.Join(cmdLine, " ") +} + +func runCommandString(commandString string) { lang.InitEnv() // default config - defaults.Config(lang.ShellProcess.Config, nonInteractive) - registerSignalHandlers(nonInteractive) + defaults.Config(lang.ShellProcess.Config, fInteractive) + registerSignalHandlers(fInteractive) // compiled profile defaultProfile() @@ -103,7 +113,7 @@ func runCommandLine(commandLine string) { Filename: "", Module: "murex/-c", } - execSource([]rune(commandLine), &sourceRef, true) + execSource([]rune(commandString), &sourceRef, true) if fInteractive { shell.Start() @@ -114,8 +124,8 @@ func runSource(filename string) { lang.InitEnv() // default config - defaults.Config(lang.ShellProcess.Config, nonInteractive) - registerSignalHandlers(nonInteractive) + defaults.Config(lang.ShellProcess.Config, fInteractive) + registerSignalHandlers(fInteractive) // compiled profile defaultProfile() @@ -146,11 +156,11 @@ func runSource(filename string) { execSource([]rune(string(disk)), &sourceRef, true) } -func startMurex() { +func startMurexRepl() { lang.InitEnv() // default config - defaults.Config(lang.ShellProcess.Config, interactive) + defaults.Config(lang.ShellProcess.Config, true) cache.SetPath(profile.ModulePath() + "cache.db") cache.InitCache() @@ -162,6 +172,6 @@ func startMurex() { profile.Execute(profile.F_PRELOAD | profile.F_MODULES | profile.F_PROFILE) // start interactive shell - registerSignalHandlers(interactive) + registerSignalHandlers(true) shell.Start() } diff --git a/main_test.go b/main_test.go index 566a8df6f..64f865d11 100644 --- a/main_test.go +++ b/main_test.go @@ -8,6 +8,7 @@ import ( "github.com/lmorg/murex/lang" "github.com/lmorg/murex/test/count" + "github.com/lmorg/murex/utils/json" ) // TestMurex tests murex runtime environment can be initialized and and simple @@ -28,7 +29,7 @@ func TestMurex(t *testing.T) { func TestRunCommandLine(t *testing.T) { count.Tests(t, 1) - runCommandLine(`out: "testing" -> null`) + runCommandString(`out: "testing" -> null`) } func TestRunSource(t *testing.T) { @@ -44,3 +45,27 @@ func TestRunSourceGzMods(t *testing.T) { file := "test/source.mx.gz" runSource(file) } + +func TestArgvToCmdLineStr(t *testing.T) { + tests := map[string][]string{ + `foobar`: []string{`foobar`}, + `\ foo`: []string{` foo`}, + `foo\ `: []string{`foo `}, // TODO: this might cause things to break...? + `foo bar`: []string{`foo`, `bar`}, + `foo\ bar baz`: []string{`foo bar`, `baz`}, + `foo\ bar`: []string{`foo `, `bar`}, + } + + count.Tests(t, len(tests)) + + for expected, argv := range tests { + actual := argvToCmdLineStr(argv) + + if expected != actual { + t.Error("Expected does not match actual:") + t.Logf(" argv: %s", json.LazyLogging(argv)) + t.Logf(" expected: '%s'", expected) + t.Logf(" actual: '%s'", actual) + } + } +} diff --git a/main_unix.go b/main_unix.go index 66245f1d3..55d7b5ad0 100644 --- a/main_unix.go +++ b/main_unix.go @@ -15,6 +15,7 @@ func registerSignalHandlers(interactiveMode bool) { Sigquit: sigfns.Sigquit, Sigtstp: sigfns.Sigtstp, Sigchld: sigfns.Sigchld, + Sigcont: sigfns.Sigcont, } signalhandler.EventLoop(interactiveMode) } diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index aaf45b347..3373ccb33 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -15,7 +15,7 @@ import ( "github.com/lmorg/murex/utils/humannumbers" ) -func Sigtstp(interactive bool) { +func Sigtstp(_ bool) { p := lang.ForegroundProc.Get() if p.SystemProcess.External() { err := p.SystemProcess.Signal(syscall.SIGSTOP) @@ -194,3 +194,13 @@ func stopStatus(p *lang.Process) { } } + +func Sigcont(_ bool) { + p := lang.ForegroundProc.Get() + if p.SystemProcess.External() { + err := p.SystemProcess.Signal(syscall.SIGCONT) + if err != nil { + lang.ShellProcess.Stderr.Write([]byte(err.Error())) + } + } +} diff --git a/shell/signal_handler/signals_unix.go b/shell/signal_handler/signals_unix.go index 2f6f90fbd..f5e5277fc 100644 --- a/shell/signal_handler/signals_unix.go +++ b/shell/signal_handler/signals_unix.go @@ -32,6 +32,9 @@ func EventLoop(interactive bool) { case syscall.SIGCHLD.String(): go Handlers.Sigchld(interactive) + case syscall.SIGCONT.String(): + go Handlers.Sigcont(interactive) + default: panic("unhandled signal: " + sig.String()) // this shouldn't ever happen } @@ -46,7 +49,7 @@ func Register(interactive bool) { } else { // Non-interactive, so lets ignore the stop signal and let the OS / calling shell manage that for us - signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGCONT) } } @@ -58,4 +61,5 @@ type SignalFunctionsT struct { Sigquit func(bool) Sigtstp func(bool) Sigchld func(bool) + Sigcont func(bool) } diff --git a/version.svg b/version.svg index 61cf88f84..a8c3d4d14 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0788Version6.3.0788 +Version: 6.3.0812Version6.3.0812 From 710d3d85977ff78c0106b5bb9240664cb6019de4 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 18:31:26 +0100 Subject: [PATCH 095/142] chore: remove commented dead code --- app/app.go | 4 +- lang/exec.go | 11 +- lang/exec_unix.go | 123 +-------------------- shell/signal_handler/sigfns/sigfns.go | 4 - shell/signal_handler/sigfns/sigfns_unix.go | 68 +----------- version.svg | 2 +- 6 files changed, 16 insertions(+), 196 deletions(-) diff --git a/app/app.go b/app/app.go index 73d82c74d..fd6393f99 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 812 + Revision = 815 Branch = "863/job-control" - BuildDate = "2024-09-08 18:14:35" + BuildDate = "2024-09-08 18:31:27" ) // Copyright is the copyright owner string diff --git a/lang/exec.go b/lang/exec.go index 99a2380f7..1ebc8676f 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -111,7 +111,7 @@ func execForkFallback(p *Process, argv []string) error { cmd.Env = append(os.Environ(), envMurexPid, envMethodFalse, envBackgroundFalse, envDataType+p.Stdin.GetDataType()) } - /*if len(p.Envs) > 0 { + if len(p.Envs) > 0 { for i := range p.Envs { if !strings.Contains(p.Envs[i], "=") { v, err := p.Variables.GetString(p.Envs[i]) @@ -122,7 +122,7 @@ func execForkFallback(p *Process, argv []string) error { } } cmd.Env = append(cmd.Env, p.Envs...) - }*/ + } // *** // Define STANDARD OUT (fd 1) @@ -218,14 +218,7 @@ func execForkFallback(p *Process, argv []string) error { tty.Stderr.WriteString("error closing murex data type output file write pipe:" + err.Error() + "\n") }*/ - //if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { - // signal.Ignore(syscall.SIGTTOU) - // UnixPidToFg(cmd.Process.Pid) - //} err := cmd.Wait() - //signal.Reset(syscall.SIGTTOU) - //UnixPidToFg(0) - ////signalhandler.Register(Interactive) if err != nil { if !strings.HasPrefix(err.Error(), "signal:") { //mxdtR.Close() diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 9cbf6a97a..9d39a498d 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -6,91 +6,13 @@ package lang import ( "fmt" "os" - "sync" "syscall" "github.com/lmorg/murex/debug" - "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/shell/session" - "github.com/lmorg/murex/utils/json" - "github.com/lmorg/murex/utils/which" "golang.org/x/sys/unix" ) -func osExecFork(p *Process, argv []string) error { - if !session.UnixIsSession() || p.IsMethod || !p.Stdout.IsTTY() || !p.Stderr.IsTTY() { - debug.Logf("!!! session not defined, falling back to non-unix ttys") - return execForkFallback(p, argv) - } - - if p.HasCancelled() { - return nil - } - - p.Kill = func() { - if !debug.Enabled { - defer func() { recover() }() // I don't care about errors in this instance since we are just killing the proc anyway - } - - err := p.SystemProcess.Signal(syscall.SIGTERM) - if err != nil { - if err.Error() == os.ErrProcessDone.Error() { - return - } - name, _ := p.Args() - os.Stderr.WriteString( - fmt.Sprintf("\n!!! Error sending SIGTERM to `%s`: %s\n", name, err.Error())) - } - } - - p.State.Set(state.Executing) - unixProcess, err := os.StartProcess(which.WhichIgnoreFail(argv[0]), argv, unixProcAttrRealTTY(p.Envs)) - if err != nil { - return fmt.Errorf("failed fork in os.StartProcess -> osExecFork()...\n%s\nargv: %s", - err.Error(), - json.LazyLogging(argv), - ) - } - - sysProc := sysProcUnixT{p: unixProcess} - p.SystemProcess.Set(&sysProc) - defer setsid() - UnixPidToFg(p) - return sysProc.wait() - /*if err != nil { - //if !strings.HasPrefix(err.Error(), "signal:") { - return err - //} - } - - return nil*/ -} - -type sysProcUnixT struct { - p *os.Process - state *os.ProcessState - mutex sync.Mutex -} - -func (sp *sysProcUnixT) Pid() int { return sp.p.Pid } -func (sp *sysProcUnixT) ExitNum() int { return sp.state.ExitCode() } -func (sp *sysProcUnixT) Kill() error { return sp.p.Kill() } -func (sp *sysProcUnixT) Signal(sig os.Signal) error { return sp.p.Signal(sig) } - -func (sp *sysProcUnixT) State() *os.ProcessState { - sp.mutex.Lock() - defer sp.mutex.Unlock() - return sp.state -} - -func (sp *sysProcUnixT) wait() error { - state, err := sp.p.Wait() - sp.mutex.Lock() - sp.state = state - sp.mutex.Unlock() - return err -} - // UnixPidToFg brings a UNIX process to the foreground. // If p == nil then UnixPidToFg will assume Murex Pid instead. func UnixPidToFg(p *Process) { @@ -107,7 +29,7 @@ func UnixPidToFg(p *Process) { pid, err = syscall.Getpgid(unix.Getpid()) if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) + //debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) pid = syscall.Getpid() } @@ -134,10 +56,10 @@ func UnixPidToFg(p *Process) { // fallback is to use /dev/tty. This seems the default recommendation in a // lot of the example code and documentation on this topic but it still // feels "wrong" not to at least try os.Stdin first. - err = unixPidToFg(pid, int(session.UnixTTY().Fd())) - if err != nil { - debug.Logf("!!! UnixPidToFg(%d, session.UnixTTY()): %s", pid, err.Error()) - } + _ = unixPidToFg(pid, int(session.UnixTTY().Fd())) + //if err != nil { + //debug.Logf("!!! UnixPidToFg(%d, session.UnixTTY()): %s", pid, err.Error()) + //} } func unixPidToFg(pid int, tty int) error { @@ -173,38 +95,3 @@ func unixProcAttrFauxTTY() *syscall.SysProcAttr { //Pgid: 0, // Child's process group ID if Setpgid. } } - -func unixProcAttrRealTTY(envs []string) *os.ProcAttr { - return &os.ProcAttr{ - Files: []*os.File{session.UnixTTY(), session.UnixTTY(), session.UnixTTY()}, - //Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, - Env: envs, - Sys: &syscall.SysProcAttr{ - //Setsid: true, // Create session. - // Setpgid sets the process group ID of the child to Pgid, - // or, if Pgid == 0, to the new child's process ID. - Setpgid: true, - // Setctty sets the controlling terminal of the child to - // file descriptor Ctty. Ctty must be a descriptor number - // in the child process: an index into ProcAttr.Files. - // This is only meaningful if Setsid is true. - //Setctty: true, - //Noctty: true, // Detach fd 0 from controlling terminal - Ctty: 0, // Controlling TTY fd - // Foreground places the child process group in the foreground. - // This implies Setpgid. The Ctty field must be set to - // the descriptor of the controlling TTY. - // Unlike Setctty, in this case Ctty must be a descriptor - // number in the parent process. - //Foreground: true, - Pgid: 0, // Child's process group ID if Setpgid. - }, - } -} - -func setsid() { - _, err := syscall.Setsid() - if err != nil { - debug.Logf("!!! setsid()->syscall.Setsid() failed: %s", err.Error()) - } -} diff --git a/shell/signal_handler/sigfns/sigfns.go b/shell/signal_handler/sigfns/sigfns.go index bfd60e4e5..9a2c782d4 100644 --- a/shell/signal_handler/sigfns/sigfns.go +++ b/shell/signal_handler/sigfns/sigfns.go @@ -32,12 +32,9 @@ var rxWhiteSpace = regexp.MustCompilePOSIX(`[\r\n\t ]+`) func Sigquit(interactive bool) { if !interactive { - //os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) lang.Exit(2) } - //os.Stderr.WriteString("!!! Murex received SIGQUIT" + utils.NewLineString) - //lang.UnixPidToFg(0) fids := lang.GlobalFIDs.ListAll() for _, p := range fids { if p.Kill != nil /*&& !p.HasTerminated()*/ { @@ -70,6 +67,5 @@ func Sigquit(interactive bool) { } } - //lang.ShellProcess.Stderr.Writeln([]byte("!!! Starting new prompt")) lang.ShowPrompt <- true } diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 3373ccb33..158c4aadb 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -5,7 +5,6 @@ package sigfns import ( "fmt" - "os" "syscall" "github.com/lmorg/murex/debug" @@ -30,70 +29,42 @@ func Sigtstp(_ bool) { } func returnFromSigtstp(p *lang.Process) { - //debug.Log("returnFromSigtstp:0", p.Name.String(), p.Parameters.StringAll()) - p.State.Set(state.Stopped) - //if p.SystemProcess.ForcedTTY() { lang.UnixPidToFg(nil) - //} - - //debug.Log("returnFromSigtstp:1", p.Name.String(), p.Parameters.StringAll()) show, err := lang.ShellProcess.Config.Get("shell", "stop-status-enabled", types.Boolean) if err != nil { show = false } - //debug.Log("returnFromSigtstp:2", p.Name.String(), p.Parameters.StringAll()) - if show.(bool) { stopStatus(p) } - //debug.Log("returnFromSigtstp:3", p.Name.String(), p.Parameters.StringAll()) - lang.ShowPrompt <- true - //debug.Log("returnFromSigtstp:4", p.Name.String(), p.Parameters.StringAll()) - p.HasStopped <- true } func Sigchld(interactive bool) { - //debug.Log("Sigchld:0") if !interactive { return } - //debug.Log("Sigchld:1") p := lang.ForegroundProc.Get() - debug.Logf("!!! Sigchld(fid: %d)->session.UnixIsSession(fid: %d, pid: %d): %s %s", lang.ShellProcess.Id, p.Id, os.Getpid()) //, p, p.Parameters.StringAll()) + //debug.Logf("!!! Sigchld(fid: %d)->session.UnixIsSession(fid: %d, pid: %d): %s %s", lang.ShellProcess.Id, p.Id, os.Getpid()) //, p, p.Parameters.StringAll()) if p.Id == lang.ShellProcess.Id { // Child already exited so we can ignore this signal return } - /*debug.Logf("!!! Sigchld()->session.UnixIsSession(pid: %d) == %v", os.Getpid(), session.UnixIsSession()) - if !session.UnixIsSession() { - return - }*/ - - /*Logf("session.UnixCompareSid() == %v", session.UnixCompareSid()) - if !session.UnixCompareSid() { - return - }*/ - - debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d) == %v", p.SystemProcess.Pid(), p.SystemProcess.State()) + //debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d) == %v", p.SystemProcess.Pid(), p.SystemProcess.State()) if p.SystemProcess.State() == nil { sid, err := syscall.Getsid(p.SystemProcess.Pid()) if err != nil { debug.Logf("!!! Sigchld()->syscall.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) return } - /*pgid, err := syscall.Getpgid(p.SystemProcess.Pid()) - if err != nil { - debug.Logf("!!! Sigchld()->syscall.Getpgid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) - }*/ debug.Logf("!!! syscall.Getsid(p.SystemProcess.Pid: %d) == %d", p.SystemProcess.Pid(), sid) if sid != p.SystemProcess.Pid() { @@ -104,44 +75,17 @@ func Sigchld(interactive bool) { return } - debug.Log("!!! calling returnFromSigtstp(p)") + //debug.Log("!!! calling returnFromSigtstp(p)") returnFromSigtstp(p) - debug.Log("!!! returned from returnFromSigtstp(p)") - /*err = p.SystemProcess.Signal(syscall.SIGSTOP) - if err != nil { - debug.Logf("!!! Sigchld()->p.SystemProcess.Signal(pid: %d, syscall.SIGSTOP) failed: %s", p.SystemProcess.Pid(), err.Error()) - }*/ + //debug.Log("!!! returned from returnFromSigtstp(p)") + return } if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { - debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d).Sys().(syscall.WaitStatus).Exited() == true", os.Getpid()) + //debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d).Sys().(syscall.WaitStatus).Exited() == true", os.Getpid()) return } - - //if p.SystemProcess - - //if p.SystemProcess.Pid() - - //debug.Log("Sigchld:3", p.Name.String(), p.Parameters.StringAll()) - /*if p.SystemProcess.State() == nil || p.SystemProcess.State().Sys().(syscall.WaitStatus).Stopped() { - //debug.Log("Sigchld:4", p.Name.String(), p.Parameters.StringAll()) - if p.State.Get() != state.Stopped { - //debug.Log("Sigchld:5", p.Name.String(), p.Parameters.StringAll()) - //returnFromSigtstp(p) - proc, err := os.FindProcess(os.Getppid()) - if err != nil { - debug.Logf("!!! Sigchld()->os.FindProcess(os.Getppid()) failed: %s", err.Error()) - return - } - debug.Logf("!!! Sigchld()->proc.Signal(Pppid: %d, syscall.SIGTSTP) invoked", proc.Pid) - err = proc.Signal(syscall.SIGTSTP) - if err != nil { - debug.Logf("!!! Sigchld()->proc.Signal(syscall.SIGTSTP) failed: %s", err.Error()) - } - } - }*/ - //debug.Log("Sigchld:6", p.Name.String(), p.Parameters.StringAll()) } func stopStatus(p *lang.Process) { diff --git a/version.svg b/version.svg index a8c3d4d14..372ac5cd2 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0812Version6.3.0812 +Version: 6.3.0815Version6.3.0815 From 5e1f2529bc1a2dcd49091bcd1b5e28432481f3ff Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 18:36:37 +0100 Subject: [PATCH 096/142] chore: rename execFork --- app/app.go | 4 ++-- lang/exec.go | 8 ++------ lang/exec_plan9.go | 4 ---- lang/exec_windows.go | 4 ---- version.svg | 2 +- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/app/app.go b/app/app.go index fd6393f99..2c6d9124d 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 815 + Revision = 816 Branch = "863/job-control" - BuildDate = "2024-09-08 18:31:27" + BuildDate = "2024-09-08 18:36:39" ) // Copyright is the copyright owner string diff --git a/lang/exec.go b/lang/exec.go index 1ebc8676f..88bee3a44 100644 --- a/lang/exec.go +++ b/lang/exec.go @@ -59,14 +59,10 @@ func execute(p *Process) error { return fmt.Errorf("no parameters specified for `exec`\nExpecting a name of command to run") } - //if !p.IsMethod && p.Stdout.IsTTY() && p.Stderr.IsTTY() { - //return osExecFork(p, argv) - //} - - return execForkFallback(p, argv) + return execFork(p, argv) } -func execForkFallback(p *Process, argv []string) error { +func execFork(p *Process, argv []string) error { cmd := exec.Command(which.WhichIgnoreFail(argv[0]), argv[1:]...) if p.HasCancelled() { diff --git a/lang/exec_plan9.go b/lang/exec_plan9.go index d857a460b..4b6943842 100644 --- a/lang/exec_plan9.go +++ b/lang/exec_plan9.go @@ -7,10 +7,6 @@ import ( "syscall" ) -func osExecFork(p *Process, argv []string) error { - return execForkFallback(p, argv) -} - func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/lang/exec_windows.go b/lang/exec_windows.go index 0ab372c96..b113c9ecd 100644 --- a/lang/exec_windows.go +++ b/lang/exec_windows.go @@ -13,10 +13,6 @@ func osExecGetArgv(p *Process) []string { return argv } -func osExecFork(p *Process, argv []string) error { - return execForkFallback(p, argv) -} - func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/version.svg b/version.svg index 372ac5cd2..7693b92c3 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0815Version6.3.0815 +Version: 6.3.0816Version6.3.0816 From 33abba14cae38391365409cc180fdd5c8773da2d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 20:50:29 +0100 Subject: [PATCH 097/142] syscall->unix package for process IDs --- app/app.go | 4 ++-- lang/exec_unix.go | 8 +++---- shell/session/session_unix.go | 25 ++++++---------------- shell/signal_handler/sigfns/sigfns_unix.go | 7 +++--- version.svg | 2 +- 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/app/app.go b/app/app.go index 2c6d9124d..dcc5f7206 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 816 + Revision = 817 Branch = "863/job-control" - BuildDate = "2024-09-08 18:36:39" + BuildDate = "2024-09-08 20:50:32" ) // Copyright is the copyright owner string diff --git a/lang/exec_unix.go b/lang/exec_unix.go index 9d39a498d..e548bdaac 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -27,16 +27,16 @@ func UnixPidToFg(p *Process) { if p == nil { // Put Murex in the foreground - pid, err = syscall.Getpgid(unix.Getpid()) + pid, err = unix.Getpgid(unix.Getpid()) if err != nil { - //debug.Logf("!!! UnixSetSid()->syscall.Getpgid(unix.Getpid()) failed: %v", err) - pid = syscall.Getpid() + //debug.Logf("!!! UnixSetSid()->unix.Getpgid(unix.Getpid()) failed: %v", err) + pid = unix.Getpid() } // This is only required because some badly behaving programs run // setsid() themselves despite not technically needing to be a session // leader eg shell. - syscall.Setsid() + unix.Setsid() } else { // Put a system process in the foreground diff --git a/shell/session/session_unix.go b/shell/session/session_unix.go index df2a7706e..69ef3be25 100644 --- a/shell/session/session_unix.go +++ b/shell/session/session_unix.go @@ -5,9 +5,9 @@ package session import ( "os" - "syscall" "github.com/lmorg/murex/debug" + "golang.org/x/sys/unix" ) var ( @@ -46,35 +46,24 @@ func UnixCreateSession() { debug.Log("!!! Entering UnixSetSid()") var err error - pid := os.Getpid() + //pid := os.Getpid() // create a new group - /*err = syscall.Setpgid(pid, os.Getpid()) + /*err = unix.Setpgid(pid, os.Getpid()) if err != nil { - debug.Logf("!!! UnixSetSid()->syscall.Setpgid():1 failed: %s", err.Error()) + debug.Logf("!!! UnixSetSid()->unix.Setpgid():1 failed: %s", err.Error()) }*/ // Create a new session - unixSid, err = syscall.Setsid() + unixSid, err = unix.Setsid() if err != nil { debug.Logf("!!! UnixSetSid()->syscall.Setsid():1 failed: %s", err.Error()) } - pgid, err := syscall.Getpgid(pid) + /*pgid, err := unix.Getpgid(pid) debug.Logf("pid: %d, ppid: %d, pgid: %d, err: %v", pid, os.Getppid(), pgid, err) pgrp := syscall.Getpgrp() debug.Logf("pid: %d, ppid: %d, pgid: %d, err: --", pid, os.Getppid(), pgrp) sid, err := syscall.Getsid(pid) - debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err) + debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err)*/ } - -/*func UnixCompareSid() bool { - pid := os.Getpid() - sid, err := syscall.Getsid(pid) - debug.Logf("pid: %d, ppid: %d, sid: %d, err: %v", pid, os.Getppid(), sid, err) - if err != nil { - return true - } - - return sid == pid || sid == os.Getppid() -}*/ diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 158c4aadb..e8f97e517 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -12,6 +12,7 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/humannumbers" + "golang.org/x/sys/unix" ) func Sigtstp(_ bool) { @@ -60,13 +61,13 @@ func Sigchld(interactive bool) { //debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d) == %v", p.SystemProcess.Pid(), p.SystemProcess.State()) if p.SystemProcess.State() == nil { - sid, err := syscall.Getsid(p.SystemProcess.Pid()) + sid, err := unix.Getsid(p.SystemProcess.Pid()) if err != nil { - debug.Logf("!!! Sigchld()->syscall.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) + debug.Logf("!!! Sigchld()->unix.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) return } - debug.Logf("!!! syscall.Getsid(p.SystemProcess.Pid: %d) == %d", p.SystemProcess.Pid(), sid) + debug.Logf("!!! unix.Getsid(p.SystemProcess.Pid: %d) == %d", p.SystemProcess.Pid(), sid) if sid != p.SystemProcess.Pid() { return } diff --git a/version.svg b/version.svg index 7693b92c3..3af03ea4e 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0816Version6.3.0816 +Version: 6.3.0817Version6.3.0817 From a15d882a1ac7f9fe777ca5bfbaa3f69ae064954c Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 21:50:23 +0100 Subject: [PATCH 098/142] #863 job-control: failing wasm build --- app/app.go | 4 ++-- lang/exec_js.go | 4 ---- version.svg | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index dcc5f7206..dc43535c3 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 817 + Revision = 819 Branch = "863/job-control" - BuildDate = "2024-09-08 20:50:32" + BuildDate = "2024-09-08 21:50:25" ) // Copyright is the copyright owner string diff --git a/lang/exec_js.go b/lang/exec_js.go index c448d3caf..78b6cc1b5 100644 --- a/lang/exec_js.go +++ b/lang/exec_js.go @@ -7,10 +7,6 @@ import ( "syscall" ) -func osExecFork(p *Process, argv []string) error { - return execForkFallback(p, argv) -} - func unixProcAttrFauxTTY() *syscall.SysProcAttr { return nil } diff --git a/version.svg b/version.svg index 3af03ea4e..85a7d7236 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0817Version6.3.0817 +Version: 6.3.0819Version6.3.0819 From 8d46015f71eef846f0cbd93bc4892cec3ae51397 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 8 Sep 2024 21:53:49 +0100 Subject: [PATCH 099/142] ci: support for go1.23 --- .github/workflows/clean-build.yaml | 2 +- .github/workflows/code-coverage.yaml | 2 +- .github/workflows/deploy-dev-docs.yaml | 2 +- .github/workflows/deploy-docs.yaml | 2 +- .github/workflows/murex-downloads.yaml | 2 +- .github/workflows/murex-tests.yaml | 2 +- app/app.go | 4 ++-- version.svg | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/clean-build.yaml b/.github/workflows/clean-build.yaml index 5dc7ee96d..79a3ace78 100644 --- a/.github/workflows/clean-build.yaml +++ b/.github/workflows/clean-build.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [ "1.20", "1.21", "1.22" ] + go-version: [ "1.20", "1.21", "1.22", "1.23" ] steps: - name: Setup Go ${{ matrix.go-version }} diff --git a/.github/workflows/code-coverage.yaml b/.github/workflows/code-coverage.yaml index 5603f62e4..927f42497 100644 --- a/.github/workflows/code-coverage.yaml +++ b/.github/workflows/code-coverage.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [ "1.22" ] + go-version: [ "1.23" ] env: MUREX_TEST_NO_EXEC_DEPS: true steps: diff --git a/.github/workflows/deploy-dev-docs.yaml b/.github/workflows/deploy-dev-docs.yaml index 63cc6f645..6d3b8a803 100644 --- a/.github/workflows/deploy-dev-docs.yaml +++ b/.github/workflows/deploy-dev-docs.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [ "1.22" ] + go-version: [ "1.23" ] steps: - name: Checkout diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml index fd9ea4830..461cc076c 100644 --- a/.github/workflows/deploy-docs.yaml +++ b/.github/workflows/deploy-docs.yaml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [ "1.22" ] + go-version: [ "1.23" ] steps: - name: Checkout diff --git a/.github/workflows/murex-downloads.yaml b/.github/workflows/murex-downloads.yaml index bf16b37b4..b128e14ac 100644 --- a/.github/workflows/murex-downloads.yaml +++ b/.github/workflows/murex-downloads.yaml @@ -8,7 +8,7 @@ on: workflow_dispatch: env: - GO_VERSION: "1.21" + GO_VERSION: "1.23" jobs: Build-Downloads: diff --git a/.github/workflows/murex-tests.yaml b/.github/workflows/murex-tests.yaml index 48541390e..c93568387 100644 --- a/.github/workflows/murex-tests.yaml +++ b/.github/workflows/murex-tests.yaml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: [ '1.20', '1.21', '1.22' ] + go-version: [ '1.20', '1.21', '1.22', "1.23" ] env: MUREX_BUILD_FLAGS: --no-colour MUREX_TEST_NO_EXEC_DEPS: true diff --git a/app/app.go b/app/app.go index dc43535c3..79831ff54 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 819 + Revision = 820 Branch = "863/job-control" - BuildDate = "2024-09-08 21:50:25" + BuildDate = "2024-09-08 21:53:52" ) // Copyright is the copyright owner string diff --git a/version.svg b/version.svg index 85a7d7236..96ded58d7 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0819Version6.3.0819 +Version: 6.3.0820Version6.3.0820 From b97931e9f89575960865e58cae22d3693d51ef41 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Mon, 9 Sep 2024 09:19:23 +0100 Subject: [PATCH 100/142] #863 helix ^z support limited to darwin --- app/app.go | 4 ++-- integrations/helix-editor_posix.mx | 9 +++++++-- version.svg | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/app.go b/app/app.go index 79831ff54..b1184c00b 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 820 + Revision = 821 Branch = "863/job-control" - BuildDate = "2024-09-08 21:53:52" + BuildDate = "2024-09-09 09:19:28" ) // Copyright is the copyright owner string diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 2d7635f5a..c43efa4ee 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -1,8 +1,13 @@ -if { which helix } then { +# WIP, only macOS currently supported. +!if { os darwin } then { + return +} + +/#if { which helix } then { summary helix "Helix: a post-modern text editor" alias helix=exec $MUREX_EXE -quiet -setsid -execute exec helix -} +}#/ if { which hx } then { summary hx "Helix: a post-modern text editor" diff --git a/version.svg b/version.svg index 96ded58d7..f0fca49fe 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0820Version6.3.0820 +Version: 6.3.0821Version6.3.0821 From a2d2c963457ceb4c26623bade3503624d55e7a78 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 10 Sep 2024 22:44:26 +0100 Subject: [PATCH 101/142] job-control: minor code tidy up --- app/app.go | 4 ++-- builtins/core/processes/bgfg_unix.go | 12 ++++++------ integrations/helix-editor_posix.mx | 9 ++------- lang/exec_unix.go | 3 --- version.svg | 2 +- 5 files changed, 11 insertions(+), 19 deletions(-) diff --git a/app/app.go b/app/app.go index b1184c00b..d98912570 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 821 + Revision = 828 Branch = "863/job-control" - BuildDate = "2024-09-09 09:19:28" + BuildDate = "2024-09-10 22:44:49" ) // Copyright is the copyright owner string diff --git a/builtins/core/processes/bgfg_unix.go b/builtins/core/processes/bgfg_unix.go index d5649381c..960eb5d76 100644 --- a/builtins/core/processes/bgfg_unix.go +++ b/builtins/core/processes/bgfg_unix.go @@ -5,13 +5,12 @@ package processes import ( "errors" - "os" "syscall" + "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang" "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" - "golang.org/x/sys/unix" ) func mkbg(p *lang.Process) error { @@ -66,14 +65,15 @@ func cmdForeground(p *lang.Process) error { f.State.Set(state.Executing) if f.SystemProcess.External() { - //if p.SystemProcess.ForcedTTY() { lang.UnixPidToFg(f) - //} + err = f.SystemProcess.Signal(syscall.SIGCONT) if err != nil { - return err + // don't "return err" because we still want to wait for the process + // to finish. So lets just print a debug message instead. + debug.Logf("!!! failed syscall in cmdForeground()->(f: [%d] %s %s)->f.SystemProcess.Signal(syscall.SIGCONT):\n!!! error: %s", + f.SystemProcess.Pid(), f.Name.String(), f.Parameters.StringAll(), err.Error()) } - unix.IoctlSetPointerInt(int(os.Stdin.Fd()), unix.TIOCSPGRP, f.SystemProcess.Pid()) } <-f.Context.Done() diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index c43efa4ee..2d7635f5a 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -1,13 +1,8 @@ -# WIP, only macOS currently supported. -!if { os darwin } then { - return -} - -/#if { which helix } then { +if { which helix } then { summary helix "Helix: a post-modern text editor" alias helix=exec $MUREX_EXE -quiet -setsid -execute exec helix -}#/ +} if { which hx } then { summary hx "Helix: a post-modern text editor" diff --git a/lang/exec_unix.go b/lang/exec_unix.go index e548bdaac..40b6807f0 100644 --- a/lang/exec_unix.go +++ b/lang/exec_unix.go @@ -57,9 +57,6 @@ func UnixPidToFg(p *Process) { // lot of the example code and documentation on this topic but it still // feels "wrong" not to at least try os.Stdin first. _ = unixPidToFg(pid, int(session.UnixTTY().Fd())) - //if err != nil { - //debug.Logf("!!! UnixPidToFg(%d, session.UnixTTY()): %s", pid, err.Error()) - //} } func unixPidToFg(pid int, tty int) error { diff --git a/version.svg b/version.svg index f0fca49fe..e587d828f 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.0821Version6.3.0821 +Version: 6.3.0828Version6.3.0828 From 0d70cf12b6f38215a228fb121b33a5913721ddfe Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 11 Sep 2024 18:51:15 +0100 Subject: [PATCH 102/142] website: new opengraph image --- gen/vuepress/config.ts | 2 +- gen/vuepress/public/og-murex-v3.png | Bin 0 -> 221288 bytes version.svg | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 gen/vuepress/public/og-murex-v3.png diff --git a/gen/vuepress/config.ts b/gen/vuepress/config.ts index c30e308ed..97d1c70e0 100644 --- a/gen/vuepress/config.ts +++ b/gen/vuepress/config.ts @@ -70,7 +70,7 @@ const config = { [ "meta", { property:"og:type", content: "article" } ], - [ "meta", { property:"og:image", content: "https://"+domain+"/og-murex-v2.png" } ], + [ "meta", { property:"og:image", content: "https://"+domain+"/og-murex-v3.png" } ], ], theme, diff --git a/gen/vuepress/public/og-murex-v3.png b/gen/vuepress/public/og-murex-v3.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b9b7a8b044e803d95cbe00e064f17b49b6db81 GIT binary patch literal 221288 zcmeFYcTki~(=UAO5?yjea*!-JXAlG>gJj7$ExY6(VUa8n6c7-}B2jWqyMTZq2#5s9 zL6T&UoW9ljzMuDb>zw*dy;bM@_gt36?o3}jJ-_Mh>FJ)0)zMNVfY3ky03dkyKv@p} zu+SgD2wZIRpYFr4JoKLrf%?YYde(kSa8Hr)R~I}_xU6u2MrE~aB@JdlvzHS!k`a2~ER;geKVh@-3^rlhYIzP~N= zLdEwJ&dg#3HJ2hezwz+{VflEKw~*8dl_A~9iF>+LqcKY&6nU`Xpg)h_9-Ajm_^xO8zQsB;oT7j=gkXEK+fTJ5LmCmc`l zqS!sG%?uMZU5()d002ceD=FzbR8sn9KImDz34S5_pj&~i$MSJc<+B)iW%8%`9IeGM zw(swea7UQt8Q>(VBXb`ryWKqk?9Me)-yi6rJI-c;;4xd zF7|ikmUrkEDpS*48t#J(YMHabdz$;6#e2?54k)7oYH3L4cyJKug)QOoDRIu)+ zSTWx#Q+XD9XS+}4QYpdmPMSsq3$-MrP88(Re)vu2uKVE3x3`((&q3S#4OfEL-do_K zQfMgSwC@!rt_+5e>8ND|s5a-VQKsoB?)o$~Uq$BYHXO4ZAY8k}?m+^1?#9px;zaoT z9lih@&%3g@UG&)F9C%w?_JIHn$9=xW^<;K=HtT)+)suH4^F(RUp7r97r@Ya67wC-E zFJny&DO(tn&)N=VW6$Rgg`*V@0A%F-;nudU_TEf3_Kwc(vMjr;NERk%J6RSZQB46& zxRSk-^MgQ7`$vIV`nG|twvu)%@^TOve2b7%U^ z)7l2+<1Nd=g6?PfM?NTAQ}bW!-M#)s0gVU0zcrj+kWYXg3g!RzH@v*>`=XirEztk= z4KIDPneyw|d%=7>ZSC*-+PizR{yPiRhnhP7;_!P)j?Pf{pGl#?`)`BU+5U?T?&In9 zhsMs9-`>q0ie~DCmQV1%(R({P{1;gNO}5`Xf2Q;Af}n@{7yti8{m^ahJD9Droz$O?0uuHDb`rM2y!OK4lDs1J)?&OiHWEU-qP7yk!b0|< z5|Y-!|HkT}yO+1MyRH3iR%qsY&S*Z8!q&p}_7Z};b|SXcydsi#zNcE8LgGpZvQUTZ&r3_Rw81yw!#kfBD@YlwnDrjLL!2^Hnw(Rydn|~ zw)Vmz_QFCoHh)o2j4xpRmNA*X?YjRM0G~(VF87wRW`U zhr2ue>G-`aQs~*Bk+uGAdQu4I7_J(=t!(eW*EWdd({bu>EZcVg3*;#vA zD_eWpqel}E5|I*+loAxw7nG0^5tI^@;1Lj%68JZIn4Pmj!2gN*xAic|{I%u}oW0QF z2mERJ%cLIJd;In7udi;-e{6|~>5o-NS=;_K1utt~d%Hh!qIvz*W$R?^?r4v8AAjrX zKkd%{8(sLV2ttzLcD&-^!V>6Zv$x}w6cM-KMXQ0WxQMWXn6>a%R-*=VbqTeb9*U3P|$)uZZ#gJ!AggUgMuB%kcj%pve3o z_%}C$e($d~wEIGPL;ioc!@og83;h4``Fk<`Uk<^<^q)cgNBI5+uK&RGKSJPtMEoD^ z`VU|+)hd&@-i%O;7bYXjzV)xlqy;b#PaKg#yZycv#(SNW1xItQ-|Z8{+^;LIJFRmdw{J)@(f&BONhnAh12 z{`q8=VpJH9M){vdKkZH?BIfU>I7AS*!}9l2YKsrV{?qf58bjfqj(n+JAnBiu;)MUa z@((coLF_*Y^S536|JY06B)Bx#U#0DR?-gK>Gf;`Wb7CYWU z!F`FiKMrUb&zE=Uw~{5A635Wg@PDXfncj!xjR0PF5Jt(&d)z(Tyxc=RqV6+<0%9gI zGvd>n@GacoG3Khea*ro~u7TB)I8;H=B$OjRn&X`#rATJjACT9t&38`(z56hw^Z@xI zWyq}gO9G|)?C-#4&9_m9%asprZOwDQPZ5YDR6hiM_WB-i`fkx9)KCb^U>;Jrj`!5? z9>v%5&JI=OY3&%C3kLK=#*q6DDI!CGToD1W5^6y24laVWG5GlmZ^gN*GlfL3S#I@6 zP)Ex($vRNaGK40Urw8(qFIkx&}z*CqA zFtKTh%uogU)kP|)Q*d5iSzYm$*;8=y)3B{L&%+L4%%;XE)fz>@a4^HBD%ofGrh zuz+*;*~In9$PFl#pG@}_C|7Vg;?*n4Ut1gZy}Z;nOl~npTv6Rm4gFM!mo89cMx2fh z>aHXsA`2K zH!)7p0zi4L-Kn^*A3pyZ>FCXg${On!-_FTN;@;kD*x#xQdYLXHkEWQ*sFUtkY ziGK%j)nQ@FIaUK>p#@d{n1<(bPiGD>YF~*kfzf9H{*9kxn+Y31v3enA5qhQSe?8+h z{H89k7~($e>AzBl>?w@fUBp8kOs{WjVAxS#W>|OXx!~GAmFLnpsz~yX;EaqS-7Ev$ z#zvd-*m8S#?~AqK_Za$^OVKc_ALBTz5zf7{-h%$mMhk4+YVt@mW}f6B}fdd?E?Dat(cIdA78> z`0>Rf-P9a%L<)@_gcfjlfRjWs+(1LDr=Xz3KDXhB`v9%FISy1y#6`?JNl*d)gA(sc zx-{X7Ag2Ld&Ns-d?%Hl77UBvAGl4;{>jC2n9=o+$Fq;+I7Mw=vmAmM=d+j z$(%VoL;F_)It&zKPlhP;YQnO60RD^lZAlWLNV{lo5q0zk{GTig9 z08F)RB7g!=gVBL|Hv8LmA5|ObM|$_aUV#vJ8|mJC=YUU({5==*=T47*9!bZcM{lEV+TI;g;)7K53`Xb)m;$;W)z#v2X9+Op4%2)UoHsI6$d~wK`&(O&Y)-YTsCtG!z712=9`ie~u@~*| zbGn<+%{vHG?Zj(yo3%A~oQew;3QExsT|nK*jX(EUTb=3};ovNh{3V?H*(X|KW8W=gZpCCx@>%bCFIwi_%DSRf-hN5r!22;Lz*w&4I#a+Ti3sPk$!i>NU0eM z<(k~nW(wk;zzh_+HU`}T53dH4U$e602iCo&CX|+WH{58HS8E=^c|G^8cWGA?jte($ zH98eX<_bzs8^wr;Lon4UGa>Jqb*;3C(D6m7j75O&$FE;WEduv@p2+Q%Xon^&GLG;~ zPESYQ99v%V*a;D2%2g&kMh$Mlx{m6ya0Egk@WM~!7A{y`;|bsn3|poe<3}8#;{#n; z)6W#4AuB3?L0>nm5m_iq?D1v0275@FwyQEvx88PU#-k?x;N?9SFV0L;VF8w64FQ;U z5Pa5kp5yZ~9pjUDM645)05HQ$#czSwg;eA*GUcI#BJiKR*mWCdWVO+ysSlMN82y93MJ&!7*Lk3RCQ*Gv>V4p%hi z^UM{kdaaI$_P*EIB3G~{1!-NKPEhE z({%Xv#rqM01+{<>gt$M6#vc7H2CsQHvhR^ zVc&WBV4~S4jQ8t8G8H5~F-Bm%CEjCWdK*O!z6VlEFT&-`jf@)4cQL}$@?B7q_FCy^ z)V(IZmMjc4Iz3Yf^^%>%hmD8aho-wtXinAC1;2zgn>;2X*{%z+$!^tGQ*eDmup5Z_ zR@c=rcU~&`kpryFh3FLmS@nauW`^{EgM70xGa~bycgYxT+8qF zt#y8XM7T<&>$|@DeYC^}uaB6-fRqRDL!BM2iC=}VPb0KLevZ0v=5xRJWVbgefAL*2 zr&h!d>+|Qh-;Nd|NPF_^Mg%kCAYr8FhT#%DANJGWJuP&}&dXC-D; z67|j-wYZw^7M^TYX%q-i9$ds>TAS0yMgYFlr2ORZ<(rb*@t&G^>_D{Vu z{{$@_TW~3W^ylw+n}c~iCIa;TO}gEf)fvwfF(Z8wDUl#|nB@{T^5%g2ZW?o;WhI}DN;UBBKu zqXgfo7sGoayIf@*>og%4IpyHx<@IsJGgEG@Bm9Tp>^Vp#sLWeh4YLh7S=^h0)3MOCqbQ7ZtYyeDrPeF}9605)8Fq1(u9e zPmsnlpY8GZwa#}sSH;PMMH}Ikkg1n3F6y2Mt@;orH%yw$CGpXB4nNBv!$;4eWzyPn zK7L?aJ7~k5$nPX!BpcnYo}T7`JB8XrI%1h2W1Z?ZHE2%PO>p$UWo11VGRfF-$Nmtm zXr<6trxWxBI_=Mls2AbKfseKLAnVNuT&9wjT-j_U`UHpqfoiPc2# zr2xs=Mpwe4Gi2`{!-k6xmBSArn8anrY1d&b`Tf^KEk_VFSN^6>A zmu>rvRu7A7MDPta-}1&5i=BmBdh~y}J2y)a3Uz7d0Hf~NSTt(9yY!-=SxUSOjAv&^ zMm`ST_n7|91wU}|@Sl)>Td=qb{uA?NiVkhKCALm*;hcU*-tZ~AkG642K5)(8&dlxE zUl+kRgw-!%O26%sIf`9%7^UBnYlLuRE=nWFfCQLfggO_A5lRxQCGo=`&Oe5|%Nk{4 zMCBr&m|{|XN8^t9M9<3SGD<};o)JR zkHpEDWG~1npeG{N8cvNJtGCW6lk)YN2VfpNVG>D+na=mNPH{24V{cCT>eq%{Q`T|E z&CaY~&|YVNhK7cfk3E*FYZ?5F2u&u<$k(q=gD;MktNR$b!!U4|3l+rh>}W6zjYJM2 z?H)&MJBLK;HSqd0Eoe+u)K9-s)^C-OHz9Gn-rfPL?4~EKQHjbhKA3oz$SV2PuK*Be z7WinI(D#7%(~2mc*-^oXORY(msum?uP)fW~P?nw%ha*vH{b!64vi->&xxjJ74q$8h z1^!J;aVdI#bLj5w&J4Nv_@cn=PCob8*QsYwZWxf2SMGSQ)d`1@Bxn>Pz*SNZa1&&y zYG7vVW0(u{89F|M8mi)dMv0kr`V?hA>iiA5^75G9NT1MQ<6sXQrwTh?pDkPl1Z`%{ zf9MFl*z2*pA=S!~iuZ=ByWzZgbzere0eFj!W#5X06}&=3L{TDAx-ehFN^hFtRxFju zgFqC6^cyXF7XFKLbAg+Knu*LnQ_#lmumDR$RCKXKI~amIjmuGGPgZm-Lo5S$>S%K_ zc;_Rc{Fr;xSFgK)6~SA_Ml#~d0|B7+lYu$0=&&OY(*b6ZxksI0P!wuWFPm=t#!(QvWlf~8M#%t1yxx+0ho zk~j+$KG+dw$a{GRGhIC?#tq=Tz|Z4rD#(RR9YhhmC`N*gN<93$W7+UG7 zm{|vcnvZ>u3odrF{`>EJjbP`-rm^!u(mwZctE*2XCoZ;QaMDp1v8s=TA=E9jOgT6S z46kM;l=a8Z(Sg`wW8=wR7u(zPzqM|BZmjui5ZMYwI`uq;h9mv6TXUVVrKPEu0Jo}s zXyK|89_*o`gTo&3n*ZhyBQo?M+T)!T+#H7XO~a74eNJ1X?#K|q&4o=`)_QJU2apZ2 zaD|8%*?9Ua`17@@HGIAr_Vuo);?F}z;y2gxSGT@gEi_*c-aJbv3j)nw_D<|)Id%}B z@TGtLB!-(qr-sJh!KlLlxYWE{{xY9gz!dfuwN3OH!Bb8l|2&U;uakn&H6XrIn!A*) z0-Kk2zwa>aNSG+sNMz0WELZj8%TxrOjA7XO1K!TB!Rm+C&P zq9iD>|H;$n%|;CTc&sK_@+!gD;!?CD|B?wF3Qr5-se2yf_KM)Xevj$vX|b!2g_XSe z+jC{xYRE9sVc(CiI_|Rf*N;roOOXPY&sRa^Tk{lOjvJer5TO^a8~*b5@1fc_--z}G z8jkadyh<)7)F7mN_p`PwAKor6=QlNlnLy7?cw=Z7 zCT+VPA~VcWU1_v5#mjgYtCMu`I;NC98h{ma$<8f#={bv$>ZX3aleWvFrTopc_O7J-Y`FhM4;2W=xw)ho9^tEM zgADM4g@zwUA_@RiFqb`sT%TKVvJ*bDhEC~QKAJ9?D}q*uh%roO-+fYo@`{S3#GBK^ zsxp4Nw*Z@vpI%9T2 zmQ@|ADPCbONVgxjyaF_v1x|dU(YZ)&Ld0vy86xZ)sAX_@$p-<*roVorL+It$8>l`;p>xwBDgYvE&d}!h3K51H#uC~9*aSC zW#NlIVq|~m=lCm!jwVuFA6u*i-#PNr>v!{hcQP}JrzB6-Q@K}E$AT7Z7^U#R+i=T5 z5Hy^R!tf%}7Livlw!&?manyx3Wb5u8(id{A&fgJpxHgXi(5)vY>2>>rJ$;Y;ONL+~ zkq3OmRBlxp=0evQes7xP}7IFrRT?TiFdU0`rJWY>xQYT{ZC^+< zoj?;}Rf+)9Dwi?ITz_b>9#c-;F|+L0S)PrPd$%Ssen3;O3^9V8xxIlV@!xuNi7M~6 z7)gkDj*(~wq^p6nY+~GGBdip4f_OEH#0j6g+-0j+@ds5HUWLmUlH#Rj$yImM)Q0M) zuDvEkB|FkLF~GOS&!0^PnrubI{G_VXQ&v8?Kgo>V;>=v%ooi=WBYk5n3nz%WpK}8s z{TAs3^se$`yPp0=cK&izTtHS9?Gh6hJr@FL+!Zs4hYiEfhsh^29YrL{iv~8ht{Dq3 z@n~@7Ga78uyE5S=B_;G%S=nog&1)Svz~rdC)G?M(_fePcx4odlyqMA&rSSLD8J5!nfqU|2st za`nI1Zsa~_oe$lW#Z*KGL+fs7x@?7+#>PGRAnsPwGm}^;Nuu1Z``n%QSH*hco;0xb zUF#4*xph-guP!dEVg$~Q?t{;Di#Cx|;D=FGg<%h*NC3*2DHtr3^OSV|^F5P6&HcXA zivG7x4rLa;9!V&|Tu3DXtNf!~uznF0uh-YsYA#G#;}qC}Rw>7KN4s(89wY$l`P_Zz zs^GfZ9jX$YMVB%})~5CcubS_}FmsAbzMQLVV+mWB%KVd)_s{A_wzlZdOCNn4Wvswd zZc(d*xZ1OPOhCu9~VR_cz??0emxedPofC41G>3 zu*&!%{T6&}-SxE4O>f- zFX55=QO7JeFfn@#NdVLGa5`*!|$^8A;66 z;c#;^vuASd{jZ0=;ZcEOqi(<*HDz2JYkK$?`Vj{8Vc%T;xeHK6hpj=;R878uk<3J5 zXrKhF2hzaWmKWRALv)#R)L$C-e5!(0=YyIQky+;9kuQ9rBx4_gX)<%&4`Tc+gr@i7 zqMmN>%8+`&**KE;#W5?h8{(ZFe`(*dy(8DqsXnPb={ASVl8Q>D_ibydYvO?xfFsvB zV1_lab=vpTXs^E;xLp;4b?&T!zBN1>#K$6xt}2~1{&+7U%alq!;E75}am1G}-sG?%^H8Cvn-Atn5A%`ZFsB9tKmB z5%==2*PPTVz;Dd#>^(gEqJRqvkMx)LY@56Q`Qryba<|%TV5j5ke&oph>5|uaE~jY; z4d5xcurup#NiWMeGQvJAzg|$)Ddp0aSaqHlDRjAk1Ue*XRPzz1D{(srfyi3tm!tOE ztRmO#V{LTZKAOAO?eZ~~NI=)BYMgeYhREIp@>Y$7>ZY@8u`u~Ei+iRU14v+ep#vG22_2#HwJ^R_yodt{gRE88CO(NUmR5W~w#!|(x6FvFF6$fXKd9Mo za*TMNq+ucNV|L^it%0++w^4jflv!7TSiG znSr~vqhw^>x$MwAjDluCJp>j56)Ns|eJRuf6T}k3?M1Jf=Ar$cWC(2|;=BIMGH#!>X_M$*;u^tVKz_0}UIT zcfWT)dCc3Bor=C7F9PMf(V@1z6i-9)`u5JHAv*IcC3kaXslvX!@PP#9N(uC~YOSeY z5dzu(w2VQVniMZsF;j-orM1$%K}-SyUGMDO4`&S5P2%&Hw+@=?&7nxMIej?9`Kdg| z8jcMP5;vuhg$kYHH{*jUCp3*y&@_5hu6ufm?Iq+yb(WA-nyr zRa9GJx=BADx!joD&7Rj=wjcwcH!r$A%urK|GRgP`N(*luC~uL6E2oy_$uXo(glZRO z0!u|@IkP1^m{iuB)NhCT?)wj&*6gfR4m_}FQ)Nwa{+Jj58zH(qHJ0hWa<*#|;QVgu z#8PI>YW})!FAjNbFVZNY=yZ`#n85La1PHQLQ^XRvgZVb5?Bp%RN4PZxmsRM4nTM1s z7%yC}#P^n|vb!&5^v}K=c@Z8n2Gb$;&d_I8$!aJY{T|M&n6G<@P1j<6%P-{^BDsC$ z$~NvFc>aeRH!<3wtF;n78cV&1r)#bcZb@`(Fr9UjP`(&ZVoIXXyMsOufN|W zyyoXze9>)WSy5`MSt5a{-*BKUO`~>;7J#%$)t9swN)cukFeOd&yk2^Bw_IlrajnRh zm|Z&eSb}Rgi66h@rFGKo?)Ci<4~^Vpx(unnMqjXkd5| z^I-TBiHhNYw_&3kdT`l=UWH3+7uPb>foITomc&w3j-qn?iD@r;v8*ETLPn*0Jo4h$ z(vA8$BQqKB+colpdKSt1vgirTk^DVeqo=r4)F9x|tf)7!f)TZj zDCxg!2&G2c%(HV<2%wt*^e2v7(hQ6uw7S^XJo^i^p)6E`imDdyrzog?95BP zxP=fozQ4qvOI@tFVrjfcUjdYpDIp3V3Z;@Oh67^&c2t?)J;4lWo{VxpgYvV!5``5z z?|A*@Hw|cn$R=39gbv`-hchR=`d~v9d2d9o*-1;kO;c;a7ckTZHT85iHcMXnJ7ei9 zW>^~Uw~i}j%zoetl>-f|;bpXRBq%NG=)WUQ2(1%FoG*OK>nj=oEzUr=f9 z_H^o?9eG9RP*lXQjtoAmzlq2T^B^k@K&-u%omlPcaSBgzFZWm(+RSKl)5>cg@s9W~9oPp)r8F}p8$2gy%V?c5#SDcS>j0;uqFkt5acuGPA6gnB=5?J9sC(l2)2dUZe zn$cmRSbbe0T^pAo38J(uf@$#7 zvB+gW6BK(gxeKp9WylV-JvQ8nlU`9I_UjObfTDMv=ic-xxlgNW+j@Mu-^n{CHbiyO z4sE%EX-E8^?t-0zLqJ3X6Oee)&t-ZwUE7TaXEMPmF5p%$(8r=SLP3ovtR&>Kt7O}D zLvNmpO&|(GTM3j%_)bCeSM>KgEl2J#(Oz!r4^}Jv(zPv6c$7co;+8K}1|%yX3~XM? za#Zg{SyF%&&K0aYOl*0Lt~et3`0B!wR!4@3Z!~$zQXk)vko@K&sLM4r&6M$UVrDF$q>##fCZe#+M}fD=`JdSX;kNujshs~BgG5dN_K)#q^BFE zTRvCnoU;h)xo>zwq8n@l7%N>bu6Pk$2?xPQU~LC?Ar((IH#slkzzP?8!OC7(*lK-a zzV=EAVQI*Vy)65o%s%bw#a-RKXN~U{USom9rW*2zhY4|_xCueuKe3e(4qYu=0EiA* zQgiyRgc##u!xOmAN`XO_hW(!nJxW&9gGz|*H}<~1lo*XLBgY~}-xaS5oIb^zhE&5T ztuv0L-N>>AJj$D~cT4T#6SSd0j%EfuW`UdTeB#FY;wGKz28wKxDm+{hT>=aFdt4+c zBJ8F6uXrT1?fg{RNbuBSHIvyDZp|_fE{v@|LzTQ-w&yV@*8^v0T%PsQRCY;+xH~QM z587enpz^LZ$yz&g>FMLRa3lf-G_*YreJ^{}9Me!UK|zVXgXr#`@+_s+ZBNHy?#U&_ z?pH(4Ow_&7;746JoaEjj-x?M&qFtk>qQY|Zx(wIX^R4|AZRTXfcWpv;zBIT^U;esi z@?BwpRA}L2Xz6pknr^VeEhfz(D4ZBH_(+`O#K-%H!L2f~!{98&`1LTN&yN{K@!gtQtdJ&>C zwW1UT){$A8Ag{wQDnrTpWrgfuat^uUQfAD4J7rxRveL-rpU=1fvLgTeH(sgI6VlVm z*k)WAn>)iHB$3E$BK+s4q5>2kJ0_tiSBabw`q zU4+3ScTQyzVoE!ky@o&l;ZB-Uf4+zMuj2{BN zy56(1>mxJdHz(?!$1eO_37*dxG7JPx5JUD~G#%_rRKGe|Xr-y( zKxYB5v{jX!nosEezyvMeurPR*JySw8H#b8&%8op?vnnZ|nI(F6XT_@Br-LYrz}zX8 zaGlNq<>Nt*06dC`$#bm{D@6NJeE_(ATapUze-#Akj%wgW}xQP9jb)= zw)a{7yo384uPw{JWDYX{bI2cy{hEyEWbCfRFF|R`C(H})!S9f2FR}!<3!s6E z9Pj4;5bfo;fsQk!;Y4ecy&hMW>LU%2iVKE~1Q4ALi$>0mErh}(+xKt` zmm{eLo}u~@B_0%_jjwAg^h!aMIW%{P`9>{+0yfyiB$Z7Br#+yUKiU5>4KoUuW`_KF z7A03;7iMX0jurYT=~$8B$d7PlZ9dz01`BABy034)7KrMy@$va)Kf;ZQ-Md2qv{+CK zfYNcjf-DOPSg(UT(^f$&LP zRIEc3$7Y&eYxRWbbx!Mnn5G_+P&ikth#p{>8%)T|PxznYM{hJQS(>Tiy>cSBd)N7S zLRs-55xvML+ntk0J=6j`=wNH(<@&};V~Y{$W?IHX93tH32|bksvRU9P`lC^3$mE3G zaY2j=6$XlCq_)UUHDu>tE0dbG1u`V86s#GUg;;}}GH491{=UhxyU`@f0Dv^sT5J90 z6Wpf14kUW`o%YH$@^aQfJH8GRk33~t3_=8ru#^(+wjEN+3`L^Ln%WZkG6=P_ftxh{ z$zgt-t}h^CGpuy{o(9is)v?gy!_d>kvOO0&-$3(&UD=$b&-Bl6HvHXI9LHRuH#?>Z zG;*2PhNoz7NXEqQ{n1rt10Rr;886i-DqGopW#CPg>D#WXJzhqt`*8^J`DMFW4<>3p zOubmbAV(Xg^RJ#6Prkc{y&6Xs24Oe`K3cF9DRio^5t_%eByKMj@K!H>-T1M^$cfM3 z^e5Mxaa3ek$oKvao@I7MUNJsL?-yR}j zxq^7*cRALs)yFP_C%QY>CzdybMxsg3SbFU3y`aDN?gtCSi#zmkaF^BYJ``zVGV_@5 z?vj6x$4M~i!khxz0Qt7N9>1_EbK@7HaD zrlYb(`-JOyKR)d*N%NW@PY0g4O_F=iV{XcH=^P z|D-BK(O9{Q@t)T=j6(W@Z-_4RqPk%$7&&%q%qZb3BHEk7&pY3Wfi#yQ#S1Hczh1+t ztVKsL;^T*oU_7OYpB;LsudyJayx;ViAQr~Jg`#I%)pq63dDDJHq|;GLv{=nI&oBZ(HF1ZrG% zwcw(}{(NhcZoQ=qA&O}j7oFQu>r+fSGm@WlnLjqz%krD+Lf5XyE=2X$yV?y8$uBc77)@QbHb{wMts~WWT3n_I+^}-_EWBBB zCWtJq8q7gfrsMF?*9DvMIncUex-z*Ka?9{A#k}Do8 zBFZvlc^KE?#276f%9FR?(D&`?b+!RDO&rGL56IU9Oq$w!_KK2t$YmCh%?17v9VS}EJuQr=!E6utBKqT2|4vpaS}n` zEp*Qdxfh96`Vebs)(J~d3h@epsUXx5w8tF4v@nY#i$qMdbzhVWg*f*$41Ok9`tp7v zA9{ENpH9gj699sS_>7k_p+~`9UIV|^!$>YIadk%8>#LxbKlfu0bwn9PUuxJQazDOg z1K=>i!W$NwZiY{Jy$SSsb26Rwm)vUh&LpR%!G1^@6iWwS}f>=z-3* z?m@kPh(KS<#;^;Nd+c?050*}wQ;&ONw70ScKy9ck`l0)kS3p*=>1-C0&a)+Ml$k|A zf$VjVi;BE{&*%1gTQymGPW6XJiE!oyCMm{)U#>T01Mu%XV&~UTr1obBB0+_wlhw4Wt#>I7oc8>i_du zGgfNTm!7rYwn>A_*4?%Eq>JycY#j72COEp}!`h!LA2zfPwsq>@O?W0xQP9V5QFiuvSxba%G}~JY4GpflCLU4yvdGG?1eI?b zy7iLYjut-S+T&=B<;CFs%j1+?pZwdMDb@#d51pTU$l|T8ke!;|hQrXBzi|QS^n1y= zZ29I*8Q(O*NiaeIRPk7Da?%uQ=2)hNfaP4aS!Q_bMY=r9fHiIOgaS3gqd#3m#?YQ& zorsqu!$AsrdM8{VJ^Jga=65*54-IVMkv0UFhlkrk?mbajLoEifNP5TgE^q1$h=70- zlIc!>C0)b)s~fXQ@!=i~x*UeSv1Z7Wl~6W@@qYP=G$m9-G-HG_3>(5%Rr9XkaAs>> zXhPP2t|g_cD{%NqEQmv)vp!3aYwsf$Q(7Ey-juC7RJ`R~RO*O&8O`!2q$?!&M(&m> zC9<~|pr#fZ#pHVb;vwkb3H_-Y+-o@TUgt4kSP;nA{QfU?)IO`0f!QO*W6=jCAMSDb z5}qtgBbMoi;f98UfQ%|FI=|N@E^ayFbo-^YfB!Z@ zP+SRc5bLhQkvU-|lrZV4DM7sCT;rXxhxUTBLd=4cXhN5pcS94Um-4#gK?>6oSfd$t zV@)-St(74Bud|u)-3l_O3xe6UT;rR^@o=p}I;uLM2LU5Ce3@H^YSDQP-9EphQr+V0 zGBNuxXFA!p^HQAo*_H@1&_9HFXA1THcF9qT2kEGMp%(ij8$()C87Z^l&k_{utAQdS zAcsIUQl5kLY6E>_78hHj>CJx)H8_3zaKWF3(;_V@M4%u?g!^7lxUvd4)Y(#CO1^t? zFp=@{i=@Z^zCVo~_}&9t>s1D_&Cu|xUAL8@8kiG1Pabs9jA-4R!WVr+?&-ghf z$Agoxp}P4?`f)Nkmz^HWk~Ap{Cb%7zb7gm#s=RFsRO@?=qJn02n%T5N-z=ZcN(LD7==jE%0k?M^Ln(o*}HLsu!`vP@aJduF){8JpZ9Nj$)4?dl8(kU;O5AAn(G2*M>$#if(P zomp>W#e1t@nHckQ_^Yc+{Sj?{eHtQ)k|rUA%}BF$5dzj}i0P^=;C^NiUUhx?oMCkh z55)Ooq5tKwhqz^UjFW9SP%apqNZ0Kcx|8O+gQdIzKk02;Xnn`JIJJnZfH639$kuYk z>`tRMZ|QqaPJS&c%U`U}&oqe6Y~M^fP0KLCDRipD6Gzb5K7wd;g%Lyl*&&G3Ad@Ql z1_b1`KFY6DRY~OwsS06EV$xmF(`POuC0l|G-_i)-9VljJ??wMk!+a+KXUhrK=|P@b zI`h&(kp|O`2eqUQkH*oLQDYTiofM0h%6|}gi!{0#%aZNFUQlP(d5BuERjw5x)ukM$ zU*Fw$o93FFVjI;XCZ1shGM;C!)+z2*aLj z1@wJmDf=mj6(E6?IWh)Aaz=WcqHAkfLnW7s2VEc^8Tpx8G^%Ln2Ql9!P0UhTT#$=> zSDt|*V5ZM6v(`<*JK}17`e3UzR|9KYB{ht88@bQrMMS?-86LcvcrbG+8BdVUZDHFb zp7!=ztkpM*$Kb;gRckBO;UqEW{OpT+Piirkv9MJ|!15KR+Z&{C^W0F*sz6Bc)UL^eFk#N0KJn?J#9E~DzTWO27D zSmC|*_tGU7R~{A{EGy0PUuz)@7+2yRj&@F}Asv~FA7=9=JoY}U0oGAz4}dVt%MS!E zl7Jv4Rt=LZGN+(l%Q+v`7l3y=AyvZD4S^VBN-(RN*rD`($dG#`5LCh(boix~colmZ zZ>u%ZnF*oNKezWxzlpA@Bwt~v=h?0viNW}6>oWE2+r5k3s(X{pu}0Ur8A+@H;%WaM zOuqQd z7I=Gw5|R_iIE{YdSeC-nIE_=)2OTmE9i z#KbdeYq6sK_kVwV$Q#U*BM;vZkT0LC?>E5I(TyWn$w4dQwl3>X#~!P;V{ew#8ZykRj^w2do&l%4kGyBDkbo!vRa8J4c844`QD5pe^vbV-g;G~k zao#g9(6tFr5B{GPAW<>%lD!%i6~z6vyjv3S9`d^y#fsEA;5LW#hGo8X1<_mRUG#{W zo~~{m>_JCFMsje9#T&3i!n75Vg@Ea60I~&_tpyhm?Bn6#VFHsE33xnkV3Lc3m6g%U z13f(DJv;#kIiM5`9lhDnpJku8h@?j*pNnd+rN631)l2?COj^}7{MjaF<~OC4G06@X z!AuX@=z9U-Xc9a1!3)AD#ylU|Tgbt-EJbAckKI=WZ6GHcpL70AYhH?K50Di1z}5q!eytmgB}@pbCzo3#O18|&4xlt z+f#q`R&8XJfN!P0AGG0rVTg`}VP@rp-_erO!KVl^<886tYSE2rWB5Y%Gta^LyeIj^h5`W|$JxKH3 zJz!Vs28Xvw9iEC}8Uy-)VOW4MgNIV^<)l*VhqIqbcYog=*ofRLE*f3|X)QLC%pnrho<#t(QU^F+;U zsMTfQA-Zr5l<%h2QY&^smO_>B_^nOBhrDw1NQY5lo?PEeZ5l)VlX(s@v-ie!bo{Fe zW@cv2$ju!Z9Yx;ozc-YZ`#W*O{m{Z5h~j^LE@NJd0P%(UhP~Y66d5p1Pf`iV zG+}t%*PtHunK_4pF;sxIEei{iNAtMKKsrZNqQ)xK%GF(6P0jW*^kO>{Yij3w{iloJ zeNU^0g#|p!krpfFJZjYt^!71FO1U#zumVIcXApRXwy(hg6M>DN@NZZk+4_&HVy#+a8wjZb#=9aZ%}ph51aPWxkicc{^4myhl!%P zHms2Zih(Pfa+lppg%WOC9v);164(V0QZyKF;lH@kJ75mrC;3Rxe%+ChmpJAc;2aNY z-wT0+RB^Up^MAR>d+7Lx9VFV4Eh_yED-{WhM!>c;L@;G)XUF6>_FUB87*IT@rO&<{ ziiY#B)sG+oJ#7+j{RiLkU~dew7(~vt$rV)@{yoN^aAXC+baRkznNHGx!)2QKcJyi% z8e+GAU9fb)UlaSL#mx0QFOb)$-{HSKC77@QT7$EnYaKZZ3=e(o zo00qNDbQmF+5;y4i*E0$Q}4V6JSBbY(SxhvMWcai=kBP@SN2yTv42Sk1s$IxkfV-> z$j+$^Gk<;-D(mMaowE=k1tpg4ka*2}CyOV$aG(vm`~4fY=ZV0$Z(`y!-~}0v z!QiJC#$uiEh?@8&w6D>a1{v-7i9ySh|L*OAN4!a`ajRo)0z;Hw^5(g?9VH4-W^o@LsQFw*`Ft zOLK&T{?_j+zqoiG7azX`gR1&&?X?@~>o3(8Up0Qnw z$S^_hetJV3A%_}L?f`=0>E+`OV153*Ex<^Tl1^E!#QTjr=VjM<>v(nge5RFk`@E)i zpkX8sX;i++(M#S<E!~5u7eMc|@Ed6) zmSR`X=lKC&o`)S&g9FGstdp4Nn_YK{0?1ft1WkNV$AsmZKYU zNha_8XJTP8kX@W~Dyqxv@n?~j8)FHCW2(TiVSVSGsJ>v}b3)KVUE-uwgEv-vy~9Cg zqq&OcW^-f;vCC2umJayf4N@Y#Y`&*fi*w6`@ev!HwW%$miQ20Q@0 zH7@2^I{jBhqSt)^E6f@f!oA~TCL_NinXccsd&+}i4Pxy&EVDai`?@$d}eEhD-<1hofoZK1IF--ED{{*A|Nr1XfKQS^C`>Ld|@W2$qM@eBh8kgz`(0 zE}(6={^YRT2#N3GD*x8jpzAIJFYnt~jOsZ}NH_>dnsf-AmzL6E2~3sJEPl1(D-p96 zTb9f^h<4{{e%_?${h{e;&L@)a4&MLJUzGm$Mab0&qdAseGf=#0JTy}B={hw z8D)g-avoBfyEw_oq5MtbZ8mBg3^X}1i%2&vgg%Xe`;&^_lR17>gixe@$a?SQrWyFS zmtOC6=Dq|osfD5M;lKe{g;{f`1J9rm7r``#FMBvTFS|?=M|Ok%nx=>UXupx~Pvu5x zWfjs*&iqD>#m9}fMlCdJc)#B;VZ-Lh*xeW_F|a_4wo5KZynI?PG;4>;Rf~IYmAMYj zjNr)hanWV9wWj^$Zk4M40hkOr`jFN7M6RA+^_oTF8*aVm&_B-pM)C^n{felRHX$d6 zBsDDtq$0|I7g`}gl*5&kMX&$C5fmTEQ39pbv-VI0)~eb@*>_2=3=hYVxGoxshasz- zOYH5X8xOzT2lagGg`OVFY;44zW5%y{gHpj@t7%foLsax>&8_IZ>l7Lk$pk@qL}0Q! zb(AK-hWN{T@3a0K#yn1`21>85+wEZP*<<_PN$1>Q8L;Wp+T&99Ppo2^NV|WT(k}3l z`|6urU_RXXQtCAUiKBV)1WpE7vxQio`@w|F#fB6^{N0}l$4Dv*n&a$)qgF~U5bC;7 z(Zy=&cXtr9-IUc0ac;ZpI~n32pOV6})6mBH&wBsG_$dC@Wx5JyBSf_iYCR)|;~zL3 z-@miIS)xe_(%c{Rd=v@Lz57OF-$Lx%Yk18P;Yqab5Z^Np(Ee|%Dp9o@Qds|%82#OG zih*jIoQ}^4q;%h9Nz7R+Gceo)n0$HJg1a~OR-3jrQ|{R=ikVqnj_RR#|I z`-ODWO1x;m8)3VX70-dsK9qZUAUq2{(RJVIsP77OY?J(TWSSfwA8)o3aohg>$i1q-#fFe8?wST z*7RUOL!-eA%`DT;>2&i*!-Qej?H4`9TT{Xpki7MuRML)_aT?T2!4|Ow`btCZ`5czO ztop`%|C-WhvTLNgKgjW^(CyvcPGm_RHb|Ld`c`9onsE3vQT$*alnG_ZHeKpY0Jy#b zIkK|2O_1I9>YCVuJrM!^`GzB0ccEbL4-2hj`A)8htBG6@2D*&gUp-$>7uMBXlzdFG zOJc96VAXV;zzbPRLSeC%f26`Z-Au5~4?sLI)(wi%0mh7@tWgW z-zlSDG2{Dj2$GR3g}-#biaHtr%b<;FMc7ihzX4YptXXcYzG685)^dftwuIXP(Hh4@ zwHO$L&wpnl6|12oUDeGtmIam~njA8GD_w>~LZ3(7<8}=B= zl`=U%we;4FUCwg1_uy%Hq=};aE)Rgf19AWWbjk2}RdFQt?sjr&mOuOMdu=qi!f=_L z`|?53N)UV50^W@+lP?n_q%mnMBUN<{VC)vVRXz*iG@4w;=$6Tx#Fb=qt6ujx`A-ve zRxY^$@qgfy@yp=>$^b|vS}ATn<>0@)@!7S(ddtXye>}3~ljP;lMRWX#e*#UVjHI7E zl5*n85Rt>NAGWd1D||y<{eS?&di%*N>#GwviriPI(=_>i>-zbc@93YTYddU#_^PQj zhcATtt#P`Lep1QI>EGfKdTP6k!iG^y0TjfsZc4Or=#-Obx{IC!*v_S?JW~zkktjFZEie` z9ZyX9*~`k6$xT$f&gMS^f(L$(yaq>`3yk{O3K&s zpMhbi%-UuLQ)HTH^ciz6(@}<2zzH9eV^=H96h-_&M~C{IUUdeulLc0tmSa~^K{t4q zRp=wkkxV~1Gb2H1)KFmbob2=AQR*yds{`Yr6^#To6RCj7hXw95 zKkoLsRV!GH_&ZEeCuQRhZC=3NAT{}B%`FiC3xgsi|MX6nJC|B^ud~H|c2*F}(9rPk zxWJw-1qt)E5?R8qbxDeTZ>sK!cV+{F=U|c+x#Gv}hXnCg!gJ`*m~9aIJ5-0|CselH zXVemnl5`;++Osv&;S9L%Tx~(aH{rrTv;dR$3OOrV3IttVQk;rm+`1IbK^Gq!UVh#5 z;$WUWyh9ED#MFnD;YD4dxn9A-4iBmL*Ym*l`yb`UeFnMRy(g8wFlojW|rp~fb-?}Q#Va8=5GP0quRPnlH|CgH& z_XS!^eb?YAuL#BP{c}Zx8v)vVWo#y4@@AT5T<~|MIWQ09NUbQy-WdJrbOkU#W9Rn- z*ZO=Ke-Y$t5Vhhlba%E|?@E(encuq>sdckF-f0{HMyCi-FQk%-%1ngVd@9tTUgxhI zuCxB5qxAt#74hp9B=GCe_}e@4#rOb{^cotxvN%Csu5Bm;jihaBb@P=i1(ZcBkd-aK zWh=TF2H6e_F94N@gfHNm(L|blTXp`4w+THzV~CB<>nHJiuIuL*^mghdOAzlt1=O2} z$tiJXN~FLAIEP!I15G9Tydb|~w>H0T@&%t5f(wYz}_o&2x zyj3@@zJXoCOI5?WzmYf_82VA+=R$0*X1Q=s#hu@OeSzHXGC0dHy+{z2(1c~ zP%j?40koK`M9VHxyanyuQaj8~trgs=|EHqTs#=VcdrIK59}Xj=2Nrl;&_=krKm(8w z9N9pH*vJLcH}tf$o!#iaIy8?;3`0z(a@bhJ-vV0f^?h*t+cwH^B%`7MAYh7T_QYQ@ zdA$lr6!}6*40T2z9WJfOB;0#!jwo7H1^AEP@;txy0GDBnm9@zI#E;*l%GWK9;pMoV z-1raXXod6$ekpv{uG35PxGBLgg!=4ti&rTy=K7xnRVK&9^SPO@Xr~~8SeIlJh?;)Y zn54KcNH4B`TfxE@XP8}T@%CGB8cS?*-i&}Dk-wYYv^Svc;CJJe%Vt=?Z26_T#&xz- zr89YQNctMUP$^m)H5T>|7W;-gnR|RNEM#HLV?M4TWz5wol32WKtryMrc%;KsB*1Di z#%Eu5t~F<~Z&qg-I}ANo{ZN=GX_CvMS(EV+hS2AM@IB}U*;U}LzYlf}o%3MsrS#zG(qzHHBxiSh=4PIy05B&tM z#?PnL;xdGYmm(1z>*V_$ZVWOKpNBf)IVm}`W}g`0T|Crf7wf6YmkabT<%EdAweBvH z+(ZY7mF4Bu{ery6pJP1*7aj)Uo-1Bh7%40c3y~#KG`5+Ip_pFhD?o&;B0NTxtb>nX zsJV{Hb-egXT<$Dqyf)pLw%9Y4@>xAkXIZ>Hm%&JOfdP2|cebDcL5}j|c^$NyLIVV3 zrYT^E%W$@Ca;p7Q+OC!YZ4v;ikmF%CT(}h+?2GQ)`B$UaJ6FHyo_UXddn>O6Tk`!i zdp$a2h68{=*`oOY7ibS~*`{-r)<5v&wb!@2k-0hZ4aT>cZYM8p-X-Q zwSr2R>B2WSo|7}%)BZ`{TTOg(*+Cl z&D>vidfF#VA0(^hSVlcquIZMPuXp4NhCKBtanJKRGccYBIOX8 zaa}^3qa`WWoitHLg3?A0CFf4CULR^>iECZIjvie5xbDaTAdNDlrt*59Q==uZu{ns3 zTiB9k0qrnp{pS?$XQi$(a~1bKalpfdw{uK}FdL+N*c{w27{I6XxBTnsmhkxl5s;NJ zf;-J8QIZN5{kl^?NVsDAr`P#ldhboXfS<=!$~kadEYBr>GSq1=;wgs zdcOjU-&VBkF(DK<01sM(GDVQra_HXJm9s1(?Scptz2`FgEnLNq+^ND^r*TFu04^p2 zye}a(V_e8#PiHtCOyw_1LVOb(#deU=Z-+#j=s7GQ@$y2@+wR@pizPHnk%z>iZ1PNn zr_Qt-!GHArL~^zfDIB}~w$<5ma|6x<-RHVg41aQGv@Fy8u!Iy_UFLC6ITXx!sV2Tw zZz>x2H1BVnDxZGFg|ixjOc6WPSmvj(>u_L46B9tDsws4z7K zxJIt{tK7GPe(}21B5$o{f0q{8&CDs{0|CD1z`uq|euN+FPY#hmtNGrH*8P-)MU(1O zrMnt`_ev@Shg2!5s_S+L3MPg}FPayTh+vu1j8a6?>IW#p_Bg!o*-u^dPON~f9BvU1 zz>}zc#yvjqoPIvAoZSr^yJRv|`Bxeg)jmJyyoA*00|_feBblxkJ28Vh1Il5qHffMJJLwfGG4{_SkO z-4oQCzC3A)Ss5U1X^qs|M`$pqz0$MbDYfrFHwRSs*TIE-A6+mf&UQ0ahu+Cj7Fby! zpr(RlN;6BjGOe+>GYShgvRD)p{&4OSUlIuc_??acWL#&fKkJ?j*cfrgzoa@B%^6EH zy?JB@V2%En9U=a;s=$yGITP#xrsH66!HOl7lJ_ITRK7&P{65 zO6OoTN*V;{d1Ws!1=`WTXt=nxm+cSM67F@l^RH+vuks8Ea-piDHvRmi-kHk8+C4iv zyjlUD1s;yqVZ8%WLIJH+5YO`#aAcuHrKQT~QiPNt{l1BsJRk+!IV>9=?(PeJN#t0} z@!KyyB=7@90fp_f&Rzb+?Bq}P5zL$W`wzMPpof0M8X10^22;^)ZKY%@62k66bzLhZ z=&d_E~1+RHvY*{ zteG!u`U5t*9?P=Q`tvDY`8m;`M51}8zx&_kIN`$yGJX10%+}z2vs3im#Mca3 zc*hs-5V1nJ2hSq0*Gh1hH^5Psy@PS^NKE=;3%c1$*0u=?3<~eB&Y;ljfi*_m)+-C@ zokIXI#DZzIsS4@sD*p}XWT6HQz{Bs#qWd?v&#s&}PTk!xGQzT1)-4~xY4#h3gC>ku z|F7~Sp}aYZI-ldpH#>tbmEd41w2jia-$6Jszf67k`4WL9l_fbF%0y z#ksTjIZtkABfKoN-4bw$N~}OQ%9W>C;>SY3fc=T1;iH2;wT{$>0~=>piJ!o#(M`4lW%|do`*mAhJ4&^YXIO8&M_zNj2 zyxk4Ci0kDrty!JZCZG8Wm1Hnn=i7moOA2!*yX3ekN_fb@J59x-TW_DG^5)=jk2>u*~-#Dv@O)})CviO5WRQ3;Bt;eWn-uFWI(EnuD)Mffci z7_-0HH{-e~ z#1K;r`laSQ*1RPYmHIq|j+wFtZWrLkah zwUxQZKjhSH&lY!&7H%P3J{EKLLk>)M>FS%oMU<7oP^1R$i;WV^^6y(r#T|G>S}c=G z(EaP;#P8p8I&%;^hck@epD5*!@s!Mp-Lywg{8&b3ni9~t$}oMF1w3r5RFJ$b%G`E_ zWn}>ct}nkS-ZLX8PVKm=w$j8JBsuXDx6xl{s&=)-Xj6kb2miLLZxAfuj=O zCP$q5PxkC?szJSv`}#=~tV3%uYLE1R?*Rq+KUU`5vEkrK^li|wzOfFgb4o-mcw?Gx z2?djl0T(Bsal3eVK75d5dk`-D%u>$cBu#yzmc|0QbX+esQ9e!b{-ub?by@ml-P^U& z;ktO3`b5uU`nYs<^gCpUr*HIS8i*o%3pIu@bQ{tUW$Q{Q&@tn@zoCTpC+=(*rJHl!T?)V!$hWq_ykPgT7B{%^;5J*TstIDc)I)1C(h_h5A$ zyab_(uWK~ji+5fejAGr&WMLI@E`Gb=l*j#of>>x{-gkrg^_F+BUyXO6+VKS%7(H9q zGkQZa2k@BuNG;UcNH-ou4#OWNvi@W9?k+x9%?esSV4@`wcD>ut5$KBThqKUMA$i+iMVq6}zluuwm#syK4X)ED3bg*8=e0#BN9y2Il2T_ip z2FR&`WwybrG&J1ywDaB-2~WkCdc*ysR=St$xaiC1q2C8Vq@)s?@*E(I26cfP^AP0sZ6 zYVL4tLPo)?byzn`?^TKFEwAfcSs?3BcqY7X4F%Ktp5yz^d;>FQ8NsLd5Oms|YvgYM zr;7<&_KQJCsgz+L4iPRAAOwdW+Js4tHe&U zg8Wd<+MgM1`8;Pp%_}q@V0Z2y>}AA?D?9RHYqQiiB!EPG@*yzO4S}=FL@M6M$Kp5N zlG<#55veBq1kudqW`gtA9a&_m#Bo;xmv|&o+Ay9SM;2tlGjZ5R%eWMp&KLqd-<(+I z5)k-C;`H#uxJXJyP7mhGo+~i6(LJQL_@bvkJq7SsKU6`v^r-p2cfu(IthF&rBasM^ zm?CoPVA;5*rI5+;H@^iKPO=fL%*y~OrvGe5w*_+LeNwT1B{bV?{rQP4 zl~ExY-zLJX;+9F;Kur;~3hCSb)(aVt8_JI9$^3yCgK6r9e;gi5-Tj>Kv&NEu%#`JJ zOu4;51!X$+;zwT(58TqmtVY#8zXlH(=t9@Ld45TbVCa1yNxCa;j9Ofpljb(&=WCGP zv0Kc;G0_m9=+!{6y3xapLBP=9)Z#fLXizJ8Ma4TlDOmt&5fY{$8{W%gT+C~QlmdIA z3|ff95#eUqs(LlPk;l{ivooo$>Yy!s!MCIwNLNxJdNk;))=Eu3JJ z;pW&`A)gmd|B6hldMS0|kqWc+ZCi+_65fj1Wwcl6Z?DYP3y(7}> z&+B)7LAflclly!#wVw@_)4k7i#o5Vd|1$!YR@5#R4oK zc`JGfDRZeNJ}SVLRpf0e^nSYC=FVPFSv&LnR$(F6(-R%$jl!;+wQNvD^$CmM&by!e zDTJ9}NP~N1V~Zu6{^Cj#)3mhvj@-vNFnQX$e(qCZuOR^sk^1 zZri6=#dkC`&IaN%3kcb*SEdX_ZlJ*fpS{Xj*)1(}Tsyo<&dx9mrssq7o-p=+qw&iC zB5ubF49oFmEQ{oopzd-L}xvoG8Z8r$dV%_#EdGwOq5+&b-`vnB(H znYgt@9l@SxK3S*5>YK z1@_NLMGYL=2WcgECn4bg4xt}K?j)Nu`#VcqrU@elgL#Ic?K|wfhqA-n#A$h z0t`}bOHI_1tbJufc#mKSsPKNuSh~ylVz1CPa9mlAPliS=)MctfSV$Pv zFT26Q|6Z6?w**`*Qj6^Ap;{t&itaBf zrmr;yzU*JbA1zLO5hsA(0&H*Atd!bIyHdw0XMrA4s8KM-`_FgC?G8zi!$QUBRS*&0 zsZXLX`LidWnpj|!oOxxX+G5sbR;ZmDrVtqsYiGb^nMuF1-AG3r{aFnWa#JU8%5(|1 zU0m<7#rY4(0079&NUhnge|-|vsu)DiV8Idg@Zh$b0GNwBl*XH8NV$InlhnQuBO)PL zPYPTdp3dxO*_SB|^3cY8O61fceOs)p68Q?K3=X9Q2u|a0q)?_E&Kma0faCzL9Y6*O+4p)RsB9ioM5LQMZisx zCR5IfUV@$bnv0lG*5~Fj%auYcb)^3uvMqQV_nCy}-F? zSW%`nN_JRerr*E)OV{as`o#p$?|KOxKy9);N&UrPO{#X)!AS-=f*L3?u3d#*m|kp% znxG4KcgV@=QB{HvR=RnSV;S=rS=1`Ag~}BFD6`UY@6$Kcwx7>l?@yI?NCKs%s5JRV zkm{>sepM#c)Rh}l=xELM!C9B&AE%)l9P7Y~Xvb{U>f(@zP2~=_?sMhmG>!;tWs&wD zGG>J`z5D5{^%;BSr3fnd5jmK|xt%-`iz4&0f3QppK3swQPRNk!HLGQxxKx&lY|D6& z+FUv9cY$#K$PzRoXkP~3j~PEOdCUpWFQ>4u0khY8@`JkYWH$iX_ClDdNN4s(=1H20 z5;w+RcjDgW-PE7$#?3d2vlV*g!}UA!l<{Ev)-svSqTUL0o$oOXf+)Ou7ISGJB`tOY zRq7~OI}#0fk-Md00C+xK19TKUufKpA;9RY}l_P~5Y@O#TbOeFv8qDqEu6<0@C8q{4 zjg~FUND1H3k*wruG0C?hr%MVA6)6|LXW-!nF6X?YZ@{^|f8jvmv!BYM3A54>s1`3| z(J$}81S3M@F@NbOc--`r(x3A)1>bv799uIBksCA4#h- z5#Y?3&?WGJOhiIU=&Ug*V-FdcdeeU;+?9=!5ff8(S?v4&sEaIVzs%6(T4iib0ugxl zxp)?EP`gYA5Jm1Dc5qsID}!au*zE_BmfvTl{QRQw35mn8E+&yyg**3TpLO$z9uYCV z{~Fw8oGQyUzU8U|VAeuzCXG+jdzGcyw-a9YZMJeC{bI)aB?k*IdQi%{ZSIO_)54%l zIxmKC$~ZVF&ZVoO>T-Ux)6E7Dd0ncz+D)#q$;%#T@JNb`Mg)d(V1i_aLuC2qd8d=A znUDqU#J(v0HzW+dzCf)Bbhi9;8Z8*tSLJT9KxkW87hGIV>PZ{5f<9bg6DY2*XJgeT zn(NVLFRo0)VUBYM^eaK~S!qNNa3A_z37vIqFa+Vc z-oux5wUq$LyOuhx9{baB%*={HF#hNC&S(A^5)(Q{MwdYoLQT{h7ApnXPf(xzWoybX z38A6-XC8J%0~&&XnR-BQnw8#4p6?T5irRwFm3KgZD><~sl2n1$orR$^nE?)_If)HR ziPZ@j`$J|1qq%Q8aKVb<#Ny@Sfj>l{ANW`WtgI()tl~OMvRGd}3w4C?WGSI{2-#JE zYPySMCgZg}H}ocVvH>`PUcXuxcuX`e+j{UK7N8M+4q5IycDr30ZtR$2%&t)470q(| zAj)Qtcq>3=Lzr%8NS64WP=k|Rt)v_UtyXCSK-+p@O2}$6L*%g};+^L>(F2FWZ`CJ) zb;L8!Vf`r-lUyK-V#D`2VrTG=qq;ou*xs=PP{nZaQ z#?pcta$&q3OoCWoRg2J1975RIBB07x6}qYtngY&CKbVp+tR)|K6i`Z__@L>zT-G5p zcT=TRZHg`kf_n_fg>u=-MoJ}rGv4r~Sf~xa1h}l2VWI8&S)gisN&{A0lMR&dNECP| z9gcv(hz4}ra(;Cef%kkjrz^ZCcffL1UDPST5_qrEw095MduFo97N;{PpYii(y%k}2 zbep$)=N4~X4kt9X66FTa2WjRU)vpcY&eBW&Q!P3aTs|A*LK190cQ}4HU!N%RtCLYX z`inK9f#1+)8<_sf%8}$K2oxG1Op_bWA-($-FRC(fK|xDiAC;6&uk05J+JDFb4^t`E ze@`6%`8V%d!i&=ZI0=m`qu2k@X7>k2VI=p48fUZ4y77)6oCp9&h0~LvqyV6>sI2xiqsfP zbZhBECzQAR%EA>)si}j<`SyEhx(+!fd)1bA0+sIbpL!|V{mtk-u{qla#nKS=pgj`o zWb9xEhh`RtA|b!Kz@H?~F>pER-%>M62rmp4k#o7`cSZnsc>4+*cu;%FF=E-_3tdNTX5j4sAst_g^okw@Qia7V-xC1A`^tllJql zm4z*T9fo~Eu2O)o#UPnB^e5i5T_j<3K(Z=50`IUXwtw3g=gry9fKl;eAu zrjCqA1suw>hg>GobaFdHNT?-HT)IWNY@OD&Rkc?C&C|ti7E^k41!jAd&GfoWIRCM4 z)$hh2^*=ggRYp4LT5v8YUi+ZK86~8~aEY9XV3mmoE|WGE-LMfvzvv-dSQ_kvy5}kS z>SAp9HMHJZ0x<73UvQ~#E`q{*C*iLbW!X+c zg;F%h#4$Yt;$TAJB<|LGYIV^#n2DyW%*w-~xwy0iq2tM~WZw4o!Knmh*(my?z{Id# zN}5t-ec+ClNJkdt%#`4O6x+z(g4Egi7)1zKGSUtvOX?qA&3R+QYTV0(wihvC5}Uc& zI%|^=U>vHedY zH%kxJF0hr4S}=+pO9rLHcW$tf1P7B^nMH76WhJ@u*YS~t{VRRDWO+n6mtBa`pG zRslSV7)lgDt$itJhnD&VGJp#T5koDZ4#fk{Qs7*&!^!}yY=m6BD=b^br7v6nijF1h zrG%XDo8o#_~Jjb}P76 z>FHOtY@n>Hhi^-PloSC^jw`^06wc*uYe_&sQz(R)E;x@9(nh4@(#o3@+MM0MjrK*R zuBPQwXf?P?%=<``)^*snwkI=?ski~Ats`mJ9&&t_s3{)Rv{{B&V8De)FVRCet0UfR z5aGcW>U+I!{@V4Z)8)gN#%36umbS1XR@W<@Kql;EHWHsJ@YRO`lY9jhywqO;kQipc z)~_AJ(o^M|c)5L{*obMG7DT%~@cxT&@SxLDCRxy(H&eMHBMBj0u~(N%C*&N4c-Xf8 z^-|@!AJy7_cm1~CkT@uRqbVl#k{%RMx9P%cn@Rpb5p!m-U{V}a#-C%)_jmdLjq4qS za4?D*YLs&jRR3YZ`V|vq`RISNcCX%~<;?L0vz0+oLIdME22zZA=ZJocfxs|LIB#Cy zF@KZWgl++{8d8QX}VNdXk7xb1Qb%T*sG*V=xFdDC!bx%oawv z?W;KCz>u!=)g|FTBX?Rs+x^+n&)Y>_yH%RQ41e-4qmp(u&n<&s zG|F877H)6~=_TMBE`*k-ngQjhl-7k;cN|t<_y215`VkTsxKP1%@O^K0QW0t@fnbWA*PpwMQ`1Ffk$6JGEwz-^p&aj7h_?vcLJTBGXXOT-TVx%nB^aLB=61B8OAP}6%S zJfJR|)O$zPujugo*zkC3p7#mGn*=dTOq(L)Te{kEU@8fSYCvxEkxHJtMI%v8@87Qm zzJIbggI+^${Njeo{BnZ&Q2+b-kjLGIB4KVV^G=(ct#~rvqKW*1RD z6dEM0txdotGCi^qMw_J*W96Y_YFFKbhj9G0d z+=~dNq&`iZzwUxmhCX8d7=4f*U6iFrib|F&L?$KETI$d)5*u+@k&N$f7g4qngh@vi znUO0NNr#9i@kA2BY(+U3Fdy>z^*8)@F)udb3xkgca$w>2k4XbIPDc^Del*+fc=IJB z0y?KqsP5OpanQAmZoi1QTz-y4zf}%e?GH?eE*{+@rtAo@h^5CH#&!XLM5nM(AvoZz z*l&Rva2e4|H62F7Yi@BCoJ!PDE5qA8Vy9~zaOJtJ=m%^EhlZ^0+zPsb<)ZfCu-4K& zemAo)?HsgllsvAA)`)yAOo^6|Xm=3!ux*BJGs?N!VzlIv2ao_{@TbcFwt~f?xYHRe z<{Vm$F;_1drqMxfH)3FS%H%?>FQviX%Z52a;^%KZh3}du_uU74-MwV3}9><&<|1 z2HtjCEkV6!?W>)2Zhag3agz&Zh{c-z!k03lO-moFl)FzSGy*>dTF@9Hc@V5Iw z9B5sNOo@p=$7>GlWSUuks55<{W}pR%O~!rTv(wYpzr6GA!bvxJDsu%uw-O;+$Q%L{ zGvbu$)qp}uh!FDO>sVRTOU9&&#hiq>=*&X@>|B3R6^(feR^VmAWgph-yM^9M5V_AK z@aCSP#?5h5t3S3ft?Y<|rnYszaNxz~sj}Q<@3Z#ygr%6*IfgnWqbsEqTBr$Xp$W32 zf_WbpJU5E=Zb#2HwCiXIdUu*C;38j86K<-?KN2ba{4qs|M(4i&2_=6gZOfVqy=O$7 zsmirr3zGQK>*x61P2-n$X$XmP7iRw3vv^@g2LeIO<<+xnu-gzGUpY&#U~&y8anj9# z=coJG$^p!aGPTh?=D!IQGx&Nn1OOlKqmqggZMlv=TnpMBxna7f1^YhH({`SXVj#TxX80t{~kUz#!uXru>%$3dM@If4ww+I5IR2Mvs}_NK(v}vH^z`!OC#a4!Myb6P;A8Lw?{JD7K7IB%@E|j)iS^dI>NolB!MQ;N~7LnEO z)T|}~!QuH7-kIB3ggz4w$vNSTrD24F^&FzuNb;|MAZX@vQPsMXKQpV3HCtiS?&bEt z;qsqkk2#(?W+$$rM*s*8c?w`rOp5W7spy)`LCcZJ$<}N%;rs5uWqq^(cvZgww@RZ- z6MWUP8BFq<4mA63#=Xo6c_ukfBJ;2k;_xz z(hs1_7XdsVT|B~B%-N=lqgE|OT#8O!?xY=&aQd{@CUTVKo9J;3*(v{YKsg@;!2H}& zp*KEnR8dW;32>?Ycc;To1PgulgvX66TsXw63?$LQ>9@jY!A91m^rJsQwcn9(0Yq)S1kg3`HvT_gBw zF6&L$=4(eFBy63?&h3ZPB5!NXt`}pe4ERb7oT>b!dxeq$adW6n8fU(!SRxOA4UgsQ zM1@k9DXw^eHiduyLXhFpu%N9^B)Zo5FQRtJ<-7`9ogrmowG4y|iq95ya^fN2N ziHe+GPt7Uh2qTsr{+9iicE`{>Zuvc6LuHi4hIe$8X;YD(C&mhs4xOJEj|4%>gJjv# zX|P?S5Iz==&I+SF15s~1VbkW*dYKCQ-#m&ppM_f9MT2X$uD#<;IDo?jvB{+D$H%N5 zg0HIJ{9oJ1=(ID_J01xfFS&AieSg|eQC!WQ1`gFwM`ndR(63_=11nmd;v&4T8SHBb z=BSh`^;&$5^?z}twsUtc%ym2J%$7yZa+ngaO2-L3IU~%c z-ZU7I`#AJqycT=};u(3zed1t;HQ8H_BCHAc&z0Q*3O!Ghe=%vJikaIuRgGkCUZGS6 ze%)J^{68&#%@gl^Kc(6*(f4MVumX}O9WbhaFwj5bqidE;J8)TGW?>G@-@Uh^b3NE* z4^YJfxKX9jpKzI+b25mc`29bct}-ghuI*0H-QC^N-Q6H9Al)rU*U-`p(k&w0AT@M{ zgoJb>9n$g5v%dBI=FhCfIp^NjzIKF4O6+hj(~Z7x*=K$>`k9*sWK14VmDkX~#2^ix`~sSyK%t$#Tj|+OG7~`!@z5Sw|k(4#0w6mR$|)31h~R z1+&r6X6+-I|J|&_*%`h;rW?dj3|U4 zqWCVP=ef*z+H)?T-tts)ROdBiR z5jq7>A;t{iob|i~1#E&T2aZ$%oYr*Z=}V8<>8Y}$iMZj4)LdxgGwaHrF#UMVVKhj{ zAJbsWgaK6t6hd_alk1B=92E44-8~aci+3<|N7V{icNJ=xQZsVC%}Cg4p&iZNsGU7L zBh~brRo>SYyxCgu*c%6QCmskW!{JwC9qGjs*HhRn3<>;cb?wJIyMJxU=~7*^dR3r& z#QM*l0Dx9@zz4m=0c>w!>-8gm{AR)Mp~)p0ZIU*!=;A}V2NVkV@-Y_>Je)A1$;B`@LT?d*e)n zRkux=*TzoTHOdOR6x#6we8<%rV(5VY)AG?3K`}{flnJ2X%6tSsv@A*efoPoUYsRkX zTyP+#VvWY=q<#4CCaD6K-Gv6LERW0bmZxV$_D%9^IkmXVJWK~Djk%d3g^aLeuZD+t z<2^d!o01csn1`V*FDnK!1by`ry}1D2@4}AZ!?hsMT`zIc^uguqerC#41@#3T9T)2f zgJ&eLhoxHuW%yN2yF?CeOwKTDV#w7*K*seQeRmnR+wK=xea3?H#gKUBJ2bc?_aF+= zcyzYy0@zy(1LJ!?PD=l5q1-oq{|hP6(NioNQS%;6p}!vver7{Jl&`bDw&}c?9Va3_ zlc_M4tv3$A0p%YQmC(XNWdb>3Yo_EUvgTqUBjsU|p^~yPcyjVQJ7?#JTJM`d3+%UB z*Eie-`B1SM>@Q!bvXsj!bZ`MN^bxt1{Bys5$INL+;Fhx+MZ(%qONxrH(b3Vr>#)Fb zS9)PF3Re%R>QH&|PQi@&JyANV-UhE$_t5 z1z3A{H(?GI_SMwkFd95c zEBByaS<0+%J|kt{FNYi6%H4|c{GmVVw_dPTLW>7`@!vgUAd0Z0->XG9c0##Ghx5@* zIs`LYmoMi!cYWqaHxx|-Jl6-asF-{3+3plDy3eup1(%nfcRN{uGCp75%_Z|E8~6Z? z)|Z&)O|d+rsHjb8a5^&qr@>u*P;NECA7 zesjdoXMo$ZafeP6_f{O%m5|M3Ycc@`X~Z}PPN~0icniIexoUa1fdH=<5XgdZNIFL# zdxnb7_SSh3L6h;>!V!8!C?4dBsI)ZoJvDy#?211{Y&#*h+#X#-08m5xacxD_EKAG$Qv3h8F&B3*nr4NkL<*;g~0*iOzlm1Glkp+;CCnuqK|hCkR0c>z9n;|92Bu*c@N< z_Qe`Fr3b*`{Dz5_jy2LAh*eZN&;au(H2ns`DcbdXB0*r5DtMj zKjx9&uO7Stvs4iVaW0^L0a`dYiQTCc(Ml)211IM1-EBUKBjZ(#trK5+cq6(s6_D^5 zHW;s&K3nXymGk}PAtP@H6k6soG)2Ti`69a(C6Bjav>d)U#0Y!K1@Bg`0h;Y^GL_&s zJRLZf2MYR93fep;@Mj)(I5E{aos>oFo+INwSAfILn{AV*M6?(^nZ#R3b~2 z;GBXHYroOPBY#s%(>9{SGq8bJ7Oh3=gW7m+!!P}~p%&XSp%BxzM{HQLU?5T~fser* zPP99+l2R8IoZ@{q2vce(FdvjDf1NrMp`(Mrh7TOj27-ve7T1fOl*b4GgF+`p-IS3V4wR;wT(!ScD2ih-%nmH{G&VIHU*1xn; zY6?=|?vcxoa?@JS3|Qciq1sN*Hv>CyU+7ZqKPKLFp9dN=*&(~M?|p+sjWFgdF-0g) zzTm&!C)O^+IzpNq7Z*;hb3K2%cfP?8gL7+;h`Uf;4OZx9eJy5w)>d(jLppkAtdHJ{ zngbuS8_&UjQ}$gVbU>I43OR-*46(c2AO&W;N<}<>|AA~|B^;W_WhG>?J9G$`D$wp1 z6KO0nk!FgEW5FAjG%b*HBvmltsYL;}yR1G#q?L+|ZPHYAAzDhs2D2+BXl*CO^Kmzy z#uy>^ROqEYxd3Ji&UXga`<~m^1#i4RJ48x)4z6(mUr@qmaUR~UoRkMxgj>&{q5sp# zUSA#9@YtkWCSY!@j0V{q01Kxfu%3 z7}afZwNVA9t1C_DK*qa+RLt!iX$g{m-_qd_VpwZrIrI}6<}t+5SsuARY|SW(U5<#FOv8a{Lq*JyX9laOCMy0R5E#V~n?y z0Y8~b;l4IIX{tyh-zL^CFHcV zaWe`6G5%w?=WbW_V*0j%kSicR(PWHRMXV!1!yjdC_7y@5WDp=Ip&u{+p*NWr6h*^u zM0G@8k}479n=7E*FKKO)WB*po1JoFf?40VXQxp(&Cx@b#!8UQS8~BWCt4)|EOSIT0 zX;@n3%UY36*>cE16{>sewYQpmtU$ICn~`tqSjBWo5xkRBOgZX2I-ifM=rzAry8p;m z2WA=v0AIJ?iHGQnh3P=2#6YC{QA>;ERj}kW<@~Sx12e)N9>PKd>}FpVPpNav1+OO> z-S)F=i+Xw}F(qyQFxT34_}-KyA6^8Uy3tQ0%Eui{^Q}HPzzE$=?=YB*IORgjp%sre zBb;ui2n()9=~l{;}vnV4e1_G+m-y8>?NWl8R=(0uod>y6_Yp6F1K&-%zaM zvD3%qfPf*ySdq-kSbEXBXOFg%hHNni;%F+@{yAXC9g77f1V?-=KCY0+%*@Z{ zKlpomxjg*}OXmGUO<(ueO3m+5f${1qF2f?{;Wu`mScdluqf()VCR`9-UR$DD%2*;u zBhJ!$y7c!<%y=kJJ1H7dO`=iOG?uwmJwFO!wTEvKb2lCgY91cSZ{q1Bl~I132`V_h zaM8_gZkqBfgaDy2zje{j>dJY)3-Bem2-Bp(GBG2K6JQoI>*+{Qvuw1$*MlEdUfjTjEbAmJDW$Y>Sjlyl43artfAR5s0mIC?$40;*wxsfi z#B|_}GiGjJ$ z1z@!9G~80~K(>qzMcA;8j^3CrnJBlR(n}bQLKHE77Y%1^>`v1l#fl*@?B954OZg;N zgAVF!`vm59S%rWRF<><}pd;hwp&_!L9m1cE$_O{F#@|UfI%+r7uC(i$Eo1}IA=G== zhnY$|Y2(U`)!*aZrEim5G@#+?Ur)_RW_n6kVYdlk*vgiPpQtEd-umd3fa(M5DIT1DsuLjemd69mwd6*5lQ3 zTDBt4JBpv0_vkXo?|$m===*M84u4v<&MYd6F6u%S^dZ913JobTF4E%FNMZgmtkm-d zmjiWX3aHKgfdfzX^SK8GufY2Pt|@5K6xHH>M1Kj6G7GN&ObfBl!k^`P*R-@0*OJHqogsj_nTN#X*?i2(D#8^eZBO(wFAY$X;mx_4Zn z#TIp;%<1Xs5$_$c<5Ud|jV@p}3QR&uN*&%utAVhzLdyvEhLl@;r%`_BKc=7kGF&Xw z?>)9}iHJCn9h^IMWm!un3E{c{F2jZ!jTrr+Y*x`C zl4fSb7r(mNE>0^nMmvb~@XAk!$9X&MmVg-iOj5UK`-#82yBt;nh3+o|V<+yE?tND5 zD-4DLCEBaKHu+SF>aXK>ObW83>Pq3Ujund@8)JcB6+h+Tg7$vDq z>-@W26G=vW#XdW|mX}l_J-a+tX)J;50?M&7!kR3px~1A zn{VzeZmGQ?p#kH&mz82saEYXhSpV!GnTIfuRs|kM_pX+4z-XBz&IgM;_z*Q?bh|Zg zS&J8jkib9?iX=-JFK%*Cw|e6jqI!~9W=v*E#V0g-_OpVRTru(xFZPq^rfcV2gsC5l zn$>D(p3Ee5(-J)d55L^{!a{Xo3<}C(xWMo2?6X(N?7s5YaFCPf9sV`@UOB!^OZmbC zFxvD?w@ z=&S*zT0(BF1v3*Ekv*?By=j!eVJgoUjvz#P}t-lbjc(sYTT#p$oN+%W~v1P9h=# z?tA(PIxlNIKM}rSw+0=^laVvYF@q0u2n0m8L&teU6eRx5r^0e~RNe*By7at=5Pc%m zrXRzPcm)c%j1RL!HRI|h zCItgGp{=FWNNKE}72k7hnn*%SusD&5G*yJ$5I`5)%>CO|1955}BohttZ}W@ztZr|t zxs8JncWNkC6O`L^8W*RVyKz@tp_kZ0ZEl@fP)p3UFlFC5FD0`-B3osDi>SMi{Kz_p zIP*s73`}8il>lRp$&Slvqwa@nCx0U&){J~FLp1>$OG_WwB96)g$4Ji9WMyng89-ri zN*8waURV+YZX;)n$3|bIzb24(8551>ThuVo%x{bv^5TNKGr~q3fK{Q@5?d|Imi}*+ zgapzH^b7bbX};BY1b!ZJ*x=Sg<`j(e0!+rEJz*+AQuXx5TCL4Plf`u$c{l|}3W-7_ zm(j?vlqa*bVjyY6q~}4o%e&mOq8r2IZ-3`DbIr{ZxBc(*G*J#IMs18Q5&?8zq7URk zjtyH}<0&CWBHyr3B2Go5@Ti~))Z^Dp#WQoENPbMo$SxR5I_&=Bi)*degSAcUMdUES8r1vF1q;gIo1l^MhRIVM{~hIOd?WGq%wChnv+FY$yC zF6d#860a72e-TyFo9C^KuUdh|n=AWmAJpg+dgQdW;_34wvJT6(5-emY2Hou3HkKf&?l9&c(lMr*; zQ<>HwVxiqUrN$4&67JN#?YnM0i7Q)gcAM(gZ734>oUK}q>!9CfdVN(18UTe`V~A|F z2?>6gkZ_oIWwn#vP&6?YtmWh_rYZSWQDtAj8w>3+&SP%XnH%aj5#W|EyIySN_ni zbt!^>KhBZv1!;*WLqlO=-h@PR?@Fq_JDA9H?e>`15wg9b+*r3Q_(JL(@a`;r;JVs# zG1mJ$o>W9Vw{iM4=t+R-T0GBK9?$KGCanN@J|W%Y*9Z}I9Ba+mJifkhbU-)6uj@92 z^r^bF%eOe#)Bu2RocXR&H~L}u2pOJO`Sl-j8t32r(nave&FA2Z^adzuc{`8O@5Sk( zr~_mb)YZ7^g>M3A1D-zSXjQgJ36;|Mnjd#^PL=uE4n=nQxy@b?q}GljWT~eQP(jf_ zi63a`N`aOE((Qm;FVH>97Zv5`@XCxUAT?|ke?mN?93C!ncpE?QaUAK~=Q=0(9p2^> zv>@0Qat6^TSvSLb*4{sD;h)iWYOsSwQhAUmMpCg%gR9;f{6H`;wnoU>sl&_e7ovLv zhj_#S^M$u8Hr=5e4S+rb)Jo7Fla5qHp^~e~Hu=L8$l&)%DYD<9TWOsT zg3(m88p)6U5#$H$mx4Y|lDIW#A;0G2yIT4E>3St2b;A|K1VSfP&0&uj9{>`3{~J(U zV{wvvX};TJDxQ%55+#QZcTmc3O!NU6=0=h>yz%xc5!IzA7Hjd24xvvTW<=swhMZDq zs;&bJ4F7RSSZ-Cjc7TH~BYLDtmZi%5%{`JRm)8hL0gyz|TcoqjV~(`gaASG1<{{O( zSING+Xemj|3wHiyOgJn9k`X$%P@q(h%AZA`z9Tnivv28y$sJGuCnE(&Gqvu3pLYZz zP`K?Jlfxv-&$T_zD)$?&cc%S)eI(q>wDgF0mg=e-Wb2fi$M62`CJ-(RXSa!VNfU{aegX*m7WxWXrm8Vb_z-v1P9vDmJ31i)YbItQ%Bis=xs=szkMyTBrLJo#}Iwe68_1$Od{&#n$?$(sCG zlLSvighB~CBDd4p?}k9abyPbR7Vyb}FXmE7bJC?QFEA_M2k+~#u}3V->*|`8`6}{U ztse>1>SE3jKMgilw?`qtVn&QEBc_92>G`}CJuim@y6q1Gjc;@g_}aE`81uI^X#_ zUhbN;yMhgHBURI&c3hIkABM!{tSYumnV7yIO>Q8f*s0MOulg>21V9uL{S7L{HTC}bb_Uh4S?rrG zQISeAJEXmXYeeQ{k_(mJC&CpaP^cm^#MB7~XNo`0uxy~kczx{cU}*^_QG zoDlLS-Tj8}phRE`W#A%a?_Egx0w7TgH{6kb(gH1zi1w)G(c=@FIDre@sZLmM5#0)i zt=R?*EP1m<6|zhm?U4HZmrd+jcei>eoy{b?4J@2w!4IN58fuB!xnsH-BJnU!ICDBm z&PA=jItFOs2LPsX#lw2d0K=ayt}?N^UkiV#BSH?i%ueAUd$=IV3uh=wlXuG_&d`qA zJn3g+-+W#)Nx)!d-8fzc7Seizf8aT8qG7*(g}yprm_;5I*Y!ZR=96s{+IUjSGA-o+Z}phw!} zoXJ$b3`m)7(6CzV|7ZX&{*>nRbi!QOE5<(h51}NkYqBPWyh;d))@2o%q;~kIStEe##SMGF)8``=x(XYCUw6EmcaC1$@ zeV~m6cworE7G=+)0_28Kpe5`M>g5xg%ukd<#Yw999>kozq5y$^@u+~PdIsz~DH?xr zHn1fGk%?2mlB8NU*WU#qhxKmK^W2h}JP8|QMD#*((zC7xP1R%xpJgR!>^uMc_y?%i z{aj^MyfYspI|^4+GO^h4<1&B0eFg{W6yX*WJ>1y@N|T>J#hd_6*CR@(7ofTga;dJ- zqZDBsHQwExSd4N}@=S8HZ$*-B3S#(yH@gu7Gk8!v&>q25>6%o9 z&T&^C|CCxA8fyKR)s4V6PiB7CZ0CvxND6`dQK#YkU^fcnvteI7z`ov!8(VoHatDsc z$>Lp~YD_9egc(&5Jrs}sQkYl}<@GYtP{MpE_0x?g9f1Gx!220_=hx44G{IDw`M&{h z0R_vnqXYa0OtA;k4-eqBn^~2u2OQI2GpvLtDf@n9oKWeD=>{gNhY$Sqs(%>ZALXDu zUl@y##IP3#(}sza(qbdK){eRVEaBiKk6s}NDuHL=&CKjt*xZK6TemeNUi2?SDZBDl zo8vr3z;0kXE+o4AfGcEU@3l%dyD4d^KqTawwARvda7Zn``n=GvX=$jRl@Gh4>1j3p zgx>Es%C?=00}3(ko74y@xG_SvW)^&v3^%uoo;MB5`?f7%(r8)G+fimPcF%)RPkcn# zLEnS8kX#X}6ji<9UfS}Zzgijc!^y=tzo89`cvF`9B&9kea@L9Kz477&IKh0(@_#z~ z7bWG!{@@)6l_*;3b(gu&fCcef)nbg8dsUHHpeu;4pig5mhkOGm>Fd$!{pf80)%v{1 zDwY{&)7QlvI4><4|G-;0z*;KfRa}pr=cQ!jh; ztR{=ZZX@U6Q~K^GnT8AsLGM8Yz+NfbHbJnL+)eB#8S#_rtqFv9#I*3!o%rVz- z6mC5;979&`cRDCZXS;Y9O3jlDd#54OiEpaDW({ZND zgwKrDcZ^ANa}5e5tRpllT$&4!`}@3eY+x{;Dj6t4g#4TIBk4P~tPuRz{>_3{()XtC zlVlrv%~Bu(t8tQ*=xo(Wt9PeB7r*MTfc3tojW^1RKRqu`_d~4|atvxR;yX_tUP1=0 z{&FVK!!^FjXHC8UXA+cy=fZE`?}@sv^EMKVT)NN!QCk6LtYEkhp@U^ao)lS!WY9C5 zv3?|^;FM{(7To_#`tMaczi2<3lUgVzB$zC`Z`jV4Zz-cWVu#aGBGWu4HUNWb$1!K& z_;RITZf}yGeVY7+9wF?sbbE}v8dD2pNrizqZP%g2gvPwjYC8r9ZR4;IyO?SH^mnkF z!5fF3L+aBj2Dq+bu;3Pe7Dxrx%dmq^%@&P2O)-3x<*MrDlu0Aut#bHKo;p};xkE}g zPSzwEnbzA_hn(U3HI|K#f!02OwWh7b;2t#HjkUR_Z`k&9*4kqQfR4ZGA%mqYYblG~ zv?aE#b7!Sn^Ww8zqzkBp!!J3ER|rys`V`e>X-<5$ILBje|NFU|5~i$zs64oUdjGc;fQ>>t?0JEeln=D-FBNEF|T zNSQ4i50Zy-DejYu{_?*2RPq5`X|H}bgsO9&Q;$~mJ*MP>13Zg0-{uY$oTM2ooF*`% z8UaN}sqN$^n>8<|Y^Wk9twP;ygI;RgmzmT0*23GT#wgWi>w#mJuamfZgOt_)LxRL^ zz3RT}m6)T^1Nqk0dNd*cH!&E1@fh%2?VJzeDt6*scbj$<3NC(~ftJ(WJBK4fw|2Hl zKNNw)r4dr;<7JI_5NYkdHNAILg{ppVyGLJgDby;h@2MhAhr2y-YzCL6f?8Lv7(_2- zQV&1V$3(2vSC*_B=9rt?PUmg;($pHn0G~_|x>ItV@ci%*lHXN4H#DOW(b_|Ie#|8c z5&{9XtY7Zmh_N)~p8<g7EeMO- zJpN{l^Q~z$PX^P+#0~%HT^gvekZR|N5cn3};HBBH!9+y}|5j?n8nd?mh#d$1h@V^( zlIHYDo4m5oy&e(9N68Ra^MG!j#C2j#R^_bAR3zFr znOKU2o%GwkD~WY)QylDDu5VY3xF@p4c!|$QBkn%fgRDVVmwnu;a=HQ}*q4!Z^Nv2- zMH=dLO3JXd*mx?eIPx4UNHtoGZ*Q&YPxxK}!zm}Igp|CxG%w9!H0-$lW|uw>p6_4K zH((-&g?+LueJ%%awI$A4S3fZVGD0}2;Bfu(z9X6yeihHcdkO$58;a0ttM<{Oi7tF) z1#o61pR_kb|d`qs0WS z89k>QN7u(WI&y1AIo#Z-kw}lMLWh4uEmB@QY#W@=mgm^G)WMS}MCN~xt`<^k93MhD z0wYstYME7p5cU_&_mZP^USto|+mBqyg{iLi4c3S7@Z(NDLlvt^@`E$Va(uwAa?7I8 z;pUy_kNx+Va-#KOS0l6zXPi#^)iveeV|63FY5bVzA3BB%*6 z&0DSx$X`i03mM?tPMa5*qFV;c>N<3Mf^*QIgM)Gi-^k2b6b-6L37VW)_e~`c0P_b$ z764_HNaW#1JPI|W#e=II4gala93}3cQfw^FT#Yo!%`p=2i56#U&X>B*vGs%un3)~A zGwmbD>sX>i^Ssm%MAVp0_xgJN>LT%pXr8n;X^|Q@Vuien4r=_tCzNI;s{QR_GI}`u zMXJPuOXoH|S@`vmHbwW9=es7pn9$&aGJsgRPxW5cb8WaIs$k6}x2JR^KxpC_^%N9$ zP!L4+LO;v;yxP^W_k|S!u(N`2FL3C8KfxG8DaF~o&lh~5ut~=P2t~RlTn3_e zzh|bYPr|ym+?06X!cv{Wta3Y~Sc+~S$>Fuc9YQjCcNKoMQ_qeMC>~Po<0N8dcTG5P zP-16{*63>6Ua6a^g%j*K+}Z4mXk7~w2)grr{iBoEs>8B1####kh(5QK8}z68vaQ!jsR$LGYrx=MJB0xpfCe+ z#V9vn0Ik9gvqnbJcB#Ona?C0ul6%&)0^w^;7FpvbJUG?z_T)nrU;h$hoiUgRcd!mO zC8x_pfiKoG+ERf}GZcN6m=Ue%r=$^3KhwmI8DQp{j;K0DGN8q6HobHA=LpF2gR6zy zW>jzttm$vR>@}~g4%9B1RD?sLw%jWQW=O)mt0;Y2R7Z3($E?$`c6DDOXH-L#O&P$( zj}&2MVZfyE1ix3gtmxxq(NUy70!VbC1%2q~FCEk3cW3|?I+2g$XZ7u9Um=|F89@E$ z055;si^`h7bdV(EyuFtKgwF`3ni=W&rlllJts!%Lpgy$u69a?1YV#(``o>QL5kTMa z4p_5Dy7l07SP0dcL<&F?SD!cBs5~ek449$qG)SRY(86uk@LBKeOIz5$X8!ae=R_(+vf1R6wbZY zQrw|S#C_mZj6*~pyA>fG5qsbkjZc*Z8iX;CJ5WGh|1dECmTO%JE9d+5eX-oDvvti& zL_iKby4(bf)BekbCsJNMvZq-vUSTzk*Nd5O0;)h^{}!(7D%*|U^IM*u*Qvr}8oc87 z_y(Y+<4BP_IbeSug3EY+S>XXR@v7j{MUOuI+Q@zJA*Bod!f*nYgwI~G3KYd*d9)&EG@0&lm~p2H4*b2kM)%(`s_7&ADS38eLt!8{90*-#rs_OM zHPkOn&Any$vJC0WDEy+4fdGmh?ao+@fnDZr3l=_NjMV9bg-Qq*^t~xbYN;Rx!Q9?Y z^$BWnG1cFsx>QN*S^-J2t;6dPL&q+Hm)^PFnKtP5fS+^LJAtyh1+l0qC~1&nprs?R zoABUOz$EYS=MWwDvz!0 zTPTZyb|q#r^E;dB z0bM4$U~(Z!9%6BhM*NKXR}c8dY-jZ-7f*)1py( zbHNhr_4EnFK8FdHmfB9FMs^#hw>z*xrw@txONJOY|00vAoFC)NA6(I12k{qePLVDK zu3^JPAjDX2^S{Og)1b>(Z6QM#jV0z9fID5H;Wu-Xl^UpKgMPFRG{a2yQiz;f)*;KW z!*MgyGS*f?A$&N+c+ypCRQO>DZnO@Oqdzq<0HHi=Z3qdf2>PZZ2KG#&uh9{Eh_Dw0 z0Qdw~&z#s(+3=Cd)k%Gw%Ne6)1>W&v5m^J2k#&>_rgHBjH*FM>kcb^uYHE^fO_hS7 zcW3fEl4Wf7uIA^7J*3Dz?Yk)@NjL^3s5BJ~Y-$sw_dHmkFKAC-s#F{MiV`a?^?6=X ze_Lem2r{`c!JrUdiSomf51I(uZ3vsV&i2KBop{+eb;9-2Ik^OGFmUijmv z1CoV2l|MW;fK*M0;zb~}c&4XvEn~zQNg8gZf}q)tT{J@^8Hg%1Qi>d(k)_{)8-Cdr zje9>6C5{)$;;75xJ*7L4@2WmegQK}4QGLh|756M}b)9Lji`B zz)>cyb2S+UHaavL!nE&-ZORTDKo#IbhBVDHM3CIzN-TES%AJXPc{cw~Xk-@-ZLMhq zR!w(67%(0J8E4&py5{NhXl$~W+It|DuAPpPrJjHOO)tnE?G$+tDbNXfz7Y!U2Pmn( zUbq;x4&TKbvWp}as)><_1<&6l9{kPAuV@dzfC&Jni!|B#?&!PSHvk%H7G}1zqP|DyRqYtzNCvI=bs;23+`p;2Ibp;^1tZa|URpNl_~n$r z`kr=4v$+p!Tv34vZhi%2DHm|SjFpVUy&f1p9;U*5bw6qg?tEPU32X$go^{=+T!;n# z9rEu-uZ?j2L*#>lNq#3YbWT_6k?}C%mi#@(`sL%~{j&Fr(qz%2 z`81Df6UHPdz|A>6XZZVoj)7zaT-Epe>-qL0Sa_fMZ%41DDtFR@EHGWFq-n^c;{qUS zepk5eJ-=DK8Aqv0W?4jwTv8#{VJO^{Z{ZKC(1o7^CvnJdOUEKLSgX$rDa=a=U}8XQ zC4y{;qDP)0C+QrGbVvW|M`0^fgZ|^989`Iof0$`s$wDymoR*}Fr`?9=k_GK^=+CjendtYCnhi@9P~{`?*jwn?#T@)fQ=W^5omC3}C&JrO*eK@3GOQZq z897^iZ$B7mbl%BluH?%(<VUbiajFr_4pXioGGJO>_guO zHnCYctLGqcRs!1o_gLU;&5kS(_N}Rz32hAw=Mo`N0YyKr_B+-z!}ws6m%pSJ(3g$; zpY`j$i$*{<_fOu?SmWZ+ZH)Ied6f1z?0*!U!+_{Gpk+U)jvD zSQ9s*X1;1QsU_sXW&r4(u8W(NHl4QePf6|30sla!$`05ffiG9*XHj)f0_4cs^qPmL0Z8;{i+lC^(2>N{>S z6qK_&6aW5gHL}g%X}VHzzELEDc-ejT#^&@#s+DjP)s%emCRFPk^GssDI33&Iz6ah> zZ!^8|>GgqZUksV0ZlR1cTh0L+Gd)2DDAzRO`|q-4oiD0Fp%CMIPHo^m3mQd`K*qsk z?uK1`c*k1up|>|hpSe+h>y$OpavbPsmTQDi9}O_njQ$_1d|mK@_QP>J)o8-XG%Dah zml}#-F6wqeV~{fuIcuuYhYd~Lcpx!swuS9fR*#d}yWGd?KbY@!$x4%c5*eC~oQp|+ z)-NBxE(b_12hM>3x9vhWo07P#aGK&n@q?I>A6vSLU-$FNd z{-TzB_$*w(0|zK)LN)+H!a|C?OKC?3^J>D+dB*Jx#~UDF9-#86Pj}62a4=Rs3~{s+ zO@=u`A4Dc5Ds}_E7~gP0x3X4EI;CY!G@sVH9`1PfX(|o5e3}_hH&j@O(LGasuNv*P z4cBNPOim1{eF}f$!b-2}Z`NxqKY!y+(?hZNrqMV!?6Fzj#F|%34V^|2yJh0tTa>aC zuJHccoy=0opqda52-PYIU2a;5OM~0ku?a-NN>Ge#e{cKHda4K~J{~4Q9vz?_m;RUl zeghy-C;%mkf{sp(<}7>X)rUv?T2l&b=kO2^Z+_x%xAGtqID51~@^fJGM@3q*Edjjj zNmtn^nV(oY?Yll5s}oBpaePBtBZ&3!=ihl;^q%$zg{NPUr4X>a3dHkkl)#?&cDusL zG(U8C{su5kBCPKD`PwgZE-NchAwd=#u=0ly5AKB>TEjGhOgXr(Gv?uEPL-;v;F$=K z5i!UHrr(}}2VnUn$JCp?)O$}jRn`Uxt-s_K zgkphC)gjYC6^UgmLy%x1&|4n_bMkf$P4Zu@GxNCw{44Ud=C{FgfC{S=(F_j!n)W4Z-u2Z+GfVpM3ngj# zG_R>$3r8@}g#225;4cRVs|}ediyJa)s7n)=bX%SI`6E<~VL|BK*2AifqYV!p;BaLk z>7TBPW*7T=7CEV&!%Q?{6}%e#p<2dbEeCb@Z=B>`L!_cVD|24R2cV;n^pjyTAceox z$g;pU{h1JU@}@(1xP)%By@7MTR#$Fh9{xjCTKJ$d3@28WvhQ)~6%}|o1Ttd|{mwf5 zesp?`P1MSGuaQiPj()m+QV$Z~bw2f=(+4Lkr)|FusQpv_%*M+qRKXN;Mn)`M2~4zI}>iiTSAiaOZqEM5;!NU<+j1 zN;FaVQ=$JcSS;vyI5;#>n;ly4qDwiM@S!m-G`PkxRFvo>_C^AuQH?xDOvM@g_1`0o z?KIDy>1*F9EVB-@Np2W?$RZAr@xW=3ISzO;iP`fd)6sQR>6-C7rl>1D5UoXQBdDQ3KzkBd1EG5TZ68wD<@}0K5_f z1h7oKET12kv11Tz7G!+0#$#izpZ)+FW6ly*BuE5(v%#> zxJ~l#7X8}2lC~z5knh3TT8*aQPrs!J@6NF&{bQg7!_L=@W0v3ZeeMw2sDbVWvlV{o zyxrJe*CE}*$M9w0WDQ6oR&?2F>!MY^={Q7Sd!}_woj06_A8;{rwk~j;N1i4(2mL_S zaGjV%wiTAbMZ{U9b{853xx8X5XzF3hKfc&{s$Cn$yzp^`8?|)kPrXzo8(!!lG0!ym z(~4(DjtVRw9JOwpx2iX91r@2c&|IZ!+E9ij&*E)VDU))9`Uzn}U`y#wbsk8jqdFkp z8}p~ws}rcXFd@;}EBSv~0MK;Njj>jE#E(AvV#Q54Nx)NJxYK*U*9s(zeXTZ=vZ`KQ znj#co~5&giS2x5+^YxCpe>14oS>Z&%AwiWDP8T;gaKtfqyst-*!*Gj zw`<#+wIp+He`>h2xvfBYj%zpm#v51y023%-TpYpHy|-qwLCv$wEKjhHscD(KItK*p&>63Is7rWKs9 z_1mmKWJ0EW_^S_8nb;#%NJlzsYyV9&JK3D~gm6Gu4|8Jgb!T*!y3MO8O>(xt-3?Nu z0u!$)=|@MZN!@(hySM&=-n$%JQX`jF#AMZ}8qyr~Z-xg-heV^b2`#N;doQ**A9<*e zGL)xK%bfbYe#RZ7GJ_pP!e?BE8W>u<3{7ko3URDyM}SRk@qU&Y!@lE_tst}WnsRl; z9m*dDkW`bIpByuKCK~y$zN3?^%sd22$-W_Rn8>GS!J>zK`d~jOTl9J;FDDAqz~@ZP zluzsANuWuw0b-F{_w$F0A-^r#sV6-yV1AE>=&R1=68ZP5~aH(r8{<|M7lvzI;5n#yFt38L+OU)+xz+E{kK1MW@mP;IqN7~fT2E`^Ah7c zRZMC?jC)hBtJa^Xr-yCfw=zOr*?3{ec2Jn$NpkbTzQ4$B7+|w25*ql;qd*WHU9SUz z8seE6B$&)lPsN>)cv35P(%4A4*s!E81OBpb9RG=^V}U zXX-kImV3ealu+~G8{h4Kd3-!M!&ZdBh`~<@dO+^!Ur|ii;7=5yJ%eTXiD|4RPsc*2 z488&4@OEG=oji99tdW>iNQ+=w&T z8)q)X3*cbf@}OG}tfb#+!n|u{+g-qKyV282ED^9IaUw*1afsAl!N(p0Cg)*eIdbv8%#BZ)&(D-x2@1SKzOKvya=bT%_bF0WwN6Mgar{TN`J)_k z-5)@ivn|wgUX%d@4CbKs?3gH%aAql*Tud{Ver7tPYOMSYGCaP{e|5y4M^M8`_Br5u6#Sp zWK3}BnCpcVOm_@YdA=txx|?l#Pw(JgEBQ6-yonkkK{Tm}W^M-MC~rY<>CF-a?{iEE zCt1t2XRNEr(xmggD@iF*K=CAskjK3I zo7c{F0J9=!S2WPTcH2RZ6FH5B%@j0hXyuR5BU4fc~QPbVdX(Z zEC*)u?4VrDT(-E^FDKiypY63(U*#tT*bF5GKlST8p6yn*1KyEBmzRf9@Fpe9zl8NB zJclL&%C#T{q3^bq!yiRyGPbXF!L|Mz3E#W|OQAto*xk(`z1^&7RFk6$#{aM69F z#RtiC8Yl%3Lm1-J_yGW?47#xuz3Gxrt#oM|WubzL%bdjA!SV1EkgX4#v6O3GD9B4H zvU`{I;jUjS%5&Y_pBD2vf_ivnjIEz-PbId)&C1IdAZ}Keh9T@h-dbvy9)ky)k&Df%}Ys%6~PI?`YZ5$b6=KGH!K2 zQ1w|uawzElx`s#HRZ_r_$aLjf)O;%{JQum=5axAxtm*`v-~gl=i9EgS7kyL>JzdJl z8%397QZxfu)q=+y&okY>NyvQe`Z{ID-vwK0zXtllEpb6|;nVU2ftK-ufm?C-x`TqXBZdTCc9&$l>C!xsC-6w1jAqS zqbL2A`^_gVNw4hd@rr&seM|wYBGD#i8lQc(F8UIZ=b9r#3H*|uIW1;*3lV1qgm0Il zihA{&L?tWjdBsvOcvDq34W0NTM2+$5Z%H{aHj9o75Pq!~O z?RR&BFSxN{4+mj6w-;p;4?i6-ehluXoHB3rnFL@EBet`?2CIV}eDB-VAaos*XIF%A zjrs$^n@k)K_*`P7NFroe`)l}pd+g0aBED`VM7R7>Op<_#LngXI;ab zzfT$bWZ%FrZzpNQ{R9bi{MqS{n`YC+nL{vSWh-wc=FsQzpEa6*Hp}v)no_Zf-Wzk8e6jxQ6=b|@bqt=5^{8wPWn@XfJu)X}cE%EgO#X0aVPSX#ngllvlK7J_0 z)W;6X>!OhTniH+!AJT%;xsEmP1~3G~-o3DKbltENOR&j=Cf09fSMP-lU`h_E|{Hp z`i!^DJG^_=gl4zebYFnS3K`_BLssGW98B(F<~P%P#jp2)E@()b!z=PPJ4GdUvZ*_@kj2tIjn4PKnJ)2z-HODsIIq8^N zVd<6w$HP|VAx3XxN(hm^A=Bg#*ab!`9RL3kW~`}%*ic_SV?L}!w98rlqf{u0O*6Rr zdYV(sV!4QQ4@W~7i9Xk!JtdJ6nUp25_gj9P zSeG7!=WUw!2Y*GV4uCL1eQOxfXb}RZa2Ynk`0Tf`_6Pw`wVse5?2-zQsJtCa+g=pH zA}#!IB!fW8ZX#j?NPk4y2&f$`p8#nPd_^`z52WHOruYxL6u#gEdRV9j5tvvnb`>apdaLBHUN?s!+kxRy5){fg$74t2cM z`SEdBU?E#PCAcT)qD{CsVB^RmLdoYvje&N|HPASn>mgNH5;yCCS<0V4e&A~I*WXmy?E-@6>J%vaD$86CKOd&@`P|~uWqq^0vM%6A&Htxu^>HyCUlTQ#5Tv80i&Y@ z4s1fz#nYf8Rcg(Lk|d^)}9qoJ|n-0C+idE>VweN0(=7W2P) zY~Ku;aY`EP6YnfeGEthb)-TUqX0yY7g#GG>9;?vo=DT`^VFFj$%hG=dug@(*c*9Kx zv{BJN-ll@ct*Eg@XALi&h|VwRt?LebK6{LJl~13=xkMj@e&kd2;?lrmBfBSi6uoSk zUS0Fic=J7&SHmr7yCnnU^4@yYbMNZ`lT2slqve(1ynhOe;>K!r!`_QAWdW2aOl?|7 zmdguys^z#b%1oynOF~<^QpR}#Lj^nUJsA?vFhw^Fa2}cNV0r7VgplJyzh-FQPj(n? z0)(?EkCvR*s%Pd~^G#&GhjP?bI8p(A*X|(Fx-;0h|5b>gaXHS%1P)Z*caRX@fQaH8 zA0YMpkUSpCcVik@Jpv_Wxsw;A{)_ZfKF64+ofb-g6@KYZtCl4i8Vi4@GUGa+Pb9kA z@?vm4l;SP^G)hOixb0m3=KRkRpqSVndkQTeT8}YV2@ji+!7!+zi(dzA48iA(0>A8Z z1P4VkIsZxO>y1_Pzk~zS#prA5_^6%;`e+$-s0h5DuLb@!4R>c4A8(GNE~Qm`C3%W` z{iYAIE7el$@`}KF)4(Lhu+?c-L-gV~197bwxmDLi8ci9v{p^UxDSo|AKw&_IxL2&s zFG_Dn$V&)h2gT%*!r1y`xd^y!o)N>jqEVaV#~V56yy+y}atO;S0{K=dMn_)TtpbZj9Qb_1Z^3O#(FiDNmNIt2Egz=JZ;h<`+VP`cTl8BUQM zGdyA8c~{FA{xn=vgH25+RGT}aVShrt6UB#~e8FWJud3XSzVb3s1pA)Q&Ml;9@I@~j z^G6}s-{g8g=+pWS;@yPvX!}M6kO}bbF;v>rF`1gPO3Cp4S3qVD-NKJk`#!ZWdobw| z1N$CYg*9R$;I~ew;Kk343{Z6?kqYWsu*|O)yBDkF)M6QZ1KV_E1&Ooa%!ai3{C1>M zJo`wZ(mH-IrWzz6Rn75bpO<9eaENxwZ6#+rO)^gQHPi}Eg!1NQ1=X;Qol0Ir_+;`y zvtrc5lXM+^69fc!Ke6IeP>ss4f{@T?=Pa^M>!MLYvz-Zl0k8S-#M-?c&^$ykf0yML zu%U{=uS`!wMcp}uhhz%Xn52Zbz+*aT*FJlq%3W1L)>}hT9l6x-iTt~R&(E}?li|m> zJhoIa?zQ9i6gM@A3>VgsOZhE4tT(AEj);nd{jv}){uSrxWRgBhZQEr1@1NH%TwNcS zK?=ixNoyS;#Lj2og&fHl*XhW$%jf#`C7u;kX5u@%4~(2oeuBCLZlAZ)d~TjE zpMg}5^MgQP)^PXTM;n_4eu1~3hvo(ihpy|6Ad!2)tLNH*M+6B#$FQ}{mEMjr3rS`3 z_@=)W6JUHfVjn-cKUE@l<6tPb;cC#N5p)rHe%Lwv?yA6^50xR#nxe%QoO_D(@(=D` z6!MY5KW~K>vFte%IE9m68=K^9?1%jRtDTFPTd+z#uTx61IH{%VRn-2V>_eJnb78O^K{<99D zWDAtCc310iRoXarMKH>Mc9G1qm%tJU$#RKnH1UIC&+Z`fxU#|2AcO{haEK$nYk%4Q zVAiD_L^E9#oxOqy|7%%QyaLYC{(=yx7`8ccZq3bU`5y##e*5nY{m@|fGcG8M%GDKs z^H7EZa-i+?NTrc}10G9Rn(y(re?HiVes~H+@W(Olv44VM2Plps4Plcx&lhaUeu9@5 z%1!K8RY|CYd0)YA|9rDAK2E>GZL2%t6n`F8jZWrlib!iFKV0SJ|BEwftT?2>_BzQX z+oJX~#~!FIdbM!o`xYSwF>+YYKM$OyGMP8FiY|UUO

i}%4Xf-hjz6{_qn574+F|t^S4ME$-8_LpAH?wHLQRluv9$JOGvVP{TW?Cp_)^tBd(v&l={hjJX4J(!nqS!?-9B#u2!*RX6m z=ppAtUG$}g6bb13Nbb0L?n^$E;J`Jc!-{Y0iTImvKVzbr7i&_EK*(wYzWJ;1?VNs! z8SH;E37+6k5Pb;g6Qo8x8*{_Aw?FQdkm_#ZLdv$40QE3?c6`p%vcU&Y6Riox*~fnJ;?4<&PZVaZ0L-lOK>;e@|e z{48S~!wzST+yZLw%wWpF1goF6XLpH%?Xk6%a|IazZh|-I9O0x7S5(sDoVydBSf;j+wUbMf=OhWqT;{ z5>m8Nqi+ZvSL2un!rZqW$7a4N74XY>szLOO*V-jFa*__3;Kpy%a&K_WCmL$Wr( zkTPwh^;VM=BU8M}a^X5U=(Ba0l_>!CE93C=%se1*mahfdDBK zc4eHNyL95oSra!osY>b9A#%!jA6NVLOD)%6g9{F9>C5vJGapYXwZot91zs;uswtoT z<-yY32xqfO0pUEb4NX`znDjjVYsE513Dq%qVQbr_+z2<1_zKh+K zv%J0C-Ts`D#LehUo*MW20WP9tM1p^JhWiLlkEV29osm#4yV#py8qw81)vt zJefQR!}mVF#K0a1N8P}~Cx=ez(zu^RPxua4f|Lh{IEp&Q zn{yiuL6RIt7s-XEpOVcaqrU&cZ(h>pQ#-HjBNT&%M{?bF!cBX51cP1HednuBa~yfA zZ-#nJ`U@cP+St1?D`(GHz<(R5t3p=| z$ExS!-@6Nwjkim3L!M_12=U3*wmQne4c)L8y$L(8NDQOJ&B!SPn9NsZtoL;*)Vl&` znee!(fi6uab-)I(DaH_5+S*(HMM9BeTI#{w*-pQtjrZf9=XXD0_-7@Bp`powRey1H zCRDdqFk~yCASWQpPMAp;>RDT$cc*9KyB1xQRz5v5N8$k5ve!knP3tpq1CvHPw#USNu)x`qe`? zVx%Ct(Y&!Wc;5;W)nKC#$MlV|vyrsPy+`tBt${dmGF_eiSjrI&10*}7HWX7Rna{Rs zjT^A3J+nQnRNRnFZfuvVBBH=Ft5B>d?t5#<&?#=4UogGaQDZ-N^@2pLyo{u2MoALhPQMN_CB*xZ*BuZ+Yyp@YqR z@4H7B^CXi`Y@wkDaWQiV(rd7N4XE`)tmFSl?AS&wMKgu3|MbBF&o^UxJltedW7I~; zF6L_y9jU?-B|`Kk$GSvKO)~ZiOD1L1c+Gu{J;q`KU(L-(?G(}1fEPqF%&C@uYbH=| zl}k$hdCH5;4`*-N({a@4;!wHM(2 zOA6*9L;B;_D-rqY_&a3;92%!^a%%HkjT9lKNbFLOHfK_$&7E>k+^Jo`nE1qZM9V^q zd=@q(WUH_8ca*shX?QJ2R~{SjZGEev_(EMm=`5uB@6#pq%lM(9Tv&QE>2>jC$l_C< z%#@iv6w2xv?}1yJC{9>$6P(fR*?+9>K)kG83HduepXz~zh*1Ojqt?_(tJP2z_AMH# zW?J(V3-DIr+#v^^cjp&&(DYyYTW&NhP88JEyhLrIfc@Xwb^%@h8oY20cabMw6hyAe zg>Z_d)2G-*PkHPbr@>$Y2!O)e4CFo8x)E(()%vDm$w>o-)8;%f7(5v8Q%ksDz{9(} zTrZFe)19(p+}*lo1$%=yw9u-D&?zC*7>bVc8}9OUO~k;6cYodRUGAK~Wrvl;9(i_Ux zLxdJSf*4) zB>O%ri;*_Ov}mH_G^e)}Htzc>k<75=LYtvBH6}_mAeuDe_$;Q-k$j^w4vmF@Vw@1s z)ASGnkfDnz#S^(*Ts;bni32Dk^c^*d4YI@FKxdll@fe@CaC}gU?d;OBE61q4rhR8IQVUVx zd=u3#>W{nuxQIs3wKPlC7e|04y;5d4Sm5sU*kvtD-VfSp1HB>EVK5Htw~VcDbX$bo z%-YvMF9del?lYIXKh-men*96L%=dvvC}0AGMuR>|K0)?TT{+)mAq5i56T^%f^^G`Zdz;nZ%sQm0_|hF8|ubAtUj#k42Vr1Q+w* zFNd@`hBP|%MWdl0U@o3n&O{ROGNmvQAp$f_L}yWM9Z8)b-^}kkCl?Ahx{{4?qk+lE zwq&Z||01n9bQV+3+prlvw;rDLby9D_42)g*eSc*m9&BA6(RvCurpP2{x|Aa}X$=CH zC?Nr9QBeZ{cfjrh(T&IDJ(f7sy72suIT<@=IJmF^G!WWpT}Cd9XS4a=6KKjV#)h*6 z+xZUK)h(<%{@?NYf26HSBH{_PJtPGR85j7x$GUGpf`=Y_08@A{0Wlj@FaRsD>g*EH z;MIvbG!j9VdmTY!JGFG{K@B1H@#oLAg%Pcd<{SS_VqP>F1V>3IG@~Do)UtOOX38sD z$f^R?j?WPk!j9a9qZ{a4*$<3s6r#X$;tepGbUo1~H8r-h3B8$Z7#C^m2mWH+hE?9M zR2m5IaU`~UgBtE5fXtWN9Mn3fST`JSRsIX9mO|tQrfv@@knw|}ba@3Z04+~H2qW-?oft~01{L>MUNQpQ31^njm)|>B+NXZ0zr1#xt(w*)npQV%(I1CajowJ zHK+&$&HE>{!{LLhG70gmx91-QF_my&|26&AA1e)aRd>3{m%qL!Ao+-^&r^x3k9 z2RJfa`Y3Q)#R`qXmK1*W$9l>{!oB+}v?z|~nQ3Z13-bNPVj_0LV|APfavZ#aF9|TO z9)=m~{;%f!mB43_5w6Ddf9C&=e=S0rL;N3FX=dvJWLD2!y;hd}pc+c^w2HDG-Hga! ze+%rmY6K5SmibI@0Vp}VH02H&#%UJTn*qOywSubQVu00yn+G{aa~sq9iPO`NWHlgV z^2*FHki_iHiibTm;oJ1$;f0$(`P{2@U4#urCbJqIcCSRig#aC+oAl7Pq=)_Gt4{@Q zS7Z9Fr`leDpcO^3jiZ{Dj;KL5C&C4@5X-|G2GLmZz2{29Fy|PRuPUwO3}qP~Yd!(G z`mG>aw`Jdafbxox!O&m@HVgj?l9H&O5x%Y)($4tUKMI3=+s4JvI4~3n(E>aw*(*-o zm|8F=PvT9y{+U0$+TE5&$43q+*}%d*S(Frz+44wHd)0shKnBLxcm3A(a|6V6U7UL^ z3_-6?B_0+n?&AGOgwo4#sRBoEc1wGq#NBkZ3_tZj_Ow0Lyq%NBnrPCwHRJ95aJfC6 z4nN3|4aDvnPhn_3`6?I5!4!l7PbzNbRtH zshy>Xs4pW8VpCKo{B$6C;5q2oudr~bLwD@@zU$UMF z4+%dIfGOI{K_n8dsmq8ujI{CSsgD@)D6f3Qo__lUk~LFoH3&A{4S0#VKLSH+pvLNe zos2FbI%(Vp023`t5(YCTz||PHwV4E040tz~u&N9BF7_CP7X6_jMeGgl{$aVOdhKEm z2leX;x#MJ7#@o1<5rLNtV(S)iZXTz$NE@){Di}XYW}0D&omg{wDYH-Rja>osC7@lBnpKVGwZm^ zH42I$GLl>gByDT?N#j#-I7>^&SkmXW6Pe<#1o~R^DTQAxq&O1%!pr$tzdS#g&YIy= zxg3}Apl)>4429m4))E@&uibf##si>EI{y@w16*Rc!)Byb3_?;;>4pn2Mr>RXUL`x* z3mkZ|9Z@&U(!?Ds+g3`q;Q=-`VZkfDfowgwj$Q((GN4|b%>(~ghX&`T^FbhBp|gjq zV?PdfD}AP3(@DwyvO@Hk;w^T!2dStRB_xBOQnJU&nS1Lyr=ZJuXI_wm|9FVc--6d$ zEl3M{o39oao3NP^S{nj!?C4jmp>s9)KfDP$)Sp``Wt=I7wMDSIU1U+=!gy~fU$636 z5RvNnpUVBtvmuT=v|~UsG$5AU{jr8E&2-OlSG?~v$g{a|@3xN!qY7}&+obLyBA%YD zKRtiWo!w6IW)(C>SrR}5>sUAkrf9su`*pYm3u=j>4gyib&;EC_PX{^qXGQyKcirlF zp7*r^S|LB(dQ^xHzWl9u(^l_%P`*G z^mB4{{$$*@i5S)X<2$^q$WNtcEeYb(Ya&g*n8O>$SVm*$ec(M2>9}Wh(7Z57gDipe zaHyJwELvZc&LsC*M1FzNThz`ivSU~mh5hN|5wRKjMZvN7 zV>I6haU~*lij%xPQ<^Oy?7%&n^>72HW)B^#P~5I32ei(MPJcjEz~5_Uhs|zzG5=@8 zl?7^-s7KoXx~JeT79QE=bMQTBw*tgmHhoL6zzKiLUa1DbM4PiRV4$-lt*)FP;bKqZ zmamqGqagXUWUm~tpA&=)K)9`ZtA51&0tPPrHiV2UicXzKmf}P2Loi~;v16vEW$64T zF3`c^-$QDvoBDF!F*wxCrNp_4NOqYQ*j9d~pQ24Bu||`NzPruaqXU?>H=NtcTY11_ zNyKZZUnQ^EGabljv3~cdnoTx?_7||F@(;RAr5cPRd06r8xm46VawA5uBaUoQW1sQS zK_~O5wGH)2GV5m!28!G)@Lrpn`O#}IXs75yGspUakYF2u&1K9G zMnmbIdJ=E90?;O1Zicdg@lI6;@6)YO>Te+h;FmrNH$vTmII=3Jy&GP+7 z;WHHn7LpQ!!v}j^{42CYFZP(4md$e`1(=8d^wa<`l#AVQ;*s?_I;W zP{1Ch_+2+n-kM#n2UM_Qc|b+6>oPr_?S{A1j*9{9D;mXjxOBuMW4;xkDYmAM5auGft`ab{m2d) zeCgLHVfaRqq>P7z3%7cL#F*?<086Fut?Q*JR1pM4lWvt*FLqm#USTSjmDB-lkG=+? z3)`;=d)MHn8KDdn=oYa9e;?u3@*2Es`OkCNz69N@^QrvG7bOUwpAc^5tk=0VUaP2Y zt9>1%aOfpJdaCt3pTEmwd|l4d+R`Am@0aawH#+t$ih!A}LvZ~x0D}<(xC4br zG4#+7vNQ$^dVcI=GxMOmI$fA!_nMl!;w{kMA8hx#HQVS2Sgf-pc+=k1lP%+s`n<0+ z{AmeA4W&2ia5i3hk7)UMjqCUF4rdOs$giFiqfrZS`ZH20#cST*PfYdigCCTha~CJY z6_FIE3|-P`#AMV8bHb#OCBhO0x%F>e$nJQ514#u%ag*;odXsN9*ta_04AeP-Jv!kg z^M2C@zTjq3GL6|;{6c)UZo4(X_gZC`fL71HJqUuARjO16#bt%rfy)6Wzl|LQ^3tEt zSBZ%q?yfch@C7&AF@A}O3Hh}~*q9&sx`5@v|uB}we`N(9yvi;YOSO;)D zcuxAvEO?@2Q_%V4Ja|)r}z01VU8<{?T?HnOP4%MOat%B z=cgP5@FM%;m5Qs)dgU@*M@mU3C_-@i1V)LG|M?6JxJ%LC(F1uW7NDkdRIkEv=s+XT3_p|tLO<$5r5VRYTy)WsAMMUG zfT1Hh&g=GedR=EUz47@;6!Mt9`QcPgR;HNpbk3ucqshtOf-e@~BwDKB;(ktYbm?iG zM&S0Yz9ur|MDy;=$u9zVOfo^7UdS)ZMW~xM%y%NHyQ^S-Hm!(k_O;H@^+BR9R;T0l zV=HKU6#P6BIpzUJWYGxfsnAq-ts&v>3^*TyqlY=9h)3@3mVUH2A z6cMrz$(qO)>fdwj6f@uLiQyZ{y90lzA&3P{@O)b0kr(rd*U&u$7M|m}8qAbhzqg@I zRwu}pT!2X$&4T6d4+wSgd7b#?wZFjIXI+gB&jBi)JGFmXkY{lsvx9Nht0Lh)F8Z&V zwt%*(26@I{S7elJ0uV2w@Nv*l85z&H#&Y-(bj|9Xl#0s^^3eOaVBglQQRIbcbSS;> zWj{k6^c`1^F2aWAGymEHd!bZW=yJO350>|p&X&AMBxywvvubZC zi?cj^2X8r3k*NYkx`Wl1osp`YzQWb(P)Y<#3qsv;H4}#zgjFKb`tbhxe&W_4w`;z= zo@Q}VM&9Qk9V&vBl0J0I1JHN-t$;jC0IojsETH5BDZUGid&x%|jC*p{b+vwnCeD0xg1se@mdnVY7nOkcy7nEuoy{i1R=uG z4DETbiSrZMn8%&ZxW)|%H8Gg__p;-*T_S#6oUo+qeo?;j<-zn!#I|g7TKl@zn#0I3 z=hLIP=Ncn3UhxrjMS(wS2-9hKp$zBC@t_d#C&7_;;(F6|CT-{)6WSimz+@vU`S6an z?%>Rzi%SRyEkX&wTP$2)!17eQ4OsTvuc2%D^-91}X{1X_Aheql@}P=&%|mSHnDLu+ z-d7ZIb(OaGE8cL#Wa-q@A%X7$=`Dkx&_c^b$2YPG!$gT*j^vbVDW%pKld-L*6)T;c zfV=AXmrJkxh7Xvcb%{hVN_u~WgsQE-(vxkyxw}QE3JJXePan4i${3HX$;5A)C$|R3 zH)0X4|9_GyAb+^Sh;JV3_8IA2OU+Y=ieTrgZ0G!S+O?LOG(~3z5HNl4?^`&SU(72s z0qb-R_&+X$AeGHV^bLj4|qrjE-plM&lH~mKhuq8;q1_#Bt;$9gd47s zC@C>|l?*Az>RJgrZEyNJn)9wU@Z?LYSZ`u%}3t1H=5O2AdJ!vr#_ zE>kj{o#fwxfrM&`oj}+58iDNJ86^oGWf|yl9w9v}-zX3n=H*Zag@v zE*6^V*%=aXuK4>%3soKwBS@E}WafTpo#{8xJY-p`z(_J7G~T!Ot8bQb(J8$i!q1;} zB+T&G{r=jo_ib8+mRbPC0QGvnNkER{w%tbJ)?!nN#S5*p|6mL#V}ZMo@X60BkXYjJ zUTiDOE(T$uXmZz6fiN9g5B~es)3jFv+bPW(zFU+qnft6&NynWI&MfluWzwdx>5{~$ z_6df;#Dk;g3;>;lalELA`YjFM!UUu{5S{vLpq$rN!Ffjt|G^rry2xuhkF8`QZR+Av z0766mvbag7q-xk{><)ejHCZ|9->T=Jlc{_ujh141HTd@BtoQCluroy8?ALLF6-rg# zcaEz3#8t@^Arj)>0<*7Yxl}4{w}3&Fx#yxSL6FNs_^`$;XB3w<=9LATmU(TrWRWg% z%T>x{CNp09eT#<}qna5@g-z32j})_yNLeEj?*l`;!qn;#@WF*KZFN_3zo2g|u zMVI*WGM9~IRm5rUqh|66@Qa;{d^acCIrAk=Qs@Qq@t<5GILOgZrypXZf6#|*U4L$$ zZcg$qr9%`n<;Ll_${U6?=2eTVvi;i|XLBI>=1@rRbhKf&gu{D$>!6D)6)rBViDM!B zLLM2mIml(A6b)B064TH&`fAcT|qnB7I3z7mGd(yj8=* zyxK-k`UdoDvO+&5Z1vQ#pZG3yPqPkYZHU#19TD$=@A=LS1@BGmepo+T|6|rCdBmX! zHxV>ZY(U9sbVA75RJ!;`CPYJzd}&}S9p@gR7eiG&(OTio6euqnshv?9&HqH&{>>=Y zIEB!YMQoPtJMKh+W_{!^Jqx2tQT9!#dl4gkyB?2;`zWGBFnK9&$>4HDaj7MtMpCPH z9Z-|>VNpM^Oo-fSR;&Gs(w2~$^pQ^~JgVu-Y-sBz%ia|g=ayy##M3fY?zwZ8 zlKepGNHSuU`uYaT1_}&Y@4$qgiBWeeu2i1nIf57c=c7s1Jey|>Y#qsyua8{YBv;t& z3>c;a`Za%(3w&S;NEB!ZqP-)QBPmD1!b|}@roR#aPNQJ&i2ieXU8fK{{!LPt5kHcX z2x$I3LN}yt5+TRmR%vBXVz7`@58JExik4KaDg1_QLH4zGZuRO{Y%oYf!3_wFM};wq zFcqc9J+j0f7}^YzV0;=M-;Fs6QmdgeB2sU~jp=Ia^mq#}eI^61s0*N)5=LbP8QtW7 z-XeYI$~6axIP;HxeKoW?VJlTgSD%>frZ%}I)n6x`fj80bSqC!phf8dw6sKCHeLx3lw{YW{*mySe*jdhqfAtDluNV1=0EJ<vEI+ zV)1)L!V6?)@M7RE*bi|kBx(b$R%inC<-gW0Uo1rW5rz>Rxrb}P+>2nkgG9J29cHm3 z|M_=b)jk5m&V=w>czP;BdiirM)Znz##@1-~5;#bCH@xNrrU4ht3b;{Z0m`(1gVxRz z=7{hOp3H!jhz|l83VoywD2R%*o#PcE7<9ky_Tqt<8o0DgLNF02?RhmM>rX46yPJuP zU^Y2{KtJO^ylW+Ftk#&XbK$z?0GZ=P+LcD^nC;}Rz=Cty{ee}6LFpD{7MIwwEL zwW&tigL(=lkyU_>9rO}1py`qb!RPtprh}OUvxQpDKV74fKlEScPM6T*AHEai|Jq%@ z693m=w#G4vH?539gZD)xam02tI`LiSY;M61ek19%POcsyDK1F?jI@3Id_@~_HdbpD z5Vo7q!4r1K!_KlcTB9?`3>uH^RH+x=5ot8$6)2oM=`8s*eu|<4K?QJ^TT*mj=-0$0 zo;r$iN3^>@f82+{jOH)0`K(yZ6B8+YIyA0MEn(m*7V6a9t?b zPnKlHUzbfN;xA8^-Z$ws)d7RpnO+SM{=);m>!7p;&y-SV7_gu(_$0yb0Y)&fvy@!X z0%)sQ>z8mEdM2+fpvYS3Zo{OtSJhvCoLfl8nq~y6;p5?na~s8UhE>`}5olo^rr~4* zxiqgXNF<#=fiZd;1m9Ca0&nJk=pOup3)~e}s+3IC*nadMmi}C67tE77V@@Mo-Tw#p!MZ+3w1jo16RY4q{0f&W^|02Dkek@&$ zKzY-1yTfC2$1KfO7r_Bz?dsGk_d*G!gq7_#B0mi*HjiEl1wNS4AFQ8b0Gfh0 zctqQ!f_#3?<62HZNXC!}T9NnbYMVR4YFK1GhxKYk$q#xuFRV!nOa=wU9*cHNk-YUK z47zO0>3aO!gqNQoU-OrNAXb98 zerHBB1b&nF0(HF~DqERkNJR5LnS@iMJ3wwXyr|*NF>kev$WNcvW4S!}V!b*p|B@UC zI*(@v1)g0(>^u++C??uor68e>iO;cLQ@e_vrhPaVYzX)=8iz(AM?woA8E}0kir2eT zC5*8$DS{ClCfhFM_N5UU=+j{3WCRwMBuC}e9y@A&#!O5 zQmrYXa~seDbO`TumZZs5TOok)2 zYx|}4;oD^)iF!V~aqi!m*;%(VNS&FZht`dom~gifLHXoS$T1l=rY5fsitCFNPB9U; z3l&ui0KNr5R|=L&%^|MyWAwZ9W4%(n)KRP!CBQICuY0h#MqyD_36Qm*_(Lg4RE+6R z0qp#H2%tCK1%-V6T+b?hunc9$|A0C`{m@sS0$UY8_|2G=pEA1+1w@+fQ(UIRqr4jm zgtqKtmkYxYfh!{v0p@)!ttt{&j#a{FJk?_0Jk%!c9C^l6F_1N64Bm>AY z5keGvhRO-Kvu~r}YIX4leP;OVZw-zgkL!d|B>q#IGki>!p@}8dgHd zoxC}Jk;WVc@_s2caaKr7Qs&E8r#Qv}d2oFyNtXq20hjVSwqdd z7L@|wK&6iySSh8y_+6`$zLFRZXTEyBi;AbUZV$v$PVP*P!WWwL>wqk?gEyIie~biT zsgWyA0Ifg$#VJJVP7da@;UZ}t(5&nZQ;euD9Epl8bW9<2$guJ$qF()&!AoEAh(hzf zwN~qGJaT8DCS6gN*xm%A;W)jMa5Y=&w=|V;f+U6aq*ZUOcZV#~zGJYm#9&R_$?_S`c9Xrm;6mb^|mFL;@flas=Z@4-=u>*{*wsm(Y=40A_9Ih>|bpXDPyb*aH z*<9IF#G`QDPv}3@|e@b63&* zVnF`=SAMs*m(%WBTnvG=D>KA1)mIxF^1Egip<&YhI?beO`=nwncvxXtV}9We5bdbO~%3#DuAx+Hwgt_XbI3Gj}ZaFA>T|?3=abo z4tF&5SlryLfQ#s+R9286@2wtsgy;xHOCC#D}sVKppPk)r`L8>9?TduKK?ABlH1GmHx-a3({wi7sdeQt-r6I=h|oe{yJ!^3sB zc^ulIJlA1Fr%f8{IL>o#jhT3QE^+I7bm?DiJgPa-#?RuH@90?QS)`?7$_A;VKv$Zs z#_qr7J4^oLd8zX-KeFp1f*SI7UrjWd!(W~wWkpjpJaQC8om`P{JeWIQjY>ZFkre-% zy^+fIz)O_}d}BOxS3n`HA~`+PLS8rc3+nkOJL{Oj1uf%t3-1AfGGczDFjC8X0T`DQ zU0k#bwN+}<`PTJ=jem10Z*F@C;c0+yqthcXvpi)AG>|6DHH0Ix@hwj-9)9zRG0f<} zD~jShsaDF{3YL=JSz{*E?-JB8g&%exr}t~e(PXIm(G2T524{?bmFa`am>$yZzqnQp zNR{09QbZ0w5s>IBZ1E>r&8TsCN#^|3=s7W+ieV^yIs7>c?Qg6;Ve3G1^uCD?F8sM0 zE`hLsCabj`BXwLiHC>Ag7JDQ=7CR{Ql9rNJef)SrSvC5j#k^8c7EHj(nO)?k&bz>A z8AC&9Aupo`rFr^|u$SJ63mWQ?j!5%YO&?d;K?EnF>h5E1M|~I54YPA98zu6+or~Kp+D>l zrA;+Yz?}?OQI_uA-JP^c|9USVxAMR8;zCl=Tj@~ghc3)bqo_jpFr&3tyzo+%8)?)F z`Z{s1-e-1(w9$zfa|RNZ4>UDwHRjKvEl5!P41Hr0UEo2huI2nh3mKJtsev52ydr+Y#Vg8_4+PJP;F5PN|Pg#qdK?yE{Z3=Un6RpaAej9To&L%w(gn3dDALqjP#Pq^1+}b|vXkpDmyp2Vl zExFzCFp>7=>|di|9m~<=%GGMi6ii9-l7`u(N6NgFr`JT}3cm_@BI)XYoEl{G4eMdG zj79=R%=$kyg`PA+twrCngrYoOF>`JySk5LGRZ7G6W5fQ z+VxqV%15LLOrHXmcuv@_5q?82MY%{0CWPA;nET zpAk2@QOBH3M^w$I58&&!=i(@C(!T+J-q_lX=J;Y#}ZRv5{7h@Ye3qjfl@gHToL9%=Gd6w#*3 z3o9oRXIbzSyPff-JbmY*oxT05Aoy)=ubj9$Pu&t_cI#L_MmxoBahMG$tq~B2G7ZMY zX#)b)XgMd{&;-Aai=;Ejj}q*5phBZxUxQm$_M>}35=-AJFXs1fW?;TW2AKTGXIlhH zbIN1shI{Utiwy}Yqt_~d4{=(+8%(u5QCmMqf@u9YQlx9JO?hUc8q9|dnB*DuG^dBT z8Fu6O-+{kl^;)uDVs}mdv2Y;6Xc)5x!k?UGib75EPfdu;vP}g|C3VWaJ2Y2V73mIr zQ9?saSluTr&v=z^Fvhw2uh3)GQ@%ts>6;*E+Adr%126ZmL(*j)dH-kJ7C8ost8mwO znvhfqV0?i1?+8+ap)AFB?PmIHjD9!(Al=s|=y`6cQ>{cV3aDAP?Y`KL(e-F!tx+eC zAN(vwALWXC+IBSLbGLb|v^1+c$&|#*DWa|^oGer*W?+O-Uzx1;|@9FuBeXb6+(~lgIAE!1U zDE;uxkDAI)_`7*klY1HRB0oqVIh^7x5BaHT)w%=m+s%njabsxx)h4CQrc-FZs0@NW zk@b82r)K!$%t5Viw~p}eWa-R!?Rv5i@NX^SQ7M=FZEZgY`w36P`?No+ssqo(r|%CZ zTX?JkrlTQ-wgdV77a2qq@)KRK2~{#HGj^P=Wj2w=Sb{X$((#9)>JV=TX8FQjpUt$} z{|iy~{%-I0!rWWGfKYEN`od$0NjSN<{viMMwL7^czB82PdeUMuqxBPPN{^ZRU#tc4KyAL#iLDV=ps>$Rb0$HrsNmHCW@DLV z*`E@FiA+9{#yF#d+t9yXuJj0j#)iW@bJ8P<(PJQPwA+p!LJ)v?zl^G>zvdf(w@8Cp z7$gg)W*E5+96Q5Up36iFSum}Mm6pndFIM5hj{n82zbeTYB_0ea==kgOSXi~Tf(7o3 z(sr3>eID-9!;OS|^ffBJ%90^4UZSU&INMbQ%Ha?gWvKR__GEuDED(g5`djz{e|}=o z=aoSq)^a6y*&0CTVn?Qn@J-{Ie#Rduc_dn1%O$>5Ca$0YT6Sqc)NF5)P%C(Yl$8~-JA_Iv3wvTy&_e2=Lb9E}{x=@9 z-MG}Gpito=%3OkjVdA0BLd1pUJ=t!98Ac#zEh9mD*4|*NWTR z97Woko@4d%nCUJp7N2#NiaF@|dUEx*kkxkY>$6))m~Bk{$0E=lsl&zK4-zX83gAOD z0K{RwvL|&aHvRX>*)Kw#vAp(AU8RPr2028r06MR8jS7k^pk||f-}jA2@zb_P=j@;t z1d0BSWpZW((P%46v>?5WlZIRrO9x0D(;sGhaphi}!sD%nrd#7rh(7aD`kVth>h@ow z)&3(J{2qVOAC5`(O|@Rn6vttTZ8ux@MiU1kp(4?iz9S^?ONj0y@h6`=t}lD@ zHfGAV>ozZ>AZa=!*c5O>K_GbMh<~{I7YTTT8C8If6cLBED`K0&E&KS@Hkp>noNL)T zgOGyNL2O|&SkIek)_FRx4B^MPpiqBtjw}2t`Ba}L=(QBFStww$f(AL*1nY|=neuWv zFUj|R?nylw(e20{M4I}WoipemGdf8uv8NH2#%_x~1H;o1aW4h^gi( zW!qPEi`S(T1jGf3oMz*$%F6CU zsLA-Me`k=ZvBkJzCu)dl2tQuS?t^fWEdNS~qZ(nE%&S#SQ&&)vMS*@9wMqIrn%p5} zaqKP6b(JF--Tk~?nwhds`D2p2Em~E0mv(do41EZ)xdv02Xtx9DAqJEI>1#m3WGLPP z1FVz=dXm({qgI?Bg~{7Llka?|A+)HfGH47J0!o%^o}Wg$zyHBd-|;*qlz}xzp#I?} z=n$*@$Tm6u$M0*F#vAtL%P z(Q)cM?aEkoi}w4uCZ~=%8*F3$!}rI&&O~uB6nb9N^SiUOvG0|D&|U-le51IOobnzz zWK{A2B!Vw!;OPXQz$VOo=4AS9$Zb6s9(et$ujQo4rE*zpq;bJ8Yd|i3;K#G*Tt>}mZBBc&_K}{g`D{o~%uN94h9+0ywXlM{+IxF^r+q3%& z-XpeTs|cqC|BYEf?7;Ss67%s%f4NFlH62i zztFR15gq8mQkbP_oZ}3?r*oFRat7Xkz@8&ns?2Tm+8eHsldsKBqtKMJFF|}^-uioS zDqQWzwT;?LF(3F_Yx%p)DH+i|7}KX%e@j-j1KD?yRx6hY^sVAAS%(novA4%h(Q|wU zGt)iD?Ib0aa@TxtJNjn<0Ql8GW_X0rQ+|zkx@=F{tt-(d5tESgEH3IIGP*%Az+_X| z$;T`sIbrnK6v@vPls$0gkaW%WLKO&Bv z6wo)*iO2iu8foS$ju1bS+g}Bb5Rr#^v6nkl|7QodpT=@_q#uIjW)Hqv6(f%4;f*#X zaix!~`YlPsv+WkH-{;`c2FfFf2QKe68Z)FO)IwziNHPDL()A$10*f*HL4Z2Ttn{Oh z^;e{DZaGCdl0gsJ-CT~zJH7_35^mjXSsY|#Iy!oW!<=j(*|#`M!HDM(gwm{p9~?_a?Hdsnb8&HTLRQA$s3+xsIc|m6 zKNP%|Xt^kgSNKq2$NiX|Ej%n#a*!*z?6kyJ6hFDBqH~#DgZ-kIHfLpVAxo5<&5&{P@j! zg#LOQIf=n?E0e5)rnJzQy$1)=m*fdwqc;8FB29dgj%$p&Uvkca=fBXJzMF4;V<7jU z8n=e0upn`qye<`ByaknXW?Ekg{JqjvxzlA5lcceA_Wc8$ncvC=M$!@c`ayfd!?o={ zFaHsQO`%6cG36O%V$RDZzihac!ii+j0O4ECfdpAtlhk>kOe7F_!9+qwTZd0~^e$zd zN|Ghs;b*&F$&{xSGnBTRF=`qC%z-!wjX)p;y;=Ef<{bZ_w7I_%$cDWrC;h9Uw7QVT z!!_DUqZ1cldaG{0I(YfWfPT4?u@G2AkU;B&8Tye+W5;>#L2Y2_cM(c12v3zh z(x(t}{24a+3HcHQ|Fw@&&wrQ`R4O#h`4%A9+{bJ){cb*no4ah`7#%-pAF*w@@)JBj zcJ^&D!kEb^Z_lR`rc$D$9l9S&IA}85jjRRXPZ;N&XKPDq;67T0cKtOT&~THP4G9=0 z%D1RKY#LDqD|uiN=gIsPIlQLDlWc`FSKj*o#|9#U#lz7DAY=ROelIyX2RY^Qw2FV0 zSownJ7GItp&tqNu11=KhONSWoz5w#%E!od88B;d@ip|^OMcw_o5vZNE^%vw9{!6cK zoxr4DL6IA{b&K$g%}^$^$qm2)qYAlyMqi=dY4nNd(Ln7jN|b3->`n?^8Uq38EZ)6M zc#{%BW@HMD1BqT##zrw!)B2X0Y{ty66(*4*!hNO5h})Xi!uI`suB5_>^#uMQfi(NR z9q?mCeYFeoArOi{2gyg@|8fmYNYBaXX%PQ#&-d!kC#mBEc>yN`_h8@kdJX__s-m0C z+-w6iw*aX|dNN$TN9kYf^xq+O{Y$B?T&~+#=zh_Bns<5T2bkU(qi(d9kO1J2B7>^N z5zIc8M+Rw!=fM(*XC`I4wSvd0$dik{SrwnW+!~C9sZ;gMv^Ss-r3M(!PuU`pnuHne z&Z%OTA23OYzDzULEaz$hn2f5qKN2IM)k;8^6_Noz>0(Xl#55k}+nAjw97XY-B#VI2 zpK6)u{3DxCvu|-G{e=qs4ar$K+>h`0cmTYxQ9MWUf%V7Xbpc?I@RFtPtdi0|!`?e86Z z8{*OiEP%1!@R6zB$A#+K_6K{9m?nk5>GtjGaL*;}3RJ*VFgXQ4k{fg(?%i7VFSn=} zF+ALjV+*Lt^$2d3>_xp(*^^oE(va98YYzBX;r{n@NCX2~oQWy8po|;qE0OjwuUo9d zyy!^h>?yMpdvaD*a0nk!dXO=ujc^KbP7Z0f05AuBaj}s$$AQSlzL6yEs4J8d#3qG$ z>di#8*c8*q+*`$=dX#HnMdbB;JX}W_oZRBpgxeFbjE8<9Pj%&~`l~5``YwYuW^G`sW$frVN z*>IAkTv>P8`$R-1P5V9AkSR(pMN5eQAsJDX=D2!kia5LIUxH$QORRl2GeYAM5f+!S zO;?+_h0{Am915aO=`f{sx_|den+TH=*F8J>byqj!ECJI0xFW>sb;_Dwqn$Tos<$sa z{*yC~k1UjoO_o%bM+LSWBPk(0z2O159 z2p(6Ep9nli0;Z>B1slR2v&P?eT=xd5M>RVs&60YWCa7=;C`|l`q_7ncH=6G=v2dT$iudMm{rKO%^+hwR0M!Q2-4kTa zSIlriWZ-;~6M*DRK|?d!^+6C%3K&EwsVt%7<@;BthudY8oaK(;nVLhTMoshrc`%OB zDCN1);*tO92TIf16}}vR^z=A~5H7JJMXC%`x0D z5N@<#YUI9PY2TR19!u82)IVL73v@XfPCH!@S&QEC2uav+lJIciaiJ`;p+kt+65aST z%FkxftCj07GR|Lh=Yl&m2^QO?V08N#Eq9_A4st#^l}G=_O6yqssQkU~D6DgV^$Nr7K^R zpv)HFdoLT>sn;9^Ez%^p>_zh~CMJ$#{vF&jg>1=9Ai8Cfx;V^ISv1G1KDqjqepzmahU z!1n~;;FhVin_wR5*Jp9VDT=-dfsLw=kU6|!m$%N|?^L67DQy{Rg>|9Q&+B|6`yvc~ zLC@=6Sxlo{ln>Rn&)e&Cb}plEi}1vP6qZQJfrS$bGLR!N*O<)Smfwx0 z{*;9jDYrldtnp!j!esFg>nI_9RL%7n+Iy za9HrFGP<9M59LfN`PaER%?9cPu~SC<_8uha#87dzl=U@wY3Sh{6bF=HNeYsFyC~SU zj`F5qmP$zF@f4TN-MLg>cA-|4YzS?dKZ*L{D1om=abM&_RdB+8(HH&@ls4>2R9oYe zr*9+QFG?E%JQ&7dDfw7{yg!)^n^zfRCb{j&J&H9&-(o#4PNR|7vHSa>94~`cBnJZ^ zm-t!|F^EGUG7SB1CBC%7s}Lfff48b;dmG3Y>==%!LXD`vvRF)X?^gF_E_Q)cuC zQ!u8p>85H9GesLm-krUNM70EC2b_o8WpzK3@d~SF%`jzVg%wU{vnp8zc#v8^%8;eI zb~9>eceVm6jEKX7DMUU209dg?37IJ6md?n;wSb~#wOh*3fooa^l>4~O?(5}`tb~Ym z{@Lxl;deHC#B^u0 zROXYt{+rrQH~u`LkmD6KkC9+$Bt%~EwZCKfBXtk=tUf4RjgOI(MpjdcZUaGoWq972 zS|1r!QKX@FSojY6k*#xbn(>Z&&b{H(u;CaIQa3D=juT ziQu7!`$_|a=o1vUmB-`-sVU0y#p%9ns;|749LbN41GdM)>8;A0d1ivetMZsDwqA=l9BnU_~E zGRwIOJ=`u&9k~l(U1*QFr1`I+s|f^W1&<_G$(CBbvQL1-3?9Dp@$>)W;o=ny#SS{? zyIYlb0y(Z2-%L2@tuJ%XrCiIghWq}ElSYlt3vxw9&^N}b4k29OU64NY-14s4sNrD> zgu5KhD5ou})0*WSV0WM%-bfJ@5}^=L)5zWXm9x?Wqmsf{c(WQ|rGehKT z`T(_Y=rkV=uK1c{S~Iof!NSuKH&GK4F6Hq)`v>0KTit@dLbnsn?~@@@Eg9(q6?>QW z0U=Gyct&5 z>0@p!H9(t{W8cQEn;HxA?zivd_Z6PS{Q!w?_|Az%Lj$w3yNQ8cb!Tm4^L4#0ubXpe zbeXFiNn8t}@owZ1PQcH1E1Wz$1&ONR)>?T}v`bK*(HS6XiY>$;3eVin4xgu7Kk~hN ziQZY%*FUXZfG~i2*TrnshldGq*!h4C`GSxzsZ}Hc)ISQgGovO!(fugWJu@JR$9n1X zo$3uP;oYP8)qb@FLcUE02*4tDkNa$#7;Q-3Q>F~^yFD@Z5HLHF)H5cqfi%;gUZ&{( z7~z#%uE;NAhw2dEfq8!4(=8u5D)EL;N0PdrdiiQHAfcl-pQ}w`zRDm1`)L@}v=T>g z*JfWpVGk!P5mrTX0|3;K6dk6a)G-w?*z*WtnXd2-kqaKz%AxuSO*5U=$4p5C=Izs;3HVsLqYjvA^c##Sk49dGhHy6W0?Y{_2u{ z>jK7jJvUk^kedjE-{pTG?i;#}OQc}-O+tV9jk5;ARE)~uo6Y4~B*%(Yr%PZ^Lq^Ko zzn^drNB5PX;4f8V>dC6@9I61y_D`KLvLU5+!iRQ?+Nbjk0rWIgpf|zL-qb37YNGUj zI*LKOQ6oHME(q}@>w6`usNwANqBGu&r|A>_*^Pa+&qaxz=)-}u31pHc)wgY(s5-cS z0}JpHzjaDF@}40eBtX&NT_TI!i%$>loLZAgfcv=6zPab6tqw=*P>AHXe^p6fO^v3A zIML1kM50Bz!fT@$319N|#iT6`&%@~_IR3~#pB5-l#x_pRu(L#)TR5ZPOYc>vzsoYu{8Wy0a-J_CuT z2rEZbBACUJqo2vugM?74FV?bF8Le~cpMuB%i_(Q)7kEunMk4A9N%kmuEBiB_bx069 zXfp8~Y+@ElF;^T_%ed1rB)p`QGihK$*!s7^c-9S!$2C$?OFy}${@wfbF(OWubX|u{+uc$-}&-_u20_pZnke?)H)>= zWibI_(qu}kRC}MRh9&`M8M{3PIz*#X{oHFBYlf}5J$BOwcnOjlGHA+2$(_M<$c4DW zWJ4N0Fm74fG6HIxK`If6t_EcFXahd3XvoRVZKHv)dyy%RtkdZ9myYZRk9DP!C?l+# zfZ?7H5hn!UT=RZ(qt0&G^=Q}M7YjW5&`4>S$bqK3->G3%2{nzjMslTGl^-8=*7$Bs z3MoszJt`RbWu5I6S43(72`&EbyAxLy}?TL1V8Bk3?NGTBBnt z#`XMY$jCCLu9smu+}wFx)9$y*O9Bp%yt}iExZ$MEvg+E8mTWSq<`5hBeFk1VppJcA z+kyP?N2kGYqI0>B-A3z9NA&4MJ-DK=wXvWrR<=Olm`rYa61m2&Te3)z^}F_$Y@_R^ zeNrf6XY`On;YVNqLpBHAJEu zQWoL~Hprq7Za5Pcepd(5L_%a(=3Gvk{i}GF7C&VZ@QAZqUEyz4{sY{~C#=>up^XkC z|MggAe4A`Deeb{YpX$&CUbn!KCeX-*-mFkcTFv~oyyJR^LTKzA9QLzd@Zyjy0{6dG zi<>BP#n3t9r>TBPT`MB^T_J%09LLKP+;G)d92HStI7O)dioKU2;SnY?igS6QX}f|W z>Ja@Jo?Hz8jgiCv#{a2N742%^t4yl5*@aO5yc7C-u|Q)EsZKK8bdTFA`42lK(bf?J zywCcVd>2)s*xiFR9i9671${;UDn;6B(kR)~XKvX7Z8`fDZgoxlpA|C7zS$q<-A^8U zJ15*MfAG}1i&Lwo0eR$kNg-0N`pvlvgPwyrlL+rng z6wvP3aDm06vF})Q3Ndmhm1N#%G;ioS>>V4s7sVgJMY6=GAlR&{n0E(->dG8tu!Gy{NOK?Htji+sADlsL)~=iOz?PnQ{IyaRo!#e16QR!km5_mxg@ zH4Gd1svb@YjX49*2&fIWz&YO^!4G$R`oL{25PV|2KDXc2#W0D9uugR^b&Uul7yq3< zK1XvpV~->}BxecXx}odvTb}gnIq6N~i%1z(gxomQ7pwQ`6+nsSBFy5(Z*%#gM%Zl| zkn1@VG@*isA86cg^nP+J)gcegm@T@8mjr_H)JmNPycP*}|6r=f^|RS&BhI_~Xl-N#_2c7) zNF1h8>xzif15`p-+ZEZ>$FSFKIxv$A_JCWZJ23iP%T{i&lkB`d85R=HchO%TSAmK# zc}+}0Gq|xAdj*f|yIjFGIZ1-P+CQeOI}b;=9YvO4Rz!L&cYK7h0>nd3 zn*{&cZAlDv9>FaCZtIkUcXw#CfsQ(kPX4Et@_5A?Fa{PX;?G=PC^o=iooWDXfq;CE z@yU}HM?FZ%q?3xQN8NmwE~sTBA`sV}xhC{o2wiz)(aA)|L7u)r2PCj&!{EkxugrM0 zh8@k9_rswzbB6KFNcynlYFEtr4zs0L4bvcw)mXQBg=c?%{N|i^y1!mu+~nlsE}9&w zPVO`jX#0CnXs0N)2n!)5ck9OxLTU%#Wg8nP?tMU;6@~b%;Zy-K#r|xH1KXpM!gz>9 zuSFt1nPitB9DaIqamC<7mOhT5rsH91t9SD%kkFK2BSU5tG#i?p>(oZDH6+tGD>GEM zf_+T2@1Lf4Ev3lJkg6C_p(T7QlSaPzBfs>J6^rlhZ z%390`YQ3C=2JDp^6A(dke0AgUSG)f_IkLT9?tO+?{MWG8RwFPsT=B1epm4VlNYQr$bYir!T;|d<5|2L&ZjH>Z5 z88jS}oSEaz&A5*f@I|pY|FPPu=jA zTI8!t;E0&n`q*YvQ%b90N8u4NBWaj?&T>VY1>dGXxv4yVX1`j)Q~h8aP`Mcm_uB&j zivXlvzP)s59a!D>2Hk5U+42v3%X?~I&58t+1JoamMGVU-{Q;-lMRlUqG|%5~>o(Xv zE(Ztx&Ex@7Ns;+v!gUa|!{q+6xp^Ie;J+iT#n;Nwo8DtHNbTGZ$#CEVXqcEcty)tT z_pEYjM~y@2ppr|jMa)Ew4b(;b;jvlh1S3kh6)Y)lF_^xoYD7`eavCKh^rodZiz+9j zR|~%iTe_6XXEeeM91qUn|Kl=>twf$X_k4paI;Odm)+;Z7Pq&B$bs%AAdb`5r#AeM>CHx7 zEw$hv(!1z%{UgMeV$>JCuP1WV7JoYrOjU#CHXe<_l&sE-TkaaG2R`T+H99^|t@I@f zbJ8Y3LO_s1+Jv!b8tu;ftNJ3Ft1YzfGP|?e|L&vGa?tq%o4t8P^fLn;r}(>=ZWA#( zi)98881dxBgzLB-q{PumFsCo@7rlDjiHqtbEFh@0)58g}gv z1M~mi8lNn2H~3;2LoMw4xdTqvDm$W!I@VSKETuvSScXnQ3O~S)k_asAwwOEl6$JkM!Wz zf<2o4*y1l_g4O-Tunrwq)g!PK6eYVkFGccrS^Itmv#0LYQa8O%$2}_-&L5WWX~X z{&C`2g1I06(?Ctr0)~FTWlz0^GLyndbZNx0G??IEIoXa{Y$GH0QMP*m^X^v*lt4M4 z3fb4sFSTQ%05{j5>UcG1I1~X}WsSJd;@{TJv@s!Gs<@0Er{QZW{IyQp2%Sexu3fa-3)#OLVZ zuyzz}k|i01z62!{85{w=NDI18TWquPSP^1Mx;d@TH~OJX7%Y?1{kuN9t4sW8U&iM8E@)cejB>fniY0H}3?1n)^lDUG(TYz< z$+R%{hF0^gr<;0nKUX$XeUCDpxAsy`#8h_>aP{9#HF(I5p&n}emn#ez!S75QC;D8u z1%ptBf4$`-Bt9g}=^TUoNz)bFhu}Lz+-F-&{jWn8>h>ifS<;zZqlQzp)Rk1rmX|g- z@b~BXrG%O+yfOMq!x6_aUS(QGCK_a|j0s2LKcVC^e=F9XICQf8@q%A#%~0y*~k^AP#8l)a@Ms$G~#cy1;|^N zx2|um6JWvP1?kCG>b0W}TOw&H9{YwtDKQ&(ofOBD+?|CBKF4}P7B6m?Ulq--?qek&usYg9c!sjj zOYhv{jAWjf&zUqtvAAKp2&tQ{g=P+J5$tZ!2Pnos8sLsSZ0`8O+_61Y?9zloE(kwMHhy)CQ}AD=9|8TdPLF6dV3tdDEx^wQ`w-wZqgfL{a= zzg1Cw+=Y)I`T^+~I+QDFcHlfaq_F45@_qcpZ(h_hUFf$w zL?4s+qPkbPc2R=0e;b6L%fNo2aYSnB{rItDFBiY=Gq?BeM&xvp-cLcg5ZTi@EMB$Llku<0j5zQ3I8I0yDgS9 z;UAHjUGXVKMZorWfswyIa>W#Zxp&BZZsX%D1pFVq0&S$c<#8VVoo+R?Rb}>>cT7Br z-rvf8!ya|?ps3IW{8ER1`eo8r&FP2s4J?gDAUOCz>|1(9JR7m^gxKw-ci?^yY^oqa zOQNDWLenpFIFTA~Pae2C2!jCv@6&=%as#h4Ld_zjG`1$-#o_y^3PUm&f>Hc+!wp!g z+<{&iuR5lOo4<$xFzoiI*iTw`x3p=lu5V3V^Vdp0 zx$lT{^VA~z7ClXPp+UQ!Uxe(cakAfxQl{_jCCYDrPQ^JLm8g(cXV+_~?hoWHQrl14 z$}c_d&ds1L#(`dntywB?jjA3>G%FFbCFSU6y&!hFnua$Qt4ds5_npGVfqbecROoEi zVu2Abwjs3pr=rfiF>cp?4ZZkkOv-9y^z@%};%59dyj((?DdRc02n(kNRtm(H0j7Qp zL-D^3D9Ihwdb3Q`6C#qOlmdcj!S;BiO5jIjV)?}LAVpw;qbB4%Q}HMn9Fh>7BXZ_D z^5NbIKk0F@h|i+LIGVyj*+-e~9VtTdwt!GXujbl|Mm1s7OSoy~X?y(_R73==bL}+L z*O?5vVVG+yRRgwd|3wDrb|c73bu)w$cCo_%I4^6@7>R=j5WYI@(PC#=OStHex~pS# zK8+AX-`{o@#`I|x*E{6h9NhgB=KkKS-f;yvDRj~Izt$__aJg2bnX5c+c(W!l|iw7Ln~4(;O}pS57s>L!$aQ6pz&g>zAPOs zNNBuT;tf`w+w~Ro4GV z#z$L~5${f6OdXHJFWPjFIaC~lkn!+h!Et3_;`~;(nK&84^d5F>{v|90S+kC=cV7aI z@^oAf|D#>RiSRCcAMhN2Nkf{ns#(I zh`mjJ&H*v&=~gau+;*|m3Yv+LL>N48a?oNlk?!Rh?O0dO-(c=}yenLSKDl6`F(TJ= zoFYvHKG+0;5k}}EAF?X2gCg~wXX@+zT&B$&-amND9QxA4Eiri7f81_Ov+%#H70&S$ zH)BCRlS4n&oH+acEI8>wDHkHcrOC26n(DjpH4I|02^i#zi!$0iF`cW zyITL0Am`Trgx%Q2Q}t{~K*I-b8X0y~IDd?X$m2=U|Ni37P5%oy5}#l4HVM0kmKIR> zhNJApeWJ0NM34YbUnk@Gr}-&@Dv%h!u+RR}?RDvJAcVlqI*~0BC4n}sl`w3Q(t4DG zl+@irf~VV?doxNyfQV(pe#Dv&ANS$mJ}E;eiuPlAdOBj0Y4LUL$j*=&HRNr7R4+zJ zVbTbC9*a`bH^!9VqN2yWW6HNR-4Qr4PvRECiF?ud?`M&a8}^>##?;HWmE@UBJslz4 zFJ#?e2!W25;=M`iyV6tG-tW$FRv2~6`GuN4p2TB)?t2_$^{+)=C9adG_U|i2=BLJ0 z9tIRLUD}^NA(6h6;tH`g%wAnX0LR(B&qMb%WYr>i>}zdh-iy`vj7r!)CjmEhj<%d2&v#n_eNy3Qtl za;Ecf-_n7J^Id}dxv@n}xw@vH$ZG?p-3xq%^8t<*O3LS}l5Z3HxM2_^FzNZIwHfy3 z_2UATjWFz>JL$Vlju&xC|8p8BG}bGu`{j|e>t8H!qb?Vj3P{K7*F+j zZUxp8PnV~4HA7DX+AJfyQ|4?}|9kb3nD<7#)xn5yTm+>*;Oz5+9{^A?PJ7pWM*C^a z3H>GP6o&ynqctQI05Y@OQ&Ot%iu`JJ>2|UMD!F-A4p+Z{4IcjqcD)6mo4O6u{y{9q z2gYT5*6|@1^F_AU*?}Ta`jxNmULWL=;pn2f2Fh;z(ZLtJaEuwsDc>n0GS3#yGIi4v zrf({%tqYA(=rvG7v_WN<6yO6f=IB1B@56|UwHIv@?mts8@*slHq;bfj7LeE3uFFQInTja=h=MfS}06~wBKQz5Ib5ojd z1<>c1$xE5DXP4#tLh2Ba$sbYbaR@oSn z!92|tKx=Li|EHZ?WI)F!@t(in5rHt&C!r8uP`Lo$n6!|OI$>=-^0`a4^U*Xgf_GCH zdAGwgw#W*d&a8R>Rs8&2$JsMgizWSJ6+jysPHGPbe96&`rH{D!@!8ww z&i3~&(~prB@Xw~75>h2)ff5M8dpu_PkvlZY5T^(6|_lR_u}uvUEGpS0`+mMY~u7l_+0W2uxCYa%8ma{PFOp4q=8vp+!9^3SVVsi^<@P7QhfB3MfY1M zYLgtvk9B~9w$M^lr%DwDn||5aGey}x`ni8}1V@O3SpXY-Ndps~nu=5^P*5PlDR^r>AHBS!PgFnX`WSvi=PuL_ybg*_PQEN$UeOc@SBE|P zOZNKR4an8VKVGCh1_FBPo_={gdW4W)JLt0!g+7?BuLd{1#r5nt>AhAkA7{*hR&!+4 zw|SLFl6fw<=JdlOm2n~EQV^d>KK_}dd_{-{pWKRwFJ6;K0B~+k+m^jsY2F*xyi3^V zT9Y(QXzF@)9poEa`{WO*ll?a8>FjLr_TD8GbxstUMl|Xq;>BCP>Zjxj79Hkk4ELk2 z-<#d~Hion0;XnGX+%a|l@BDl$lqeiM36}{taigE5Y_ypRvPqDme_}Zp=pm7Hd0N7oR#0|LElTsm=*w?o1{>c3N{D#{JlIJ7JUbm-s4Do%2 z-4@D}-_N4WFLkBEkn! zx57>y0FBEWTSl7?+QYZ^H#XHCfT!Qly}(FYVd{R2Y3aDKGLVmX^Z0X&&fLj&i#@^L zn0a{APs`I*Ha3X*mb%E`f)ko16h2zoBo+0UOxGj%lBdc*Du^f5QrFZiGP;$A>@S|Q z(T3y53=^uQrH#}-NI8@^A`gD8JJ~SO)W4 zTO1C5{p$sIOT7zJEK(eZ(`o6z0eHTA@1LPkQbFDp6Nzux>7Gv?)P5Y$-UQR!;=V)5 zHe`I>uRCPP61`kieX}WVG9@O+j^Kx;g)1Pl8@E~;mfMJ^e_m&!>~J5S8S+PZmqJw6bep|&=HbZd z+H7`rw(vD&P{4W^PI*N|eSLk~H^BnvV;}b;XlQ5%ak6>2I~3GEWTK3fl^{s^L`YK$ zq5ELNftfaaku^;a8;exC!tHg7%fqKK;t!9_{-FpORs-&p6KNHAXkAeKC22c0g3&L= zjReFC-&xBbkicMS>u>vzX663ClZW*qM3=nOwvf@1jD{_Gj ziWV1rhM&_jJq~-wMeiplKo)o7;^j)Z|K(Bo$#wplxW$N z-24GqJ>0m~nKy8D4KLu`dnIPuqeDi0feTM(#ZCD3TIX*3tH>-t4=Y0h!rGpc);o(n zcI22Wf2&}vt&T9D)Y+)EH6oa6S{82V@tx?T^8~SI;}ogutm+eg5xO9bi8e!RxWNVv zYQ}U^Lr?oeF%REEV1U?rG{8`@ zYx=AD`=b@>!-#3?JzoAaOf&zABPjNKO$>sJi}LYkbnR8t%e)La8346V`-9d36A0x2 zISRHsi3$BYx){9dM& zEV$8IGx-5jJlb(;@!oYL1>JvimFf1Heh^=jD+n?({Z8vKnKjsd9 za1e!fcZV|dj@PNF4BmthlE0}(`83faq92TvBQFX*JL=4*MGDML?krIBj#~9 zcEn@RGd*?4<3os$Wzq9xDI(>j9|r0^>moP67~_-CLsbLLtN`Z^k;(|g#36T-CG0qt zyJ%g%DZL0|QhtQA!&Zl4``GJ*_&X574`m!=(tS@1%KriMjh`+JE6SLj3F)H>w{_uL zMO)f0r|Yt#pCxHMi_<69V+uF_e6NzHa9!xy*VY?SU0mR)b8~WnAi9Z*hI?MtU%p8K zf$mHe5BRxJZs=Hc7yNF+Gb5L|zY)Aj`qvBi#q@I@~=NEHGTV zWXGW*zrzm;#v)8`t~9+5iEP@-ZMdF2Af@k*Hj9Hxzm!=Hz1(}gOcqAM5FFDxW$7m} z3<=3+4Yyuu@E7toa-PE0_64$qYPoI+NgLj6;Y|GyfIwN#! z&^?fxpu5`1uK11sn|f4X;&ehG8iA`eZqEpE3M~+u&BglWD2-I=;*MR;9KL z5}ueik&yb#M%}jGrzpVzddq@P+N5u+U*`SGt zXKmblu&pM}%t}Q0rOZ_?M8P#^0Fh$}EaHI`y=GAeMi<pKfoX%hHT1Zv7it!cm7$*WPl+jU{(5T4d zm`cgY$b>EX#OGU1GRc=BzH``3Yq3sDG@sszPDwIBcObCh}zrIZLv>rMENp+Q9h=^BI+B4gev;7!-%X1HaiB^yx(zhUb&iKNH| zKcJy9jR?`md2K#EF^lk~09FIEGtZ;He>~f6^5>{MMHHtqB4Dp3a>Y6NbR{cx+QBi( z+T8*~0a4Y85CTj0|4Ef>ty*U-lPmiw*#~Nr`TG{9ivqEuqXGb~hxifC-vsCXsu2BR zis8wi9Z}d^t(GHXQ=r|v&JQ}a??holr#fXrs&B*Wye8MS6Os?yIL70OQE>D~oPVyg z0>6159ob=odN$DTEV6*|BnfKQy8ct`DqVMQ;4JYpe{ zL-b()G_iLf;&Z9gc~#>%m`<;(XK8Aog)nBIX>~Jk-dbmnBL~4aXcv)JLnIWwp=4T! z-hrNvreBZ_4=Kc_*8ASO+Qi<2JD-l3PefAHFK$NS6| zsg54My`Da5CYt-EWp^A_P`72!f7_eKB%a?Dj4H?>yWnc@IivVno^4OWwB45jYV(ye zkt-8KZ#%OJzLke@iOF8bryi31!(CVN#K;|cWISB4COFkF5?}g^E2>DCP_I&Yu4G0A zDDJv~z!I#z6}0=Y?~(F^svjI(_BsH|qvy3-P+;Sq(af8Y#us|3`7$V@tTWEKLPwaQ z+I8wqSIkWggEfysAaq~`AlSfscqL{Le8AXwKBj8c<^{aCNc>`8Nz> zgKz%)Hx*EeSvPV&*o5xIFEN!<(0qr3j8%RnTGL-}|5BnZXbgH~AlGAhTIU@+(aD0F ziS&63ESSr}fG#$#MXL&te~J!G5$<&44pYVY;(bn|DECWPkg6nfxR zE@`SXg=t-nOyI@#=x`I6gU0!Va@>TS0E}EzTGf}w&DD~Ibk*ACui(a@VP@EKe#hNC z7+5QfdvuHGl!_oRg#dwyN|eL5lk2xF?mc_L5jPQT+Vd1h01bRAdwX!i!(v2yOfJa^ zfq#vMjVw;Evh=%uo2CVIL=A*on3T9g(K4BvHVhPajU|mJODLZc*w(@nB zKmf{6npmcP-(obG==|*7paR6u1`fdhwb7(>w;`g^^}FkDr$6hSCDqDiYa_InG6utL z*5huvZ>;kZ?k5s?sYArhqR^~*(NStfgbJ291a8^VMge;j1RQnV1Rb95u}YF7Qmm;Z zo<7R8Pt4Ydd!X@3H3~C#HC^COcMfbQX9E98(ay$v@sV`t!hYO{!&mJa-Fs|8f~FTzjdQOnmt9N%?Yc#noS{-I{enw?a`z~upM z83`Zp_EdCRgiDur%xnH(C5XS+o7$W|&=c|9#WXN5&|x8d#r2_~en6A1m{Cd6v?m-7 zvMu&~W@RyPG+vdm>x?voS~6j3s@XtTi*QO?UE)P8>Q2%5M49H2AOA`T?O|5zbVCxz zGz7vp?Y!MeyxkSe%edrudZ!nUOe3$Y z>Uq5MJKymNLH_psE4&0$FB@5Gnmxbvb_U0Q?wfU77gmGp4KWl}e`&xj9ebyzkoEA>Poo+Yvkvl}{E zV{NR#gEnN|p$8gYHJIca9huL~gAlo;C3QVC;HM`iyjcy}GjF>XC?MA0 zbO)`6cg8N3mtibHNs0;g!^CmDo-0clQ9Z03cB0`$I%&`OtQFJ@exvxQ(oRGuZ8 zrQm^yMgD22x9#nsZbA(1xpy6ia5k^UTeOcN;Zc#gl9uat;aHC44B*fAcOP`b zUq9}$+Z)rjPd-5e1qJQbcIN5;{2)bU(Mkr^nCCU>&~s**!Mj|=kD=E=6Vo629GsE8 zb$_D#WI_N4Tv?s3Sxw3zN563)rNDPbq~~GE=_is%=ybT5S7mr0M0_LWWIrr1MJIyu zG|@C8O%?9o{Tp!!U~7UNEd_J-auqi38T1E-Nd5+8Zb1{>viEihZhof*tOZD01nn>s zhMuE+lnx*s)Fo>%LFU`E5nV}FG~|k-@DPdm!>qLtOMxx#wB2ZCaEpMy-fxCRCsfqK zjlX`y&7HHE)K3KUtLb(eK*e8}qH~elB2@q#9ahPOi^AK5K$!envoGp{fZksyGm9&s z=0t59$H$D-PD2~>W=Vzr(w0k&`)&~-38&NHXfbj?M2HljMc`)8#N=d&NsURnKdIvW zUv%#|O@g+=f#bG^e+2u7<14Ngv#cn(W%_1z7<=pkO8?MbvEVA9zfvIGPdDQBYO>_O z8&Y~KM&(bfkG+=#_yrIM2{mH|s#@>?mRx9vtlIHajl9I8)qR*wsNdPf#Mq;(*`OU! z5G)BZ%`7V8M#6g!aW<_Iqx%tWad6hsrlTbc(tYAlsxeVy%9kayN0g`FDUxAgW19$> zSG}rY)tFZQn4c{YAWQoSABoxc931_KGQBR1gm-^|A92+}I*iTQdG!X71Rt62*-a+A z9?CDweR!BtP@q_%BU57`?-{@y{1D75CWKN(>GL`@vhn~)yBqq7g=yrk{s3G(3bRY5 zAnC&qnUYjSoS8{QI;dZubTUK-O8Tywr^+6#4xiarSQJ}V9I+$PsBCJc0Q|Yd2kAF?fq2(v`9f*wYi!uij|M?f*mvH{i_6Wk} zL1>QeNeZx)_j^tKLk-A}k;1t+H_5uRlHA9{)AL2A){DO@LV~eSUdUC7N&gTN_w6li z8T(#T?K?faxZ$3GS^LUro7GBPD(I z=Z5#h9(vMSPMo|#R4q5uV{VIs{dOU_8YnkChvscB<|mEz#wA8F_`@T1jU)boHwG*w1${D6=e>qA}X<$6&lGmScs+zaEbo8y&Zn6f4DC zw!8bk%>^qNp=Xvp1HHyz|^}mFLqJNa2>Lk-3nx~S2yDF#0xuoa*hGiP=$64*m1y#?N5H6rHE2feRrca^nI-^S!2V_PRAa9l!N}L3iO>_4oYx=7B{!ciWSHg)9t7 z*k}`6KK`OTBPH~v$!D*u{Id*)`x^VwxDVdzCGDFy2nbxso7fy`z$gOS(_Q;-&@xX0q42;rv-=+~_2nl;jiH2f&vVV@ie1 zh6*cZBgl2+AU{8i`>wr0NuvWMB|{|cLZc4ukWwXy{+yNo=)p1p7RBPqBLQV#6eT5; zAM3(SCp!IJD;_FnnQE(c++55?Mh+WetHVl6%o6JgbEif!KQT7zSyMmHEVI@(b9wK| zMK#T#d5Ds4?Dm76x;V;?4~{kSZ$ju(B7X|TSBl0|SiY;V6C!9=T8WA%e=U(99gdQtt6nP z=j$n{Wryr^U{2SOy)_jal8jQ730UT;RDZ27nd3#uMqp4Q;B{ zsq|qnC>x5i-CH6CAHsjd0AUXxx0NO&2_Nx>NV6pQ=X`izoD+(>d(u4 z|0wS2?~ns2VQl|J7+&?NmW88MWnz-uEGO#=Gdd6t^gHLiIR0Y(M|BHk6KQpNE3^2R zgZUg2K^y27f5N}xH&%yAvhG+qW__eI-hho?c~S4TC1%Lc&z~)X&g%@CQ&&Fq4UmGF z4v{AbF|ERA75fJTZ$jU*aB#4i<*0fEtI>Vf{Jh}SZ&uzXEobybj*t&`ex031kee3i z;4LJ(phEli9M;n*baT}>yk;jsu7u@B0m+9@8lfndlq+*fw_aU8ko31X+)LWp`?VZC z*zXlXeKWafB@JHMIJ%uUq`)}5j&C#Z{V|}!7sNp5^4ft|P4SBXqYye=N%d2ks%Bx- ztL;1&I#jb?yJ;Vh3d)-3u%6LuFR_nk7(dQ+2Qp8q0PyJ$aYWh{MxLy=B^F>I*Hs>~ zob@e2KK-JFL7RN!umXLgv?m&c)0c>U-|sBGA0)JXaSc$Kv0kKW)vR zBuw`%5=06tPb#RsaZ1LF&?kfKvWWmVE`*n}YEX8gGP`?=-T(j{QjN??vjWR@26WZe zGld2X$7<$!rQ!!)Kev%zgth-3K@=m5^2K8i#XMJK5{oXO5?-CuFq@!gB*(GAJ6r9j zsIBTJRn}a1XMQtYhS6IKvCP6bS=O^a?`tjLB}qoQD++EQg(oRh-Y$Cp@O)EAnTqGFte|jLbwGS~1c9m$<`9pj zx_xndE;Lv0IqLCpS}A%8`&x5CLCi1ic0FUGOWvhLS$9v+v<~cF3AK&!$?6wN$d|F! z^SH~759Ca%#T!w#V&dFu0Tesfqp+gY>q$b+0TMQ?mQG7;On6Ib7FTOKVX3ENro{UC zY_V`_YMGLZ-Sq4w2U`{^Tt8zp@K`Q+D%R zWsxGKY*zx$oF~B^D8$oX!vA6di)d3hJ;9feksZ)KL=h28hnvXScxOqcL?c3k7<4LC z=fA>TUVSpseMi8=g@mLtRK#svr&zq00KB8?zfW8pE@}AIfKJgQl+32o?%&)W{jo^5 zjb}$FCI!=LYr#o7s)x&-;eBog0%}}g#r*V-cX|5TlOh7#YTSDJmRJE`=Dvc ze}>9E7s7HP4LE8`EjT?*7h`i}IS+L-p%!|da!=fSk|iQ04++IyYoU3pjoUj^GN5tm zl=(OO6k`t07HY5DRQf#{R%S2dvJoBH{)vmQr6T35Ac1aAoDdzwPlKOO-D#cLzN`v8 zx>n1>Lt{k2S?@UaW_$wx78p_qx9<`~`ziDpiirc9n_FeknpW4)ipEX2dB=e8EyW~9 zWeBoiB`~7BJo#2I2&tia7kr~+C5pX=MOqjIYUJEqE>V=@@g_wlIb2-&69|omN-m(I zOG;{i^4{wny3!!a7#3FNUiZzGfnnc)z$_$Or|c95P}Jd!UQ78y7;~-5{Nek5E=6tFZNz>EO7?)to^Pe+e&1kg6TpwYKFQ1^Revd!fcGm zTb_$>NC|28!`&Ky5Ir9x|AhXNoTrC_%xvZcJC4Llo;DhxL)78GWq=$i#`K0SSrJ^A zfP8NBoHYM#YAgtvGTOHm+PvJgB2C8O%JJZad*o5{3^JnJwUYl%=G(BJ1QDKYudj0C zp%#eZHn=JL4s9|lww+>kwu6g7UF_C9-vfz(`F)7&mseR!1=IKu;^c@!yn6$lHnT7a0PMPd6@=BPhQJ)!gbfXs*=;XVv>PvQoNHSWwaL zVS2uQo1A_{SRq8S)UR=Ms7tQ%3aLx z(z(%(Z4$u{=#zWfRCj`$GvIyZtecI+wGgqZZ2j`PDH)!rAG;kijQwCik)Dn=vL@AY%1{Dba-{!AcGydoAvyHWX1}H(N zPgY^df(-6BNnKZVHKs|(iYnCNvv*H-M?tf*p)WcC-{nHwsdDlRD)%PMzs2nDw{^t$ zwUpO4eyy)(XeciF^MTLoHr`<$#SDy0J=co2t*6UA>IVPuZz)$Y!lU_w+l${ znoCa$)A_%H<67$IXxK`4Sh&MiN!7)Dp2;fbjwH;bOxH+;FSwB2n2Pt<(R|EVKv4uD zVG{_U)z3rz;y3edCHl1~W@x-(>4BLj5-|Iz;zfWtOOC?kkU+J5-$?*-U3Ejb7rZ0*fD$apVuf2?`-gE`h2WLXGXZa(n9ae|V|UH4H@VK(XO zb4O8qSg1D+FK$Rc%_gqQfK>Qx0NDu_HutE%mmV{tb*T&~xgW~jtmnKu%8yu7!fb;! zH114TgSD@hyw3Y#l`;?epG%%O4&*3l(Z9uYIb<@vuu^6)?a+LsI2q;bOCkoi5fU;f zsW8*azeV3hCM6xhv-XMhD(^$?L8>=)Kp_SD78-XMqvo|x25E575Bo%N-=~$*o|fVv ziX8Uq!2n?)Lc2!fwm+k=J%^y-kEWRj?T)~A?V#9Daw@csFU2dRXsQ4trU_bH;*9`~ zkV1LnMP!Pi-ziCQ-5JZ$tJOeo*h<}83P*j%)N`r>%>h-H7{Uk;-Zx7=?O8To>_7^+Qs8@dPZ)eICTMihn-)YUe!5Id!a zUS)@)Qx#KJkMJ>gY5m(C&NZj3jPDF89RzCt4Wzo39=|fN!VOtSr051ethoC*(m;$Y;=peBEBO7 z<3Ik6^$T%Zg0~7)i-U-?=FK4 z69fGrEh0uvlygmmjxL3#3x8g@cy@l;1`S?A^_np6kC8fJXle89E!_!VHhnLRROnRc z6)e4j90?A2?q-fUjRuZALoNkj?(DCnX1*Gl24s%AqEB~|{&Dw=|8>6czjOjcV{z|AkXM&b6SOn&KX&Z?(=;mMvU$k3 z>1T^ebfxTjx+pBSY=1?X{PG+N1fT;5MWAYd=azrUvf?F5Z6+0h585kqrPuCf_tQtI z8jvMOPBKBRkSX7q9|6fK<`j#+*o`!8shptNG2w%iWPn)NG=Mi9ErFcP9O)cS`I#R- z2b^ac;ZfwWo{5aWuHGME6OZ6K>-?DXtUhhcrMxu%tQYfsK;*jCyNJ{murVaobfLlL zZp)uHiQ5r^;0JML2j_dqe8{t?LmfgU{y@M2(B;?f_WUuJalWQmUfjR;7M_RgDgLml50bsYDfr9{K^S#%Li;|JHDqY={0jg?86U z0NEji75O-BcPT=lk8iaMNrepsB$&bd45FaP{Rjw2KDe$T>r_C^ipi;Ls=7x`mF zNt5Aej(Zf2@oX=P6S@-brkWwr;|dnUiBL@n^2J?PPQ+N^%MY52Fy1iHPJxix`LEa& z!wVP4?Cio;PAntpX+mlgK4|mVzgzvO8mS~Hod+H>Fj)` zbuvW=fw=-3R;|kHhUGnw`Ii_%e5No4tZ0Q9)HC%DS&k8Qlz6~CrD^w<&J=9tH4pf- zzq@N++|Y|9r}>>brFs(Z{%Xj&G9?JFLq)hyigm!+b>zmSU<@s4vAAE5HCc*}8fIq~ zEK64%{mNO#bPT1*r}u&usVs-7TjB>Q4+!Y@#>ZdHsuG;(`sVS+Ph<|~)avBEwKd_V zE>JsmpF<2qTrTnk+|C!zLyC%q)~%W!Ch(ob`&OrTS@&^rY_Ytzfv}M*k|iy4Rx7#z z&&nk`e_S^PqtlF8bSUn_HfbQ>&Bo~a`$o{RMxV4Eo)9`F3t71eyQn1-LfX1I0*3cB z4wTf6S5?n({1t%g!(_BUF3)p5U5F8S=L~%n&ETM25vujjw_N_4_b;6)DV45~(RNpm zzr4-56TBJ^;$RlyhElmIxj`=2_}+K3!6-SsJNHHAgcaox!;fEq9B#+W9r;5xzU(#E zfZ+lm%6;dMn(R0>8K&RO`@U^b9X4L}xA578us^{xcy{>#wyU0zQitE?aeWxlY<$pu zE&FCda!82+-POinA0ivlYaa4KNgn?F{2CgDQN)C*B6BOm-C&h0t-lUTl6F2aJL>+_D?^}QyYT6i z-+mr8mg_udZfvKZir91H2BX!@>688!3|$V1P2gU5SgAW*v@J*stuDMZAIaMXfGx-{ zKmq;nc+{*3CuVI8iFa)dY>jGeYMS-`h}=ppktJ!Bh(ow^!i%=r?NXaNtN1NnxrCF& zVkqn4)s#sAo?#}=UkqyC?}LTxf!_8D{&S(Z zUSyxKe?B2O;{_gVmA5ErvPB=u%%1Vq)@6o!SmtE4@r+wL_CJB---6ygQHFZAm+HP2 z383w5C(BhM7oyKc4t{_jG!Wf|UDCs;w&7SUV$$kWVpfgiVCFvv0}jkIxt4Ns2}?Hr z=|5BFX~Iu-g|>&n5QOkD%zykOXlLgG?l5m(z2wv4+LbR3!#GGlgX);G;vH^e*mKgQ z;Q@*cn~i7&7l-BHzK!V@ zFH*$q+mp7U-%(GfxMCNmtIl1bmBQ!fUJV|k!V7x?uEBc9I9=U`t2l@+qPhM16L|%# z@?m_9#^m?uyDat+c%nwg3JV&mAlSYBZ^8uZnb{pP&e1=g6YH>4pbVYW zOEi3x->t8uZ66UD*dhXy2S@X#%XR%@ptq$578|3NFkkE{MN-U*jGvgJbHyM;f(t@~ zV?^D!iB;&r*Zd#mg@jFp?B^mi>oxbKXs8HtOt*$S-Oa7-RE#V&KKao*TFk=%CHh-I zA5GIl{GdxslFhHM-K2yN(y(@a2ZrD~O2ng9*12;*h6}J~YAGGwBWY)b7GefX&)d(;Y~JhNe1r!0IGHyfO;9p(UG|c zI-lzDY^13`Gouw~uw&G$Losvm9n<{m<*i==_dz~xjqNLQNiC6@R{{q;eHmCDz4t3$ z@kpuO0IV9|jXRuVB-?gyB&#>FHa;3lMVVDw_GmNSNve+?rhJ|)E*zf9!amA)j}x8+1V8bR7bw)Y zxmQrCxBPG^eyzD@48xuJ0 zU86o#CXVln+E^!^HZb@WVolOlPiLNN1(R!pG4o4+t+C_t>T)CPIXBq8&~E;|P{uU7 z4`w4Bghgnsy=(h~Irk8av4nC5^_Ki}EM-`R&N`TOH5p`d}ECa{yZ`lef`**}WrZ>%;e z$V-t%1Mct92ujY*Wb~P$j$UYeQr01_!Lz!Kr}P2HFz7!Pxzv%RGvlW|7$mel?2wM8FpV zwZMOI>+XP;S^AYQ)F_Q_8Qkd8(_?wR*tPMKnyYzU8}+2Xi%1G>^5`68swq;DvVW6e z42G-9jhBMuBSWmdu zEmMYtGKb-#XqBD_JNgy*Oh%mJ^}o0(kw51=UXx>|#qd5K5M7Mi55&ZOPZ80ogc4ba z@z}bMh`!TkBeYBXuOb;%>>SjRL%#l3d(;LtvJ7Is=GnBowIc zXaiBMF2Z@=V$8;B6WC0lsgp{81bI(fh z8g*n!^_dM4aW>(QazGkz`mDUYk*x-E3Dm6{lA`9TQ`(EJn09|U5%^SQ*MrWglx6Mn zm5GNWhm=-h@@%*apNF^c;$c-<*2psMx4IBJ`cs!-xMv|Lo{{k!CY*2lcCuwu0a3}d zypd{fC0jGp$nR9lk}?@CxBqtw&Io?qSEiGj)cAMA6W_BvN_^~5R%HGu_v|WIIE9m; zml}N=`|zENLl=@WR7bU&u(ONJZX)jF|;l;iG)G9sf=zX zB-cqY+$NbBSBO-{y?*}=y;}>9bOInD%UIOMU??wlU@yC1V&TW4K-AgMG1O&B;1*-g zELlVr`MQDb31R#p-_hj3AaGdpn)`MiLb$2jgquz#r5kYrc6GWJ8v#?_wb*J{7y&>&2&$AeXeC zP6nS?aYvWZFLqwT5~RE3=5vO@Eo(O6Z#@o>5IJbYnkVsI_lB-+K%G*W6{X z*FLeQ!T!s{XYPmW{s?eK6KtSLnS*)lSK!WwCY0o?Yc*Opq#lQY)|-ML(7ku?Wbqj-POzr%&W;l)5g&N*Fm+Y$=pL$re!HHP@_B%n=Ij=FYKDU(Lv z+!_o^rkJO}g8XO^ipo6x*D==%P;`DxbPyR_o*n=#cCjcOqq_8{+AqGOeT8nPD*2WI ze|6GVr_Hh19$oisO_U7V8F8fyPQdXdFygNZID)gbX8J-eGrO%1U^@0wo9WJ&w7lZV zm%&ro`PtmrQa|fD*nKB;AGI_vlG8AQww)g0G#e?&L$PMUd)OCL!!})Lb9m=s7H4)L z7O~&_^4W(&6-p%c6Dji_AF8cW8n}09O~E=SOD}3X-+5ZRtSHwt21#UivF=;`%$(-_ zD8acoCZx8Oz0;3Pi}!@j*vco0M{1R=zBFhgnp4WaATpUwr|RoComX@u%6a1vZ^2}v zvYXJKC`CRpm-A%z|6OesNms@VDV?^tPxvewEc{Bcj#RUIA zK8>j|Bt3P7;be7%!Pw59p<&)E`$}991+~hv6VQhXq%vc<4wg7phA__ps#%e`1#(X$ zAfnUCqN*9I!};Auw=u%RAwY+P4HN6=`0 zlf0p2ocUR)!_pfYZAa$-EEIDGX^H5Rd{5M!NV%l^N=Ql=6a8!v*#df*+Ic+)fVx}q zU|)jg#EgSHtUZA;5netHcyD2PXj ziMOCV1zn#bwQggJW&u0btAKLL>pa%dM1Vu+h0H82vY>S7qJ@r6xpPjbGWG_&8>(*@ubw+KTi z3A)fA(T&zrGdFqfr$F*|huU|~lViZ}vELO=ph`~d7W=<}f2^}3MpVN0<4|4hdnL7G z0S`&;nLkY#qiH`;6l=4<)hEkPD(isHPF3n!hA;T+1pkz<@C|!?x&8XSBbN!3=Hy+! zb`f(6h;P<1C=lD{O&TRUoJO@V7g>IdsulnQ<+-xOM~dCtJYv2dSc^~#Irt^mGZ$LM zu+90%5M%23{k@81-^0HH+RJ@#MjJLq4XDahrUWwYda%ezgz8e`k<+7{7ycO+-W?YG z^yhn^H@cCrVNO2k!s2W79=HKL1+Qsc)12**{U{@{<9-5iK0=gYiN%!(FD)f&IVG@@mk)u8&!Y7vW^Wy5xRu9|=Q z%j=UC<+W93<9@uNHY zH6*mjxVC?Sh<QJO6xtrZK+IiTDTkzeAAvG2K(E2r71IdR7 z_iIf+U7>f8r7$ZlGkhsc#xm8kqKpr9EE=e-XqhT?)QE3IkkXqdn$PI^W1}uE`P17` zaq&9qQ%?+BJ7#EFu_WmD{>L=8+S^ECsQ#Gx^;MBSX3pn@5*(v`&cL#~o4omwcUj-q zP?MGpKk34XBieG;Dy(ogSD!pM(98(Y?qsPKc}^FR+yr5;@C}TJ$rv@VBIR{8s1v~X z>1kcHI_wZN5K2;(C}gBC=@sY)j#8P zur@Ax?LSNJi}G3UGi$ITgj=& z!pkqWkvn`Sb!L}U#T$S8-+?jT31PrLeZ~pJwYSUSX z+BnsW72l|$Cj&ztoxL9+&184-jo9DjGfz{y8SwSDrZ`(6&@X9d5guCp)r6#GEHgD` z4(hvGv_Leq9=s%ewz%1d+;zpb8=Bz{q}y?2mhfzamk+e}(DzTdAmP`R6n@1+(zjy$ ze>8n{R2xpPbx3fx;uI+k#ogVVQrt_SxVyVkiWjHFEx1E~;$GanI0Se2@_X-l=j6Yf z6ArtxJ9qBfy_52Zb?%b_lHtX&gR+=%y8s@K4{8!fV%UPQpjCa$6D0#rpS7;kvS4um zMC2Nt%993;63PBV739C83KZxDcfz~4MLFG)aoHcC{HMASrqPUUmJP9m^#93 zK>cz{DR}(HHk1#2kW0=DB-q1nx&d91lv{V3S3^VUg9Uy%Sp?O*ohRpS2pMD>kG@yl zm=UE%+?(E=5l!tAaj7kvh*^cGVktv#yzvz+7Z(D&EbJnawt@8r9AHnMyq&OxiA$_3 zBXxd1c`Ed#*T}0_*t^2IVXLzD%))`31D&2{Cz6wq=-Ky`G++(bNXx&zBiHDp{UE#NzmcIhJwQ}UR6RBUDD*2&3%e4#(IdRNc@!y4=#{OZS0+W$cso6|eJ z`^cM)$2p-R--ZMJV0<8j>ywgvdW~VuiduhvI*ka};NSV^=*`^qw03Up;PG|kT*&{D z_PPCS4-0BR;RQeF&{ZYkygkPz?#T8le_5CBraYXYyi#B|mGmEvEsUzGJWp|tUt$()T&k$JNdzEpomlc2r z0Br%0d%uglC#D%22SxCU!kGV)h$*;=-t-6_keG;fuw9yZ)y0j0F@h}YZf!$C3?hEX z_?fvP0^sMOzc?AKHRglZ4@$-*#u!!g&C%Bopovk8S_KnVgJf zYz&%}k-Nt;+p=Ic_lX2L!(9V=IU8OmjSu78fSK3^WRqUDEhdzt-yBu?Ss-hRptwZ9 z3|E+Li8mW7<4M+{PaW(BwBlWWyyPkp3?E;lA&Xd-d zu8?DwhQlSiE5#|6WycOmOB5Mv*T0TYJL= zgs-F^CMp3hzQvhlxpn?}*4_Jd+x^O>({;Q3jQ+O&cG3L-H#)!B5%BrL_?NIm{yOw% z?^o-%eAZEo(totSrZ#^kb<@rgz8qD{h+Wj%9Us;W?MRVPkU!>0>iB(bc;VPK;_8~2 zM5cB68BkZnioh$PF{LhH!pq4ZkAflO5j0r{-=Yc6!aNh|8M#KNTUxl~-EW!{;!mzU z@`2g6GMrvQx^38b%(V~>GAuBaTwZsA8b$B6AtElcSB~J$E#({XT@g1ywXx6CHl0IA zfd^^5FEk9K1`w8SA9|z|`}Fyne*!w*dJViK#8oTKnubPl z4ksY0!PnYe>D=P*!+^LWh&K8Ka{GBoS}1uh!l$6h5kbV=5HYvA){Ft~#lL*(1)PSx zxKcGmF#R%|p=5@?4j<84NoY76{R^L+duZ|c&)ALqB!YFJsuXLA%8$?;&eiO^m%|75 z5gU40^h*0SO2kWnkBUWtWo?VrytjK#PeJxIVczzm{TcMepMMNJSaGD%nf;C@#d>>}FC)!1&VxO90>W4sxb=#arjWbzw&_x!RIX0QbUq=EyRTvHL#cY0u5VoOc zv?YAz7X*0{8nKdNq6C`ZbtrsKj)*Xz?)$VXbJPa8t&T0@(Dq;|^{}}WtF3bb$Bfo!cp6cw z5*_I*uFp_!{!2SMCh~YsMZ=qN#*j(}{vg%%%g&Fh_4 zRrqB4EIYc$4sJfaF&yJaNHDtgFd?W-OfY;aHW7yVv#dx>`XtsoHlUaYBT>@|p5p3$ zJvrVM_byQ6S7=3U0wC>{q)TM1Yi`^sram!#J)*N~u)IQ{1Q*if5#Bs_6cLK1*76Cq z5COD1DNLuL%tC-!T+oXx1;eNLSaq?3P2J80F-{T^BX#Y@;^&`w+6SO#@_hX$dCUGj zLi$G@O1tp2pteAUCqA;5A16?69zV${egR{q@M0*Y7V8)PTd7BqZBMCVv?>#mYuYo% zDL!T6E=$LgU89vk$WA*!n-*sxUf28IJbQAR&D}4AUYEOkb<|zvJ&d!o1Ko(}hMJb~ z<+~R+?~zB`TV6fNMKWUYt)4e}Vw#>L^A1~|6$|s&fIoxGaFs(FnAKBD){M1ZpN0qH z=X^TCfQX+M{`|t{FZfip+Pdp8i}mZ;7xiVsmWUjaSsde{oa@twZ-9o?C7DY(SsrIy z>wNm`-5pc6cfEb2;$At19m>HmT5gSFyXA3{OU{6Kn{%Lo`q;nF*Ca&_M8uHG^~R4P zSLpM$-bC_yZOZOUFRj1RpH2#E&sSFPgxR7QZWxw()|{#Dhkvtz*fy3i=y$cxVz>Ow zOT`u`IEg8Bkomq^sTpFCJ4%CJnuP}T|J@Lug2tXxM2As&SG z5qD3I9dnD%33POg^vgw8%rJa(I=MCaaPn!(N0 z-QSb$;tHjQbGFo-5CF5J4lBL4Jq_Yh>RVSRH|s|o6G!Nio#;Jjj!{@%fcpKRTzL1R zMnMhCI}O@cY>mW&Qhay=x(NvU?okUBb%Ner;}%ZWIC*`p+Cv;svh^p_8g5kmL~ySi zkX^Vftl>P4mM3H*Tsq=CD8`psow?Q3Yq>8B??3;%_wnt0dY8o>)&bf|z#Okt=?g;X zD!GZfZ#aeQ!-I(Y!%Y}VVfk_0{434z@#W(qZoe2{Q7t_-@PcToSxx2{Pa1&lQ1=5P zJn+TwRcW>REvGWhQ5>BGMJ0F<#``+Bt}U!1#$)EQT&q0u$v0pb;lgG=2nj2Lz~~4w zH0L}g(ZTqr2#gr>O6Jnul=3`qXIe2qjqqV34bx757&i3JF?8k6?l;oO(C%dN9=5v7 zB{=(S&l{zaqg-m1yH9pQH+}7Nd)RMm zV`T<<3S1d48s|OgS@QX~bw%X)n$EGV5hiA@(4U6$c@lY>{rmz0jUOgTuFx&)XTJFa zDtllH3JujHtgKzFqA_KZrYnwwDxg@{@jIEfVuD+D=5xPmVaKU6ep6yMkOh9U2*!29#@}V!W`u7=!-cQrcr_ElEYSA=(3EvPm!Di3wQ*vnPlX@99j}GAP zpbkZPIQ7mFni@OZ$4_hB73_kNmaeC=(mXR$n2Ud(FeO9Qv=d=w?Cbl~$y;@k9%STR zT0SZ!iLWQ-8s`>8d4q-VC_&Q8wYokV!zfRxTYrDGS3GWGVgNq>!CNc4U0@;z4Lsll z{*1Rr66*$U`DAh7_U{oOnN(owQf+>U2`+8XBP3WVC$A_k57K-yGZcI?6g|`KznsT^ zvax$RV%l7w-%dkm(XK{IA7CzU4XCm=Y*p>%r#g1kH!)f4N{>nxYN^*-^O3;*FA}&j zqjl+CW4oW4?=ScQKQK#&F?p|!{6e6Yt_MlgzljL84Twyup`oNHfLS1y(vT<_u=2cl zK8o}hgk1ONUFmtYja)iK%tdC(o3RdZC2hzoo=UZgqV|)X9CZuLyV%lWei9<&^^T@J zNNYI9@}kpb(1_td*H<0{so1F{VwRbI)drqx?ld79uDo)Vp^l@otb>0yeJp3}b)^v+ zkTtjOTWZfqq5;wBUOl%7u6td$qQ4rOK`#aNmjUC!_I!bc378RvnvsV6)7U@9yzoe7 zXwW0p@62}UtmlVbedfAW4mgBG9N-f5N*Tj> zGLWI|T0kepACi82X&VgIK5kP#*Kk}jzVWp5_YXftYqK9*Yi}D@`(}4_))`9ZXm@%| z0FMI*KUOY{MozQbHhDP>OnAHAcs9t;u}nk@foep%3quZa-r%A!PhsvWzBtLI-jg3= z8}F^)(qy{$t%(Y{f?`aGsO~6Ik%Im7_N$J>+9!4dd!sGkqSZt9l4q8If7SB{4B_(C zXFD(TReVFHX5R7V^EMrK2e8wm*`2p82Wv^?e^Z0UcyetWRV}LB5@!(=vdGSE!-y^o zA|O!w!gX?o*AWxkwfQiRV9*@5z&;B45hF9OtIO`hiobP7Z5I*zO8Kou9iTeV^6!g? zuo(r#{2*90b>4rsy1jdT`MgHSvH9}O_N%FXY>nY7^aBZ;Y(%KQ+);7p3|E)-R*iHE zI{%C~F;rX(wxvGQPLGTI9tSNs*)(oGogXGALl=xv%MF^&J&^{rMX|oPST7>*3*#@p zHIw6?Zf?j?@ma{pu|JJ}=^gd%bhjm1M$k2XgI;pF(=ktS==ddKpCBH;UWZ&vPTG;Z zM-r>2hJ?1GM*rb6UjJ+*q6yk3nHsN2)JEu$B0QU_A6GRruX>d^!MSMQPpo!ChG(x=N)e?F`upjW zh{keGEr(B5&SzQmY!&ipbNiE$&0Ti?|f0i?h-eKf2BHc)(CT>M&>9BGPKO+4hta?h| z_t*0Yo2NjmhfWr9!bQ|p)4sf!IpPlbEVQbM`y0=U;O_u0pAe<5w`IzdBQBF(UpMEvCyDsCT2V=1zZcV>GA_)q%aoaz^2J(G>+M;qG@!rs#IbbT+y zM$bDYG5jKUIO_M89Ir3kZ+Wj)dKk@0?DBVY-5J>SwtZvQBCD-W_!nNNCG_+|`)pq< zQF;f7Krri*iF0=T+h(HNM*|u`L^G1#N`CR;v-QGTlXY&ccTp(PA0_|by;0+!1~~eh z-#r1-NW7Cbm}~S~w+LHb9W?ld3HdYZ@XWy7w~_rT$U?r4jjbW9{`Rp=9z_G@VdLaT zO*`RYO!ursHlW=?jBIa|{!DasQS({1v?}|ywoj7?1G22$L)^pX79P1~aTv@QvKAX` zc~)fJn2L0gfowbtMr?J#6~petQlLg#kms%8E?O`HZX(_fl-}FwGpm0s`uMF0p%q8s z;hRGJm)@pdqF8HYnDCOnw6BX9>eTE+A^dKer58BEbqA(Jll z%f<9$xmM$BkGHrAcZ(HN@9K|{AS<@sbHoq1Wwr2Ey7LoJKK2(Nz>tQ`GkulbeeyC- zuQbs!(aFb$jSXTDgoJx?E#LZ}%2DqXxQ9TC%tn~*<&!Pxx@*~(A*Mi5ahR8Ez+**V z^m*XDnv;)Dg4-i@rZQ%xGC@Kgm>lAK4L{&<0|?LTsZJ1ZdcnoY@tq7H{N`xb?~;lK z@6W+!rfUzb#B88#E9h9ll8AMMYL54+e0LXcEF+}sxqf`rD-QV<{s{W%6JnZC87?MM z;1ryHw~_wu^$DM5Qxe$&9GWoP>4vbWd$Gxf@E z4R%pW46(Fvo^!r-xw$j)2QW&t7xVI6*L9e!KFIc!m?SS{^iXJ z7_@HuH$gXXEp)RUhQ!Ym?Ninr5LkRiv&MLQdh3yGL466n>_ z(hP9l0Bay9-4m=o)SE!>MDZSOIAPwty(AIk5D(ZMcUC=FvtUAp)?wt7G@kbMe2u@j zf}ptuc^*4uyL*M(c^R>cyu084H}(^e)5c+p${1jGRiOy8b1BIG3C3bxAD2cn{>aZS zY%bhl@mTFFasLAw4r-AjC3%<^j64*?S89g+W7y-*&MEAb6I6%gs2#(jmIfXuBiGKU zm@K5Ew5?7M);4HyPl0+;l#e4{tJ=iVa5aQ}bH{~Y6r-&On%|<7zy%Y$ zg>Y`_cV34rH_%`ESj_Kt*zw9gR}BndZ&lF)&Q3VK(zoo1RLMr5vs78%eXa$ZoVlv# zB)x-cYeW9V=I?3QSH=`O@I3f`S^xkpT+Zok`}M>`u=MujrfYs8_zXqYHj9;RFfQV@ zpjs6{>KkG14q&h(?$g4YBMfyfFT0sYMx5>N@frEwt`Xo$_7;7&=vyuusPs)NN;GsU zae#SWq7uDV*Ik>X9zGL=jb2;y9gIY77xFPTX}G!j_DR~F=a&?!60=}Xfx77lc|H{t z*Vq`%)_umyMb8Q?lG^)><^biUL6m*s+tHxoXsT#VrJK=aKPf3f zjaac6U}mSs*NBiG1z`dGrh@dNV@Le=;cxUu0Y6_Zx0#Xp|MQAjT$>NrX%l8jiv zgdF?pZPNiM^AYBM0K8l@---ttYupt#ibsonL@?`$7a%rs@nrH6fq| z1i%;cu-$97v<{tq}Aq8%m!Dj3%Qt6gIi(k9y>m>ORl_z6SL$Aw9DP-(|a4*)`@ zg0|3ttgPb9gP#Lp-4{X&@P6^}iFKl}<5I<8GFEzTF=PqFqh)UGSh!?^Tga3pZ?Q;M z=zp4dQ98lBe{Yl2{Qg5IM5rdk!*!wm4?`b&gK29XCL%4~4*U$$`I1h#9YdyC%f6G(}X$RE#0AqhUL1Dw#U)I(_)yhtU-&QBJoJ zDw!udpfdp$|Ex zhmr`nge0v!0^Q&a*A*S&K~${dL>_UBYdB9$ScpP9+qnu!Xmj@>L?Ly$o zA~Mv01Dmv%ei5sOp|Z`LGY7GFQ4dvmmv2>r3hHWULvLx$0uwA) zK951fo?E>Rc|=6qhBKQfnBK_Wt6QG6AH#OdtGjsN>fzzW(7jmZ;27lL`SABLLT2BP zwPlIK_LuDqBYFbqz(B(B#+&7QCz6&)>rjg5*DtIgwdc>-(Zflm2ooxRzyPxy_NwNs zb=D7aMg4z2*EJDGwG=DdANt}Ae-HKhs=S3Ic6_ad2yTHF_K%Bj5Je7wrbg4zK{r{= zEJ$@t7WOd_p#kIluVy%j=b0*Z!USQ7b!?+d_e6zKo4w4bK;~`A(9AM?EFh&5IwJyq zOg>qJ1)%ts@2fyH>#=z{1f3mUcLlKJQmWv_;3th829-E`iF8*GMW)p3;#WgeSL{)5 zOIc7a3NyKv%=-ra0@t^l7XYSs#1X{`dt;lG<vf%)povQ|tsQp}SH zXJD~9HjV3go!^)I@q_bfHQf>Z#V%&S+n}<|K^_1;y=hum1hyUX9}UQ%)T|#YoRPa| zr+@aPKJd&Koqw%NlA!cIK%x2OpsPGnE%fs6K=vWsajZxh_23+-sp+~q{WBT*b(s=v zLUap(wc&iH4O<=5x7D2v<)Y=R2l3!Fyk2XZ@zXD?Qop}kls3+hren97$>HeUTBC)C4m=yj3Ggqwi&ymVLH4v7-8dHv zw#H1M-!*dT{Jc zjP$VlwNKfg2~%Xjm&-3DOn7gK3&SN?D$j#r1TP-&N~3WJa$)if?xO`t)t&aDUsIw3 zgD|PQT{iyY1=MbF_B9bZ5)dbzGZX8h_417zU{j^SuYauF=)OJ)xkwCTGO#le`bQ`D6Cq2e84 zGy`H1rGgw72?`%sllI4GFIRmT1OV>&ky|$)ZuEmMCLnh0Ljfd(Zq%-w8tt-{4eBkS z($tAM{WuIH%Op}ESbd6H8Ph}nWYSx5GRx%sN=Mp`ubS`^M#QTYUvbIuD)BtwdAJ|_ zNYa`tx;e^;-+24dgBq=Rdf{T0pH{)Nq`_Kj?;w3LxMXoX>6`RaW+{&|!Y1i!V-qIpT=}#=Zne z!nqq+TW;)gxxlF=kSq!{_`?-`@9rv{o|h#e31PDd(Dj_&I4(RU@Wlxq4N6R`VFe}h z2R#Uwx{Elqz{;GYf}>6>_lFw#4(Xt3I@|;dki7ekJmYLpxQLZ%4*sSfxjPh!`9^jD z4j*q5EhZ-bL5xp#o$^|BzX#Dn2Z5DR;tt+zV!w?vb(j!W^TP3&D>Yf}U!z}RE9#It zEam5``a;a!`e44;xbyewqko#shccEIj9#R)a>5Q3KuQ$X9KIfim3EwTa#a$%(`Q%W09>cC=LL+^*GG^t4jclN8|7!wIXslTmu{M_WI|+I{>P5o0Mss0@Uz_ijB~@5V4&{<{tVGD~&K zfi-L~eQzq;xfBkLD9Q2;yK8I5GqS2XHTJ&-S#{g&dsG8hSki^?RFbh1aX9sARv&-| zWmMJ}*C2||*H<_8gfq$3r5nmHFnribznsm@3Lrsb=TXqrogMY?8q+m)W^KK16O;mO z60?)peBobI)4dw`;^Ix|e^OWyZ5$NsH55LutS2Do#znXpd84)uJW(yHJFjgW%^>N1 zby1Ex0%zKNHaW`cc89i8GzvZN9-Pv#_)SetPLe96sk$ezTHTBo9CyA_?xK>O>8Rwf zt>D43m{0jkbd8j-su#P-)7>!U{eGEY?#0`y|CVg}?*`Db>F8GaFo#i5f zE!FaMH(WRb%0beFN%_N~TuxRI(63YsYhD-g0~^m@s7P9UeksS1@CW>&{}mY-mpQzg zeA~oe<`?Hrxcb->+m-85%aMr;4^fV=y=@^mnKA#lW8FOc8XVh$h^y(V8D@EYo|ogz z7frHy_vnLs_+fKXoNeQ8d8l+YJ2&>TQBHtP=fY1jKu%8BuMd;0Ei>5wWB|;qxBs15 ziZbYzRD8E5%Px=w-}a98nJ6xip~HB#_oN4oohQP!{by9rgI@1dI(mAra$4wDXzYUwwO(ZE<4({o7AK+`eO37{D-q8Oi@Uw(19 zYdz8+tqUdT1n}tNRP}eaCS02O;I1Vw-#31q=~wQ1Eq-Cm05QnvM_C=*kB7;N1T(7U z0NphY4qdD6r`N9F?l-(&>QlWh?X-ky6pR^ZhV=+r2E|+oUXK~zj*-O;i@?g(h9gs} zjs9Ql{~CQ?Pw4J*&?Y-BQ}2EF$sj zGEOgZ_7AlVr07bnY^YY&qCiVRrXoSW<;br`i;}UV=AV+&-I(Izw#&L0B_$P`7kCqG zb=*FG`-I-hpGLePR#@D}AAuC4#YTC^aB6P9(todhG9${FCL z)>K02cgz6F$fCQxgNc~hNQ&I-pGxv#i6}HOayUnpA;`TYlJJnkGND;)I5;(A_|O#0 zO9mA5YBYvyqAQO{= z_n(_U&(FOBj)C9?JceDnvAv_f&LpZ$QXQ1k7;sIDNBy&;vZ$J8jD#(1~ zJ#dN#Mic7^Omx`=WHZP>hLM{sK7TCrT~up?9@raw>u3fj$Xf2fTjn+mkF7nN!RH<9 zm|xejuE%kAE;|1`!ri*z;YM#Fj_h+hma>9SBec6ExeToXKpmnchU-g zV`w(Kw@`bSX{E@$s!4h231iZLz^Z%-cgtjLasaT~@$2xzer(Xx1m`X2UxIda@~2;VlFslhce@U0n^0*5aeJ=pnw$#?y3@g} zMKVA{Fm$~KEAd_7w7BVzZ~O)l%>6%70(Z9pfwZi;LMiyk7X%00em=6ajm7=9k6g2H z^aHA#aB+N0ohw?0jTIhsAT-bjbCIV1Bb7V{Ya4o6)pW(dh`W=Ln=Y?_08lLxs&I#r z*XxMu2|pw+kMN@J16q!Pq*^)w0B%#*^#OdWisRwgDZLx|4<7ROZfSA)`0ZXgU4u8q z3;+U!RaJdQbJAVY-{|l`$3g^dE`7r@CxN@FhsBjsXFzNm9~$rb4aXPknhLIiNxh+C z_DE|qSU$9ej$XrP>z@&ms|&=#FerBBU|LF{(~N0NHG&q6OY$FN_an=mB-mIvIBT%E z-8w#_QC4GMso{U+sBbItHRJ7jCf{7xU#2?ce?%PIc((STVoPu3D*G<_nO|Uf@N59_ z7gw~cKm~%teT)?;YDOl_^&Kw323K8X{^M@?0_LNK;c6BaPU5hD)IIlqC`}FZ(~AIr z$g*$EW^x)b>G&upasMx2z`+0fzO;8BA-8ls!~hJ0;SqW)<%Y=BpG!=68w;S5v!i|AZ+9c-UhhQ8!~w!W z?Ojg1qJ;aH z57^%S%=dO=p!1q%(H`|jtBEUg<+X6D5YS+1v~6l2uNyY zKY0c()F_DVpTxLg5d8aI*QlW{7N>Uj@DfuNGMk4VdLIeEtqA-HT|ZAth$918%su|X z>Zob;{4B}_+}2MhA(X4YVGqgjWGA;m`gaCGkX3F|nd{$HZ{kRw`4e7WRxFVSi3d6b zv~c_KmAVRX{0H#?6I}6Xmu-T<2{c=?XmGl^9yVz@veb}W_|#OO<7pdF^-SKhdT=Z$ zz|cV%o|u?A+XTLVMChsdT;ZwyqRo@~Q9FoBu#^_;)x(|(0gdW}Bj+xcDxn@4=2Z6n%u zJ&M7meM%QYNG)-AApy~qw`@VFuhu`*IK$kRmo`mZ>xgNpUf96rm)D!ZP~8+$efX8z zMUrXzrtXrUdDLnq5Q&}?%18C;fcqG7^Dg@a_wb`Z^)uVv1) zM4c-Pu0~g!k_0_jDm9VgQVMhQHo*mHT$djzN?->OBr5t#$MQaPH+OCbIXE?6GTD(@ zR#S@83#NrBkJ6Z|f-CbY+wi;8eX70zBd8f*a+H^j-M7}EgD(GgPLZSQzm z@TG&TB_njSnHQI%;;YTdlJ{l^HIRD2`bbzz%E@qZ=yWHmv`t%$E$e>~O$+tN@2~hO^!=^F$^UTWrask_zX2b z@{*&qx8Fqrv)U$o#BDvR)jI<|W4-CZYk+Hx_Sc>J^u;TF)8z9oWz2oZ{B0W;X|tLI z3J53wp&An2&$zbl?ei4D+84cJ(#QP?y2|OQaDw+^9z;!5p~m{P0b!Ggx%g8HYKzQ` zD2tx8b%*9IyXEYdH58_BUhRv1M1!l`Tf(3(owqnJt%4hU+1IzBR|nWg<=`6(|7l@C zbGuVOUnn&YHALNcJqCz%hKrdPbVm^~RjQnJvA@q7@reJ=3jGj;)erxFHm_7-npwm$ zC7tCbB8ejA>A40w#=W_rCD2wF6Xv@MJu)goB69Mo#OwP?kAW{@rP>8qmuio837-sH zTfzjWDZ|PDl<0WR+w%192JzC_Q)_5sJ_!lnWCl$c!%nVWTEVe0ADLdB3!}PyY>bYk zd;e?jhIG$VBaB8+ZN8Fi-Gt<_f8OTT3H&oeY38WbZlXHjCSX`z@w&ESO>;0gsL~Xn z;(`5M3}Dmh=TCxYF1ObQl8L&8S1e~V9mOd)=Fl_tZN^9p@yWv zr@O=0L6kC@>gLG}H)4EKMjIv`{d>-g97@A%Bne)$(KZUxx=s(G!TXHfqo1N?x!LTz zO+nLUHa3Cnd~)|Uv`_ol-GykAt1pj@t-_64|}R^9gD22QC$IFJJhmzWnIEyTBLT!J)kdC6@El zo_DA>B`*;`b9*0ivUuEO>g681cmR%4PhA6Oe@=+B#5nnC>07V3nD!hY!8+IN-JY9a z>}x>p>h+B*EO9;W5wf~E;=pZ)eU9p9?S4HW^Lh}Je;2O{S<}M<`J+bs?OlRl4$_rJ z1o+K$BgyjP#}7OnFq*`W4u~6+7hqSJa@ucut0dy96-LorQT5}5q77D!-uhCk=ja?L z@N}!#k?QK3{l;pLSA`#&I2c%%>pH($IB5qMglj_7#7aq9QOJ?JZnHb<_6X2Rk=0}J z(Icoon(7nuG+cLm@{#@^F6_~+P-`F**NBmWUo6a5WoA7+&EAi&Vy=qZ$R)tTU4OL zecL=!7w>_Mx8d6wu4xA7b?qYqbt`N?paN`YECHq)0Cnm)1uuTbbz`4S==cXkjAF733q1p+fY2jv<6)-wt&`b97W8tfzozGpT?zwb5Ao-U}4&_uU?CfIZ0TV zi-2H>ZRzxob~UG}^BE~JF1+Z{-ZWF(q`B8S!kGjY?Bk1aRX>g~#oI)*(k|#^W*x;Y zFu%B;lgnY;g-TZz_%bW4QwLKc`Am4VfB8V(Hb#mFotc?eRYgPCJjj?{((7)fY=<1t zS$Og-vi+1`H1&&P{~PC<5NxL!i&CWN^|h_;*@&@|RVCCkQ(r!LJtt&}>;w&rlvj&i3=+YQsSsxn@qDqPY9PY_z`o-lLo!uUa9&lnmXrqo)&ET~-4xf` zvsuo~Z>vzErUJ2h$4_o{J3nWJ#gMn%%qMV!Fom&NK8NX1?4U;+ zrxdTB2rZ`kb!f8wgd~oB8?B{+-Nj3gHo6AIf`Obqet_xS_lwcd!ayTccf7NWZ)Y8w zZOi1@R}KUuh+EBK8P+vBL*B0wJ@Xz;(;2zc=omu}3fN%-|CC}WLSj$@E0?N4k%G&6 zhSUw1ur=DUQ1N+iDGk|4NzeR@Y5`#7$@4T63BDC0Y}qZYB~RgbWJ0kvi@DviM0vCS zM~U4VD1ww{;!}m0fc#kb?v%~Km*Fq1S5g$gT%pGOUPl{z0#0K&ns5S0Y?v!AGB00` zCG8Q>rr<~Zla9Ol;S^kJ?A@L^1E7L5&aG{=O7=JD{G@7w>T^4z)jlLvr#i3{>zd(@ z1&m!VAW)W=0$z{Jj{glrkiZuGr+c{MD$Bdla)0YG-81l&-8A#(Z&-!SNxZp`E};~4 z3%}(lreCU&1ml7N@9X1Z(Q0V)aJqb@qXxfZp@vKm$qmL8VTn`C{*=aXveIvdE8@$a zLWLzIQ6@9Fj8S;LFALjD)Y?VgwHX7n@tT+rxWrByuHR3}5Ik><7HaSLl0}aGsnr}d z&oHlju8vpzmTLdX$iP#>hjIENHUhq@iGgaq`0XRIj;gE?rGH^4JvyGeJ6!FgytKiZ zsh!LfKe-2~E6!8^We;Vn`fFK+oF3(LoP+LE$ z`-+`yA{T)n+@{subx%Ed-a#1IzTdL z5YSX$#1fx0zrwV0qk6Ft3y4s!Z1?XQpR1k%ojPk;xRIHR5cYTsZ)7fCo*<(iEj<}v z1ew)PvDPG^Eb2PvwSYe>)FGNR~*0EO85QNYuKiYIHtE6+4E~uZsa#dNRRlLejv*bS@+JC;cpf z6mf*^NwJ{AF#Njz*QJP=l0bL}m13S5!`rELAC2Oq(iV2aR_*XOqN?3|7$?hxPL7AtG3|AWl}fbMoh z>ncw$_ujy|N_d-X!7b_Iz|6|nSQe+;Y2b!^`Y4l(dQ9gVlDU4_?hovi-trd;2Eu_9 zYNFf~W|q3cy!71qH)HBHnxC**3K{m1%ot(ET*I0wCob3i7`HS0L9%j~J>k@7;7MH! zHjM&=_0J}qFWZRy^^i^Gt=J#Nz+b9oFTv`tICD6!&LMs=vMiyJd;wA}%7k;mycuiJ<;yz5K@A7G&fIw8I-B>>Ro!6r0Owu?uJtJ10F7 zy<@*y++n2#6?%t>B@94CPyu0WOj8%-$B!uSRKU%TTl|o}NTd~6tgE)wX4H`DKOOR6 zA=iI-B@I%h2~u-y{&xj>n|oGd2DZ$0UH}WtMjbwcQI1u}J5FSq`}@@!DI44<-EZ-F ze8jJlZ1!YiEj`jNm<1&U(&7@>4ii087Ki@dQ!oJ^LQ(Jbm8X%zm~r5s1hBede_w`d zUawIRE^RN`*ZvVF5eJv!BUB-f|9?UQR_>m<=89m2I}?R%y!?w{PgvmfxC36;dweeF zZf@PW+o7N8?-G6}v`z%nsr&m^iw>Y>$ z8>pZyxuucA$ra^(5f>bUTW2|N+xkjGPVH6{vZuS^1WvC$ErB(x#*`6MS|%rnDdzhF zsgNaIi4dU&@6DXPKR=;70HKqUF^fV@mIx?wHSu+*`bxE>Gk$RX7LG2T&Y=Gn&-Lh- z*qR0JeX_DJo9=AY+=Ot$gzAIu(^^gabZw3O+J%&&yi_H>{-+Uo@H?H%A=a`~$XPLn z`-KN<$4OY@0>9FsaLw$N{A!0ur1ssH~!SG9SDPIaU` z!ycq_PWHvMvA-eOEPOrJbfmt%k6+lvffyasA|$7tOQ6TX`Fc5Wkt|Sg@#2p+Z4F*U zi;XjvfDzKj<1?8oZ=Q~dWb%^k(f~US4|zMC2r{q#UA>U0y5ZOYaxdEESbMI3E=fOM z7cuL&NkCc}u}5v|-hnletXydA>tR`}Cv)RkR56Nhmt#mrad;C(hXDa046&;8LRM(+ z{bemQdauL&z@hO}7r+)R_B4zvNRjpE|Ne;L@=EYUt+=0%kn6?QR*&JVZvdFWs>@=s ziMS$bJaJ}F7C9%U$EC7*X;G~FrBx&+tSs8}(cPt&Uo`2I5xI9yl?tf9fUK*l~ zmK0^sDJgYxn=lUeFZcY@IF&LE=H_ULv(=ukEpNki{g*E zUSNr(VQHni8|g;6yIZ=Ej-@1}yF)-4M7m2#Kt-e*q`Uhaf6w!L-uVY+XZFs$=bU@) z{p$KJb+wLJ*SRFT>3I!U;>>wDDCuy+BR!hR^}hE$G!_1RLy+PNMAyuy73{_#ZrYMf zkua(ShisWUaX&TNblndq5on&}cq;6d5l^Q?z@7g8H?{FZLhXU06n*kNb64)S+j1V4 zj#R&4u$XrEjWIc^B-d+M_DFN=e9_OVkq&M%Lwk1EV#0h>|LEEF)kvul z-mT9-ae$jn^oVo~lm>Mo0xeDESNC_LI3;Qnj0ga>`}b(!1g<{d!(*hzjc${O(WHgS zoFhXh6d(VQjFc+HW)M;O=35v;b-Q&*pxy-5aYZrB8U<{w%p@p zlqmv7T$j&RugXwv-YL`IQawW6$bx$f3p*5xL{#{vc9HS`7~N(kp!UC!RYZ&m90e)h zIt2LPx;u1(6)wgdUfp#DA;4wkQD*9RjJp9p>I89PRlKKvPK^}j7ceT^+}Di)`93xB zD2@%LNHMQ=2Fc29$BTjFnxV%^uXc~p-A#*p|2=0Etb#Lw@Z^%T`$^=jX~NPv^nV}q z)j;o}%m=3f;xAOJ&spy!d30KgUcW}t$?lVoRIO|qV%Q2PwVpj0o%!?DC!po|>%M*j zimy$)nS4YdMZk1!J}0oydwP1j-?Z~1#~UZJdR6(6$RAw5Eona>0Yk`b`~uS$LWCK_ zz>unj+5df-jTILv=@ z?f{#__?3{UwtjHT7&}W~cRR<&6CdRC-s$_cA{Qdal+&Z5UotWXD5J2x1>UbD}|;7eH)o39E2tD&^odF?{b~{H-ygc~y3t1Lp7j z!}E0bLHnBwLx7d@g0zk7k^cP|v8699Hs#_XMAMS1iZI+I=}GF_UxLkzjq{WCWK?b_ zYS;3{Ez}tc2jr3@oqK9Fd8!x!I00vMk+<|$=?M(}^PHi|H|>NG@G*rLMepMKE2 zeDXh_$icXJ%Axxzlk+OLJb_q9DCBl_v4n%yz);=O=o@>T6xAolQXX}eIKUR5^=OBO z+|AAJM`UTc7$f%FB92opf%}pJ_svS8L|}uOu8b@O$qp9TuCGIr7rTQbT~s~7jxCbj-$vb>*k10RCfU@HZb?#YEumAA zqybrc75)(3&_8a1wNS5>f&>45F`e9`{B6{Y!#6*h<7Y;th->!<#|oRkbB`sbnb()Q?qC-J1RM>V^$uj< zhjCXlu@WL9hoA^>$nDCH!c4Kd{fOpPEFB%~E>wxA%&f%C-M@?bOHLy94+CFP!r(|^ zNW547#T(2??tAIPDQ<#{kSo@2YasLb1T&&9wf__0;PpeJRUY=ASz4JnpJ#8dZtv0% zhR-xY@z+;K?b}aQ$B;G;dGzA<7!j7=8wuH@ty8=8U$!b;Bd$B_a7^6RBW*D&1g61% zi^QjUi!r#cWkeAm2t0ZejSybYLs&n6Bbjq*SBGgb5Os8j930{%+4{xFi#i(b=!Sq9 zDl>|d8Sf=DnIl&WDX_FsZwv?rEy@5qojmg&7Ls&&jqKAg^4!}01qEn-ywBO}(W`fJ zD>C*5oB3%7fpXTjQX87I$wayQWo}0RpvljQNe(cai*2d_JrjxfkMJNhuu`1;uqh8! zf5GV<05Yj9iFzNaqt9@@J@6vG5(>fIZSPgjc1wN7fH(*ZzXoGFAS^7vY{B(Pp>`mJ z+|YjdGBuFS8{$2w4^E~#dFWKVF}tGtrB6aQ2n$deMgY+R@w>K+`>^d%+8z882p@n| zd3gchlW)>59_#^i9)=@GUrU&&L0KQ|x(_=wU2U^or=Hdf=W}~R>DP@ufFG}ld+MV2 z^x1Qggj^?+fr;DbdFFw4ab%D^_5*sH;iA_nq zT63~7zx2ML<<%wm;Q{^ffgyHyU3`kBncKXKsOj@Xh)Kj9F~V8q>xcdwhK@sGi&+o0JfsE%>hqM+gC9+jGy6(FKi6 z?|^^!7AuX__C@ao^0&QcFWT#CppniNjQn337R3Y_Vu1H%miwZq1se1crrmg%L3}$f zC6k-iAg1I02urm6()WB%XX(@>9AFhxd7alE%d&|T-2C($=EMo~j{<*4FGm!Y#kEgfKSBho{s<3UWIHPz6_Qj_^Q8wi^ak?&{5^Z)MfJC8RSAAIa zh)2Ui_4DP{|0a{}mIOD+etBW9q=NnSg8?(>9amh2%be=vg=&nsEQ6g}N|gAZngV;+ zCTZlS%M%Q#*xpgEqxQI=t;|+7{kjAzwz|N{4?BY&rD4q|lz-@+QhK+j2qvDr`lJ?&4@E5CxH-DiwiG`tvt&rEntw+2&b zzJ6mPR!y6=WI00j&g#790^f2F*E%9UVi~+?CU&UWwkR%w0T33LWw2gcf_t0&8oeX_ zcv#aQ7zgckFZ%rvioXE!M)2ltm1 z!J>vZY7z`kFE?L<@gxI))Z-}8(&49+7&?OiaSaKH52 z6HNqmuZ$zsY~>bkV`7G^)|!{^wH_`LK+SEXBPU{pqNZ=Ne7*H?|Dqvg_1{^Et0Ei zp}+g2a*Oj5e>}lhd_2(-*Xp&kc}k~f+y}U?L;rk)p9`F~Q{COie4f&o2mdT68ZdC6 zBCY{5L}x)HAMG<7R9n1EP2TS`=~*3;0iX`h&ggAZEOldVY6joK!oI3Be^olkb>>n6 zlz7~88kGK)(Mht+Q;t?L46IjxS{JA>g-^u3I`_=WiHrExCR;4y;55mM=jqh>iSBvP zpRKtC0q0A3BnJ=0rmMtl_GcXd9?@zJF^3?|r)xwwY&bP+k`E|ygOF(cqSc4_mzxB{ ztxkzzOpXeXHN$0;@OZsf>!S#0>4<}t;U&5Wrx^SW!DoS;r_vlp(bM)=yjy$_NAlL({&%PI%_3K3`5Udg08Pz@O$w z`Caa6mz4r|fD>lIwA{;Ud_eZCEIRsiW&38@`6&+2BmNiMyh&3C>?X)*p3=PoLP&2v zY{l1{Zc|RfOW49wozov(8R;L|>*__fF(RbnKL+{rpCa~tkMKhKvybQl)QbIBOs0TlylD0 zb3&e(L2^ZcieF*;@#Sn@9^qxZ;48x+m#ZJ9=X<`M!<@zK4b#D2a6IbFC_ao=tkoSJg!mG%*hxnw6tK>lg!YQBUOjvSQ2Y|oA-oHL)GRpcbU>=Hw&dZ+ADN!MZ#2*`H}TN+ zm?UlV^kr%#XGpHOW=~>u!GBmdK|qx^uTt>+Uw{APNN1Mpw-!P05EI8Ucws#hvd3O4 zt5byj(DZsAjuGb&9F+ODL?z!c`N|$vx&tTMY(D#re6P&qw#<+0y4f(788i^$rm~c^ zvii27eUPHi#BDhuQoC-r`Vu&YBRArjxwcM(d!94=tykl%I_%*lO3O`Au2Ysnd2Q4K zI6F1)OihZ9+Bz8bIGhGVOH<2Z-*nS#^m9M2C9}zkq=-U-Urx<|L##*PeJg7HVyVy5 zhm?;+AYz5*D;x;Iut4+jv66R`zicQumU$8RRyJYF5Z6)`*j{aIPcf!UoG36rRYs6^ zaWV(HcZbrp>ESs!qe}8fd^V&juzS@(5moeg*Du?7+6r8>VjVppTTXW!Kljma1YvGa zX=F}U=#T&YxNJsBFi11xJ`g<0U*EjcQ_dJe3vGiRvRjcZ_doObKuJWQr%!sXmX;q)Z;Jm<_&KMd4cBdgGcWMjt4{Iyu6zOh2WEip?yJ_5;#26-eebl~% zn8sA5GRW5syx$ZEsyc<`Frb@TCX3WBC)cU!(=-rh27x_zYlpKnSdZW{t{h$9C+o$T zUByV4JDQ_Pju7`{B(Ra62nRY98f=qJd=pF(HN(X{F?{%{{L}HgKrCacAbgw>A`XdW zE?iz8j61>QRqpO>A>>9)rQ95Vk$=8Ql_*KoV>h`t#Z^Y^zW3z0L$2rQ6^&!W{e*$Q zFT63_+ElqTvev8t9f#FE2X;K*ZF9X$3cX^|sgrM3m3`(QT{-g54xd6;>Ie*+Xf6hc zvWHBeg-e3ZGDAzIF+IbUy=Mg5+_Mh#OsX);e<;XPkhf^)nXTCN9;H8MEXN`99bMya~e+Qx&L zS0Yzs5)n=WT2@54)x79s8;8(<5AuZvc*|@uvg9>Ne9CLfWM~5IT>=FVhZ49gMZ6i3 zACC2im@6tj$Madrdohd%lTuSw^d=>`qD{Kv2^6X7>8Uj|^S7(+dNOts z2D}KHe79Qv8*n@F z$w}MZg**0a_Va*LdUPL{TAWpU5?Om~%9F~2aj(oiGnv7_;-TaG-Bin)8HvynWpQ=A zU(U5Vky7>(#v!dJ{=a#SrR^TQW;wfXNVUa<(5&VTyMt8_@N&f^DN z-n5J{1HE~tr>dN85|rLp`&re4J&Uvu&C4h)#+4n`e?W~Q3-d{xCm3q)#*vwO0xSxd^?U<7clJfg%LNK4l+H8K@v7O3$VAUeh(tGNTfGgFgMp~U zXE=Qq$u9Pd8r;ISwO<_m@L%9E{wM;C5ckN@N zkOo3BDU^DS4R5e>y&8+D=iM^Zdnk~>g`%W0x;*0BBoRm zmEdEExn3EowYH#pD>g0$KH#naNt<{XvulA@jpeLib|1CPokG7#rlD(K7}7`4 zSJJ`PFWWA8J7PRiPYa2@L6-orJbXj$_M`OU5gb;X8s6G7slT+El-it9B@9P1_DR&;iMDZIk{N#_wgL)c1WG?? z=CwW3>D@31&(*!($-CH9X!Zw1jPJw8-H_b;vjUg8s<7UK9BJ`ZLc_ehp7Lq9_;C00 z#aH`HP!+EvC59+j6a{Us6Vd{;rECd(7T&BnvzPgJ85FX>t*i%-#x#m(@TYaGmrt=? zkrjK*tMFK2?fE^kN1!QF%~)JN*W*oa1-}GOF~u7Fso!X6GZN^+;c)+O{@Bw_bzV-r zN>l6L5?)@;Kjm>iYHc@>3Y%u+9c&wsstZg@^B0&sj`7QDf!sJdM41$Gu%|LMuezVJ zlhEoFghcLL6s=R2^xO>9+Cj+mjXV5qqr$_(J$~4$=Wf9Ur22yW^(B-a2M&Y3h%BX)K3SARezYSL13$x{2FkF?}nd&(#J zp@lD@ztA@Ox&859=c{@8l|G@ui3S!j= zsC_(KoicPl)gdUS4iO>y`!MW!c2UEp7{iv%;4U*=TwB)F?0>`R>MGaJDp%jmAc8Fsj`=7OQ}nGaBVM$)7z+-gi24@3 z&>+&#EX5d*GNkJZ{cwakBDgSVjtdj{9x5xj5g77cG5=wA$ysUigD2#JI4Uia5V$J|U$MIS04WX=)5S%icUBEZbib zW@xwHD*0D&U$O}c{#`s^9#h-iRTgIOrK)(5~KlbXLLSV8J z?K(=azZ1OM3y@v;BzZ=;ZxB@4vH)TJY$sIrHp#O?#3r94Hfspk(#+bG(Q4c21Ii71S(K3P_&|1Z$mnJc0hP{vP7fQ_9j(32L2Q7qevNCZ17yo z`x!5YL(`a|9q&Xpph#vMmJhx`XjPeBqj%-;I*jIS5(|1CxXR6-NU0nS06F)!Snb#`O?R&3| z-dI99F8xrUoG&bTk{j)mmB(CmTs*hc2}dH(J9twXV*@&=uGI37U5Act9=d?73eI{9 z;_w8Yt)|pOR|Na_I?);|aW|B7;HVE-S3fOu+J2sjK%#SCou#xiW#YQ!1X#W5-PjSh ztCMA^MJuNCHb!JnOeosCm#d@pi?SqGA7u!(~KYw#O}Pfl)XUGI^r`T z;?!8aIwBu;s?;CspYVrk$;wkuA4NlTa+3bq_{Iz!&RjSB1mz180*0H@A!>|@!N;s7 zGuYa3dd!42zJDZA^C~A*B0RrH>E|~vRq~N!Gf4D7`0n)H4P!>UrOC-|I_IxH3x^9D z>Q5f}Vh{T@(H2Q5iOl1=Sma5GiLF6f=Xej1^|v2m)KC)Rn4@GN{gf21HL%eWU*U_& z$t~S3spP{$qDLwHy6hHqVISS+1%HZSDTIVUML&Q4G)Ne-srkJ5ci)N%hIww)iSwg6vM#97l_h>H0WbNq2NQ~)yM*+9{Lqx@WBI-zW)GjWXPs`u>;`+CS#*eLW`v3}D61Gb?@Wz)L8&_(Bo^ zG7T!GB=-IzaOwjye8rUh1vMz3sN{zO`vGsvPF+YOd6I)YJyC^vRinSsY*tT}UDOji zA|*Jc|9O_@4;j~q6vdj&ks<>uD^)^4Ziy#AwA+{=yZ6t~wZt2kspwDSr}#3!Uu?X5 za}pr*L)X55063LpNixF1CPSp7V9U2VWL3IJyN2R8in~=hJ=+ zA8eXB+G0#h%zQnQt@kVxKrv^p>ACP27=4>~x%wsAE7DtTo+o%pKR?)nvUd!uAgt3r zGN0W#;hr@BW&1e$JBMAQ1_h2Hq<5uzG@@Lv20sRg@~H+VD7v*VBbl2KQON)Bxn`#J z+IY&;68lyHMe~`KG~h7=)Tb(Tv9|q+ROsRGHC`;<-Nxau_JCQD^qnwL=@Xy9S$=48 z@ig(XU~lp-1h`N$?5OZ8lECa{O(0Drslbn5^l$4x8yMm|oIcfL#Cr;B4MCMpj zE=I05rcMwDy*Mrm7gw`TgOpq=iQVkSo%Dc}EoAMCk^W<`y2Jc@QsJ|qer|Pm{m;VP zYkd9~Wkd=@%!sw3@gJv*k6^HawjMdM^4otQV#F>g^&9N+=8Kf!k~ znTr=WjAy+*N4~5{T623CcIRtn`_(h|5=D;KJ}hE$lERsv`A4Vo=Os#0$T2%Y5FcHm% zP421<*TC(+HgQAeo@9Q%!Oh-x_NH|5^_gw+PlQvxR%4*VP3~H=OFx*S-*e;j#ZA1q z(p$Q@vp!E$t)ivnPt(DwrS^Hdf63iY)SwY_8&#u`3@>-M&JS zsgd|eQlv5SzR;lPvkpv34IADk@cXK*lkfQuK9JvfpE|&+V(+}*@WdNzujXIHAr^yM zX6ttHukK-nhG3WGtn(F~kP=I%Y-=mIgTo;HQCs+6WRyLI&v~3b7J@jFit9@}U9=b^ z`eHN47nO#FF08f@qDL4KKd+t!skvlzZU?%jq=ga- zqq1PYIZeKcy-H7=MZY!61}6QUToe>G4K8%-*(OU0B0oLNfA~N+hCXj+4-fEUkK&5n zJY{@EG`^W71bDAYe~d6%M_mUxfX8Y?6l;_a=Bq1&c*PbkTTE@Lb|8+6Y!&}!S7;>w4r)oleW1l=(0Agv$LsIg|wHGHJjDMT^Xg!z{!yZ_CfqLD?7i( z8rNu&I@C7Ws%>DDBk85cvmMt=!TjtwuH9-||5D6Rc{f~ExZ)2kM&OhiFr zhs7ZLPN5ctv*{@j>gkR0h{`XxtG3cZ3Mbwy^2^et{V08s^IwfrIj^)NEsl>=K(`yv zP$RezeEq91$;^-6B(u{RR>8j*L#1;O>(ZFTTgDe)azuLHle7G>6y)T-Beln)^;wGD zX>~M!#37J3lK(OfwAg|gM8mH1fm?pNI3XMEbwTuY&!a!8wIB+%8cKa)UR<0552Ha> zG(F|D0yY*Ho;63uIaeG3<{nXy@B@t6o+rX~cjKo=ys9ik6VWBgmF9jTt`XS+6e8i)6E_9SE07`In9A@AH9<6M~Hl}H}d0(@;AsAJ8#U+ zSIX-G-TmPO*}bETFSSBBW8X)6)YWE!e6Z_R9*k?vHV(+=WVE+(<@)U?;$Vv9e>+}P zqE@ruRI`jKQc`H^>P6tn_}naZ(*l7^`hv z>nmR&KNtE=3ZDH{JUkP_tC;{088B<0Ez>#qB~D!uxHg`|sor7y6%gh;J4_3rCAR@M zCuuS$H8B&rloO7^kI)tsI%@T}Vd>>gm;U0uA#u{5T-^4B=Z-p?kZx1`)ppN=>=HNA zYZ|GWn|5=JLcPB`G|tm6E)S%-h7qAwl^48dS`M4?>*KCEYb#RO_S)f-uL!@X4L*Oa z-2cLXu1V2dMtdy%(qlJZ_LqwY8`CG*?c$8lMU09vG&NRt#o=QW&RrNJDzU7)`O{?A zYXib#2krQKnt#^{)Rt_mF#%t(X=o7vx*D)5(?P8d2xLW;|C4Ys_=I@QKr@ahADMJE!x)3L*Xannesd~=`D2WWJCM{mGt5V%uxCg#!@AlKO~a9 za#LTZq-4oZJ%7E8*znUnSN&LGEb+KB_?zl*+q2SM~D zoPx!NZATGL?4jKOhfq#V?($pcIi8%H5?9;iR(=_dPaxr{Cd2uWxryFTvfeWqjb-P6 zpa|hJCnK@0i<)P90B!+M2}pQUJ@(v@QHZ=>Qt1ZCOv;iJg0UQP+-21n5(_~Yn2o`I}` zKUR3uBb|~lJou3O>`2MJee`Rl=<8P{&kjwWOQk)0j@o4+32Z>E~UcPYZUSGzsqmll(a@+5ElKrNs<7Ug|~J# zQjhyD{-Q@4TE(#;Kz{~dBEPNKHrHslOVxOSV5FPN(Q`Z%%J(tm#w^JU}J@FDG3Ed}XT z;%Q58`gnVEPv|LAs6RoOx=EA^SyR>Ck?Kj#zDqU=mI zg#*Evr2#bt?kswx#^z!EaE{)tWupgGbsnKB>pwI5`LbE>lz;B_F}-lQ%FY?riQSkm zEHwJmJYdC;i7#2Mtj+@8(IL(OwrcFv0OAiglMjeee*}e^&6)$fQ%D3#_amN6N1o~M13aQ?> z__U@{88fe-ngin)5rB=|eQg+~2DPk%%>pWRI|B0+lVYGW(2Ju^2MhSq@X;cANr*L- z0=BCeq%=afz5;aU33J{ts^~!baV$xcsPcT*E?z8S^tIiQNW4m9KF|oeKfYfAzF=xO z%(j6v<^%mpr=1>jDdY90s6*7L)A#8M-OJ_tcytC~Jr(eyt)X&Jy_@DKJvuqX%jVB@ z7I(gN{*qlP4UGc|mEB479z=eI-gyyyWGeLeTIObP#C$~AWX^c zZ8IlW&y;rL6Uxe=hSpfXlDn(p#_8OkhECs~_E0&!S|0fT{(sRBt{kPnp0HCq3%F)6 z)JsTXf-ui(%7B9XvPm2{}%`C9>US6PJcl8Yh+#EJUoDdNf z)kj;Yuy(d!=W^>sx91#MHeZa89GAE^vY7IkzB|A~DR(WX=H|WbZbz;8Z&~HFJBJv_ zK83APC@SA99?j-hY0QFGWU)aBLpo#pl+w7QVVjbA6^`LbJ)ryJ;(8!iqY2$nsj(qU zeDmRLwfl0z`^wR%vr!QT6>7!ZEBSYS1}_9;D94lr@mkT~@e4#pboH^{IQ=aRVELvp zDjZ!S?Jj_AVf;_j6w3#gMOg`(7VjdL-3yERpa3oBQ08Khx{fX>K{L}oK=f8S%5hBeZnW*&LJ9!zXLIS+<@UA5itb>YwiXfFA z30AM~4g<@m?q7zMxs&a^>9G3ig}t4+Nm1Kvc=ff+d>uc`X+_|kNG~lj?`&+uPsx@s zy@-xq9Hq(FC{wf-e|i6{M05ZY6kvaqf`NoWwxsSv-}ul8?xv9tggDkP-p;=f+!tA; zE5JfQ+`g3pAVPly2SziB4hv@vnN-iljXJ?+y&CwFYX&aj(3#Sz4Af!EUcv(0+`lN- zSV}yIX!(usL;4c34C3_-m1c}plkc5rDBbe@H*mmf90?3RvBh$_`QZ+|Lf*!fKhhN| zp#}$h@9}m}&a*#<)MF>ib|AG2Ui_I8g6Gp2{Q)tQVemH8&$J1x4SeZQL1sV|jc)m~ zQ}+zTH_d)qsLa7HfTL9~%J1fACSAgqYP*OYiLGdEiIaf~gO&;8(EY$4w>6eF;4z?r z<9mLp;gcz!Sp4GieHmP6?Pe2mQ0C2OFDd@p;+uZbY+mi0%EYlhBO;ktOL8!p9b$p7 zT2V!c*v$vH$8%2l7ZljU`#m5r0Dm=FCK7eKpfSZ7f=2ZG*Sb}a=488_^&9xTPodIr z6hu~DZ=N{orGx-IZ79>48deZg9ZIE;b@TysuYRNa{hb$*+!*JhxbwXCq8#(B9vP$^1!1YW`L~r^`DX zS=OjEBZ4p2e-eeRR9iuvx`m5r}4%5pmT-B$3X@gd<|w=HaGvGJrak zf#k#xPTLz9>Sz>vLV&g{D9qX5ZQH-wv{wc+CN#F(@%DK7{xUTfH*laiv;@!(MM^LhqPOLQi zkIf>$SW($Oc=1enHCEPgz>Mm3ea|GmwoEznH@m43S8*nt@ULNII=cx=G#Sz~XmYZ8 zUyMF=j+bN_2ll?`F#|MGmMc(Lcqx1)5+wFYxoitAvyvOneM)HwfKhU5Y0LqOtQEt7 zT0_kfAK+D3UX+KHMTp9NlT7k_wBYrwReq1#E=a0W2=WKlk#;VZkDy6tykbTbZ5Me; zJl|6!9Tw;=nP&l#Z*4^ffj zh(<=^!%kw4CM6_ZV2m1#I^uKn5ob;L7V#a(Y}s#J{iTL3-WVaawhsyoUzFOTd1&RU zqvqm+UwRay!Uv#&6ltAgJK%RwV->w%NH4ujfDo~_bEtj!fObasoX|G~Z6!@wT@vsL zjpuT<$$o*Wwf?1uQfsx5bmzPE!n}tSK{an~66KXLYDiLWWh9msY4o z-q8u|Hk)zcoKF48SuBA&sAAI5)q0&rxH@US=o+X@g7|YJD_g*;G^OO+^gmI6&uxQ z3j5lj2Vu$rwS>~r`{FXr!asu@9V1LWM7NHylZ=8SErmP!200HCP$G+sNDAtiIJd$2 zC3AZ8df(eSj`&4O!f=fxVFdyE5;RJ4k87}s1qSPj|>2}kQ_C0BNpca&Thc<|LM zm3m`bRHrkw0-xtN(9K*DHnzZehKK~*TVuW7o!;W{k2f@^zSuG%y352E zC8dPK>Lc!j!}pk8zrn?HS^dY$iLf|P`h=uww4n+cZ?lFlb0}m6z@~wf64UQy^=+B@ z09{Dcv?1%~C}VxI)nw$~K48z}7&(<K>&C6H=QZIU57M%@>l#$){g1u zqRC@e?{hI8o**#F7m_?(4slKU}Doahzf8N~be6aH5B%?}Yvwn`$Rj{-Ibi+T5ivqkY*{En`j&&x z-e){pKFA^n8`1&D4H}kvmVE_WWR$b#N~>~6Ug74s}{xZc~hX{xa-UQm*L@LJ3U zAAdbJ{iAYrR7FR>ZyXaQ^^f)Ym3j__St1Of(nC*HC^M2%fj}LA#x&nn+xN=0@UXBm zh57&7LFm5!9##-M9U-s((%BIif@>n#UsFhTx+TD}RUigXs4n{LN=)%`G%Y4NrIe3W z@tBNMl&!xM3e|9b2Y2y32m`Oi^x;=nU5^dq5Kjab`&v$%(|Tp6D{E5&&n!>|c-f&X z{&dYZaee((jS%5rb1FQlxdpS8phig!IUsNM(n-`HjIoeMZ#8-x!tD$Y#FNi(J}Jc(Q{}E+;m;)9gbzFPY>6wW8OsUzi!;(0 zE^~maa1%1geq)0|h!KL*@juej@uwH*VK!F4sG&0etIQT8;K5UT^_^ik9^6^77 z^~sH&<^8Agi#d_rwY%#Fn2_OE+T>G}lSxmG0+hz0WXiNk=4_L@kXpDri>9w6;cF3D z0?O{e%SJ`{?@#o2rCyYGbK$G}nRi~lN>+aAlPl2mf!VK{A_xx2mgWxK6B))VC$Cj6LT)etp+ zSq_z=DNj?q-gq9J;7c5bi=d*W90DcPVjhy`%!%<8F~p%8jVW-cZTzM5$Amy$VI#m# z*10MtN6C*|B?lj28aClY=N!WK)w~bQF7zDz^!H(xP(jkp&NkdH9{x@^c=cOMV|LZs zundj|CnQ*E6`r4%o0glGo^&vN<`Hv)_6AGkz!F|K97wru$}JhZCQ?MhmEx(3`?^%T z>D$R>6h@kjB837qrFRNrv7Zo8?qOpMK~s1U%cnfwo>^)5Q`D5%kL8Oc|K|l*4m^G$ zI)$>B_QlS8>OB_iIU&eE`Kn&pgXi-clM)Q>Ex#EC?1l#pZ@@D?4Gf#OG)ou_PsWC+ znym-YEEY|<6|>7tFT(;W?;bkExkR6X&K@8^+a43YS~6nrR)buqGRRkg3>0927o^Z| zDR4n>^*Rt%=fE(sdTqedTyh>bQp!?7*)kwJT}>DGB})vqH^a^#G9OTV1q0+ z(;Jf4kEtSAP{ngZQ?8H{%?~XDhpa!@#A2qldclhrIOVr1xbjMlLKvd2F`)M^d4KO7 zDG4Z1_2sM_Tb;7B zXjuxX$#H#7`dx~GTqiljugjDBsfPL^K9j$PaV~XimCdY?0ivO%Pm%+hghukSM?jb7 zpY6xrF#Lf=Q=IULp=*-=S}%N!zQ9+FC2KCoW=#p@W92NcW{zRySly}-T!jYC-pQ6D zz|i}S%kpkM)S(C^cRR#AYu@bi?p3|FmBqF3zwDJ6T_yCbCb!{amDD<3Th!96y3HI|*L`;pSU zs;3YS@*;{h9o`G&LN%@k$Ut}j>*-NxHMeSbCSR?+)jr-*iDp%@6{CMs^T83^&9fq% zY(_e7c5h!uQ@E4Hc9GoQSAvM21ABBJkn+BrO>J-_J<>0Tz{d`@->-geT)jqZ9i7fh zE5Q8r1ie>K zIo2F+vh(_5nH?o&nRT~H_)zB6c2&iT{d>WB7zIctL$=3zhc$wcrfju`Ti{G?$d3sg zum`o0RL~G(3(3;c72`m2n3IV!c@3OmTndQ7+(Kq$u`xSrUJ_Jl;IyYNXTw1bAp=HWmJ*R;77JN;D_LhrFphZFP-3M74I+ zP@ge`-iCe4uZgYmgqMJ$mO^3riGPA~>TQbm;t0O-Rt#*_!OTN>Xsj4DK~}T?SNA_D z;hXX`IHI6ZpB`J862-!#Dl8RV)zn=^h5_tYa~5dc?a{e37LPUZzL+7AZXG8qxdbZe z13`vtaN1zF4r!ZfBeF-fg4?LrDIrKvo25@FxG)Ql9LvU1$l8ws#>6(V1d)hD?I&5I z^5=sT&al3Y8W1+hO?XFEYRp>n{)K8;ywHTEVzJ*y(T*gGL&2Y%3Zr$CNO14@#>{V^ z-C3|4&L*!?t5pMj2M z`yjKxA>-jh_BpH!!>2g~9Qd#BEs$@My#qV!JM=*oboFD8CqcIe^R?;wdXnMu4Mn&ypRas`r58_czT)+Uhz2q)eeCci?X+CQ3t+6ZDUd8G;ciC+WY7F zi2(Gm>`!{0Y&B2zpI`Dq45+i_l-q~#0DxH%ii@MOm-#&i!p^vR;YBPSbg(Q0`ZTxe7ff@TR&4ALd#?86I0TFds!)L&z@XEZ%}>}N(OEJ5Ygi?4>lbtveVWopWw zO7uQZ$mK3no=a4u&!qCysX$dF6R0}HAgmL(gaUIl)FoSu@l0up=8<<0f-h{9w!0uF ziQL3I^_eLEd^#?~hEXF3J(O8f=3>vGzH>+IBx~+@RR#FRpbxT0@l&m*uyU-kd@kHtHIA=~zy}qq-EJ)dc>A$8o zI$J6>WY>Lt*~n@>6~4~vR^^k%mgHXPuFxBov}9+s*e{Nmt8YscemY-B3|ah{2N$mX z9V?Veq=ioE#72*C6eP?s-9cyGCPgjc!Xh-}U)fKFQFn7BM&W)k`uxnTr1z_TfKSWu zX$RL;436PG@hv^W(XaPa`;?nzTs>?^_{y4-(&m)yb(J)G`*?`!4;rKEC(OEL@-=|+ zcwe-?4mlyWk7HcrD02v8Wet=9VB3~AzrVbXD|DvYy( z{vV{2eiXT2AChb4=AW8LPlLU#l{$}bLS8vAJtm{1W_}7xDHoTta3rL3OhQZP6Yccy z$#zHd5P!>vTHofy_HG3>x| z>iwP%SJ%!ASiF+3i+wjQK}Ziu5HOhrqe}Wte5(|C${@jbW~to2J@}3b^JTQ{9oqB! zV9x4R@X3=gW2f5_j$Gn*pH&NOML^7fHp@jX+xEWGiDfDX~?Itw{~MWL_)R$LF`lQFjxl7Zt%JIW~g;!tky$X8{D9i)nMauS^0 zMfWgqgY!QnS{>wL0%wbg+UuM8ryKeU4;mdSihqY&P<`KZttC1eom}`#WZ)%Rvo&@e z$}MY30RIC?LWe z;mnuxSr--gdQDVe{~^HKo2ulQM@zE=GXurnK+{`CA!us&-(2>>JKvP~*P`&vYB|&4v(5Zv8@TX47F?(Xg`!QDN$y9bxx?hxGF3BIsr zpZBX%#b1`1Wu~Y5zOU}txv|7|kCr6j;e*8vBgZ3;ln6G zrYh!O1$S2&KUEopH8dudv8ikpf8&Qt7#Rs6M%!57c*-urcWw%hmmS+PFq4&9>st6 z0?ik43{DxHR%ULVu9_miB#DT{~^Xy%E#lExvcMn-GZ3psvA^_6sr&E$8yzpQR)u~&s-+*|p)qaf;Dx@;3DKu7vI-QNW z26Ignb|Jc4V!T9_(384ccoZZfiwn6ED6wd){tRMR)9d~z@ht{ z;n;m?^2$XR&6S|ip!m>=U$R5FTW9WkU@KIpw;~Ua_~vDvpgRBE^E(TL+botalJzrc zokW`DTKL4`{vBROH5ql1RMC@A28#>3Lp@w1zn2RYvkG(>JfL#?)Z#v&Y^P@R8L*;%E6NIFF{O930xO*%{#Qdwko$y%DuY6 z1fabOTpQ@)e!sm$_bD1RW!>FAC|l}8|0ZMN-aGbRb5vw#hr|3RI|q!hFEy>cs`JqV zl$-2qM6#ZM_o(H{{ae_Sn@W^r{o{bR{35)Ay>w~te=Gxq{mGs1|l2P#(5K@ zY_Lt->&!7Cb+ZxQ$)wDH9kUJ->CT1em$1PT(=@yR(q^0JpMd(+V?}fvS+)=PRODC2 zjg_ug@uf%NEUP()q_yS0pib0N$s5qN(4T@+4+OWo_y`aZqq z+y7maV0VIpPTuwRw_61+y(2`TpMmI*j3q3+EEg#WV~AhXbUQ*rtxtgqz2QV8S3_4;a-=U10-*9y3IQ9thE39hh?^AO4;2g%-E? za>0T;`GuPml&jf;MS37OF8mBi2>!Fj?j^AD1^@L^ykF#WwEYLk=%FS^7N8?jv*e+M z^-1k3@#XvTO(PN8V?f%&J1f`S+SAlPM}G#+lciiQ67ConI60h&7LU(@r_VvpgJw~} zr_$EVN(&3F6#+O1!aJE4+F$C97-h*%V7?KpTnw*SPO}2UaOGsT_#0_8#c#xp%S|sj zDpcIM>~zUyn2)%TFF1d-09&_Ubx>^S{;C%u1#3t9I1|rXL86HG3&cTo&x4J<_4G^Dk|9estDXH!9N9y`6jC47%6@Op3KBKj<&LNi7bfbp2{x9gF0W9 zIOViY+CGbLvv(u`k*8lz+(1H-iSpMds~Im?`-1M76{r6UlL4FH&I~>QHKXm>C3VvD zh;>8&hK6kqaW(zAJ#F;!Gqf?a3AqFP-ep0KPs;mq1wAa1hKFq~ z*{Yx>Yk(4%F#B6j!A)oLNX)BMobG%U){FX~qMI(L*L_Q0fR4BQY z$rUVBeCsu)7X3asw8pk#m&&-_3`h8^^`s zYRBOnawWhfoXrIGn9z}bOmL!9Yi@ZDUX>|VFAfaJD>G9A@{eBWGk2s2uWDD&u}nw3 z+~$6@^r4mej-0`^zPSBG_=g_%K|!|Pna1y2;I2L1diF<9_p7AA$ z`Ya_Cq=V(0_nqfUz6=Q4W_pmf{*Sh>9%=FM@K*)F*=KKe>-)Zr2St*^F6jO|UAuh> zu(PT~r>;wH9P7{r-y8=AMZ*V9f9%p4;X#*4tng@8=4vsK zI{W{h3nl&s5s|8xyQ8!FYtJV_jZz3co&&aSl?zPdDtn;1hK$k{bjV?d4jW5_Z93b~ z{I<y-AgCb-(6w!RawR64&)l7sogk4V|k)#Qi-7U^JBUsk6-#5 zGLEHCrd|Ra1Wwef+U9E^hI`IYL;5T{boR!QaoM=6FWl+_W^1an+epzh6|P&JPF*um zS~=(8@bG6K}0$r4my;FeCWpo12VWC zeot?j5IxF zb{jy}d;VLSW(`)%DO!YCCyG|gDB3EUdo(z!MRn`Ce00btDmJ_UE?*dzj%1It^$@p# z4A81e?tBnJAT;oqdO!}S|K|dGsX_Foi)AYy{xJ$bNN*}5AP2aHK(b+j)R-A!>Y45A)mDwGnqOg! z@a*mqRO&t#Q6?sQ6sq0f$neg;f+JVeAbq5o`BQHQW^?HO92in;N^mC{1v0HucCnTY zDYqhEg}|*qSQQ?fq!E&mI%g)Q#)>10qi4sOa^@8jb^I3d6-E)284E#}e@I4*RM!OK zDbXiapRE63_a`^qeS2UUljIEfM2Xp@{x5Ukn^npS) zs$`Vk4mDE}r7GGeor6)KCd|GuHK;^ zEyz6!<>3T>8K9xZ@VvjpQ1;GBg;QV0ix!K_U(x7ek$%m;YK%TKXk5L{KYF>am3#UU zp-??fnZFHL*k9J)JlkA;B{aR4y-_B*@A7uTZ}9 zy>)~q+*oVzcz)0Yi3aay2xYGE7yQS*I^n}Z2zH8r$DoZ`g(LXAi;qrnzZnI~fw#n; zU`B}a#D*woF#Ai%!@#=JaMivfYPBVf(11t(EgDdRh?xHq91KLYDWhuY^NwC^vr_lH zTnfqPM@A?CF{@KgmzD&LpY}QgqbWkRi3x==|TZf)}$ADW&{{p76v*7bgKM7Hhn2Y4T(h|z<|Eb9I%1rZo6xM)%G z8}|$V!3giLy4%aU4LKdVWz!&Q4OPTR6zja>#M$v%KkuLw*sC>wE6+fI6z&P-)%7Pbqao{G$+kHodHdb!;P^Po8a&GK3KvQi(pq{}A7c#= z5@csOG!&4%wKcRBd;gIDr)8jYdtvB(yG(;WILMwltJ>{Hkp?bwF=xaDVEvvD(6QHR zO~UpQde6u;6IH-WJsQk^F+a29A(mdt@Hin(8dtJH>TK2>BO;!dL8;&#!YBda*5?krq-v95W0M@bd|Z5mXop#x1oU@t8UVIzF5#1R z-H)q|&Jw+bQfV4&O01{P?TzoIx103PzdZ?5Gd}TQZ~v&;$k-ar(7&8n62EjG^l_x9 zfS2F2uq$}a8||kYp9bzA$VKQ&*nRi`-=xiE#mBF|dqLvXz5dOiBwI#Q)TH;n6lmxt zm}(>9!{~KD6HcnRO(12Uh3Pb*w>9d;(wGO``01D!Wa>ru(oHIc*FB7LvSzbF23e$3 z>%u$3Ijh)4j)IB9E#|PgnCI-S&J>T)^GD7JmT496QSJa4P7}Tg#EZ(^_Fyxib#}%F zzC;)vob>tazZ}$Yd$H9Ot!YYT{9M|VpLl(K4(q2f*WxcbK>Iu;@cYH}yM?d#_e~@k8uaGyjhuEj9Cg>nAoN6BZT$-1Br6@((WUQ|Q_VR!2^#L70Qoy6W zCvGRNY}Y4eO`dN!@cqOc62VnYy($R%RTl*Kg}d*^@0KrHeRu75`Jn5-1k=6FC=cW_ z+b6!M5^P|l;oa_P@7(Q$(A}B_TA!Ect+)ltz{+~+VLtd7msFkZ@9itt0^Q{b5`LJF z0^O7RKYg}3dC0+u^`5xd0(Aa&6-K0jSIl7&eEx zM!KJ}hgE9r$9&;9N-1!k1VlsiJ4wh*ZpEf%dff)pcAI~#{kN*dvy4pqK9dLPD6$Ip5N zHg%vT(s`t0_a9g;sjLTBiVf%0R@W|oC%&AxEnht7MGE+GLG1F?kaO40kW&{83F5JOx2HMW@>pI^(HWnT2w2NF%yXr;*=Hm*!Sq^w8DPydeQgnd8-Lp=zA2&PdKUH(FqKA zSW$k*Ma2MS89oLr>;=fBsw93LyPaWZk;Dj^E|b@W!JCHYc{9SjI2pK64@Lr?w& zsnF$Tn4h;1fm^=~(dXK{s-qU7PcK-qafUx?a5g&7+0wT2NXr+WW=1Ob)9sm*G z2hNh_kXXF@q36M!@y!xc!@*UZVaOsJ^0z=viQ;x86v<6pBkA~E8c5rKvUY^3vJ`)M9bk)1X8_l{G9Sb{#8FFFx|ynU1}xrzEn=ddpbwJI6r{fQozHsEO{gFZ zXvxtp%qYR>-U>h9WcD-L_UYrUnVS}Sl80}6@9)JHgMUWF+`W&~kLw}m-JtxbM||u_ z>{&x0$@0aKl#GP=t5x8jZ137#&YNZ61^4dRSNbqf5#Vusp!dOQGnxDpWbY(ATrW{f zV&P%Kq7v2z)$CnY-^(Y0PAyKr=T$!bz@UW`u&?h$|B9A9lkU1II ziXs4>mQg0ifzlho79c%#%*mMk5)!i`1)d7UgJ80&!ea(<4Z~!4zW2#3*9vI0N5;(M zL|N0x2kQJcmEk?)#4dMt-rv4V7H9ruMKPL>_SPq2{|+l!G&l*6hBzFv+MK0_X4_6h z{b%uHgEp0(M{rsj=Y)zuRdbxbssKs8zl8_A`oFPPhrx|@E+-sr+ks}dXI z99&AJ)9A6^N4sw}wQ>ZMd;UU$xoJ^u zLdutY)7h!-L_Z$(i&kEqg#!N|KS#7GH1{`n=$Z_EBh1^vQ{4X(^xNubw~kAT=fW-6 zM?zkKj z*hLilly1)3X9i#9gwl|6WG_OXUCTLN_JzRf*$+Crvf#egJ|KxzJKxI(=o$AV1C%B7 zFz|~Yq0HEv>_KFQgdF2r6|iM_FNIJPP#-aMg}-#(a2a#zZbC*r_(bDY7!>FL?W8#> z945-zX@(8JPj}NhVK+_HLFiFRG|~Gonl>k+!TpuSl|NO9AHEZcZ52cH$V`05rJK6b zH}or8nX>7R$a7LRfZ>Pl{F3KO9C&Gg9gmC1QQo!Tv%aBWI(tL*Nc!z2u-feQ`zGQ%7O{Mm^s`$(KM2 z`mT9Q2>-kN;|qd8zCvJA)ufEU%1WjHo>(Z;4NnhJOW6A#6ncZko<}bP0WRFYb)ter ziVg&DlF2*j<7J0TJp$c-RXc8(F}vdw$OO6D9I-xC^G*B^aS&1;kWuEZQMKZ77?iIi z(2CRS(oJy}9KuF*HUCYiURh}mMgn5cIAoYHQReS6Pmc?~n`mR#w69K|;?a=(zv{OiBsarEOnr-E_vu?3R(vZ7HiPu0Xp;)uY0a z^;}UzIz7V@a)2YiPCY7cv)S1F--)lI;qr) znI18VLjsyi^4QD-snG0Cue@Tks~J=mg}+cf@u&%Cp#~8K^%sx+Uj7j4Tf}_)U2`_# zjISLf1hBKeINR3Y#Y?<4>>BrFr)xc!S2>@48&E{YGSG=%(zNZ&UsGW(6fK^~$jJdw zJJni4k*x<4M+S`Eg_9}kxY|^lE3pzZM{sW?5c=1{sonU9G;K_kd8s6HDE}s^`8YSt zZhb-CM{_ftnjuVYq#0*pvS&_Y7e@Dq!|PhX;69>N&b%Tb&b=a%u8JPVS1#$#m9rRm zthYW>FV84P7)uuSSG8?9PLfJn)Z3W*sZo7k<6nceVaErlZ!Pm!IDIx)u!A^`jTX_e}{aE3Ej+VgYqoNz6r5GMHTDNC~63C#$EAI*1Ps zb7*9a-xL9q&D;xAKbNm5(diW3IyA_!FFkBppvCq%FGSu^8UtmMe=c4PA3UK)|7?mb zk`DNVVd)!NJFD2lY|vGuy=68P*X;=_M#ik)xUh+1d?XQ^T`fv-;T8Mn+GV~#zF6Kb z(COPfOVWRCMS~rkWC>7qN(If90yCChH|-0M8x*^*r;vxEk+)%JnBicdP}Cf z6CO7)ElDx>@6wIIrYlkM!MVH#OQ@nH9JQ*4-m#>=tNf8>Iu+srzxT5n+<+2%4|ALZ zl8Xr5rofHkmZBNl*M)!BXieR+QW0?F)hE5_`Ih7qre61%Tf`*R{%cNSYzFxx85?qz znz%Y~;UNN8;bgf%T{-oy(NuaFZtpoqAE3;3Fm1IDldHv4Wc;3HYGw8i`)wk@?dl%(9<|r*uPlb zvYh;%^R-DN)q}f?<>9HDl1@!wi&p3c#o`ivS))XBn_+y7;|YJN3j~#E0c+qta`NJ* zS`3_Ntjfv^Yx^h(rnYse8q_EmbMk{x8#ujY&M<5hX^fy7q$N%c*C#(t0DHNjk&3p= zKSx#SSo8HmHu~xd9_@hOGA;tsrBOMkp}vnp1jSUtLkcv9<0Phb21P@jsX|jrUY}zD znn{+ubEoIc#1_PKMH)oe``U;yn5PeurYc5 z*4+1*0yAQW(6skX|sYn4(&DXCaO`lcCpizG^R``ZL|`2mI; z(rJgt_H`FFXD2M zRw1bGEK8;sMa4|da|_o~7Nx>yVrQpo%A_Mw?HBW`vjnc~D;tLT^{x@J;_Wi*yo0^9 z#O0pHJ*17a)`C94nr^=|mVlEJs}}rUpRes>;}dxQ*yWn0X!`D<2o-TbKu;3mt9uwI z9Vktv^|3+ki!Y%%@C~N3bcz|8F4qg@z$Bp24>)B=Ms~S^2G$&tn5;%B96_&VSlO6x zjSLRLbgz#qF+zcWbd4^k>Ynd=KG3A_kR4@&(Mb210?vd9o6W(w5a^pWCY@cMhL!~> zn%kR`uX3C%ZGWA4HV~w8y|qJ7EgAdC>xH|G$w~P)4N$v%v;C!hIJXvlXHCq8|1SI!Ff~c^_xp#9Dnp>RJFaGqj#Vq~osWMHdgpG7Ov%@Uueu!R{9M~1q%*L| z50s^>Y6kJVB_Wq5FMs_7K4h6{HE6Et;tfV)Dlq7#W{by6Ebel@Zo0n9wtRRs*gt8t zBoB}#W|7_AUpPMei>YV#T*2;r9Ud*3b-#7uJi?`~==H-eEQiugFMjlwz;Jnhc5#iv z)|rye(Hi;itfQb9FADmo-RRl-wXu48hqkqG^YJ6U+U#BTX3oOX$d%`PYn2hkI~7Ow zx8q`MECbO?uSa8Nx+Cy50}t6+;Ps$B1&6oN+Rou%u8}>Lv9JHA6Lzp?%_$7VJC?|F zFPPs^F8k2$yu;pZql0B{C*b|Ex+lP4@b@?1VUD3ZFNX{{c1XBIRvTAG#AzI@uyy0u z+PCae1FFdh;*~YbvO?|X8T)+A<4fKK?7^W%|J7pxZ@eqZ1q=yLzcuHo^w0u&S!{#69!uVZJ*LK%jXN`V;qxz z05cxq{E~^fO46+UVe3}JOPAD*=}hc+@qPS^zS^&6y~B*)gSg^3m6p=X7Et_ts6heBSH>K#NG`OfViBm@Kq@W1JNVY!%O3U^?Ctr6*Q1$fj~qK;pbkfd+QJBn(wqLM zj+xK2=Q;@*btHF#?P}n~_Bj8+a=F`O_&Sw1VxVt|RNv%wrtY@ig|P8i%0umHDZz;cbxqRy%L*Y^e6v(|7xig;7p!(ybOR)n~s0`!MO4`V^p2kH<8H9Uy$IS_Y~b(i@C>*8!0zUBS>%HF3qA@r^6T?`yg%@% z!~Uag4{-poR~TSe5S6|{-3xkXuF>s?lp^_!RQ%1E$EX2`PyKOCUh*#dFTc6A#d9GR z@U!EJN4=wKkM&zq%;9*S5-ZmTCpn&!bi>%e<3oAIj@kRQXYx6Bz9!icB!o~#y}|w& zE=%J{VwfXnaVN?4QYf~$N~5e=H7b%n;Fz|2wlA!2F@w^Zc7D^QxMO*w@?N&B&p&aL zcxy1ZgWZ<~LG7&18-uOYH&^d>39xVad{-#&m2LEgeq=HsFEvJn>KFe!2xIWS*J||G zs(gRn+=Iv~LyBZ`>P=nly$*uuxzFJlwz}uWy{mF~LN)O3MASW!%+BJ~%|Y(u@e#wxiCreJ=4bsYG}(;fcR^t^w&hC-0(6X()fPOI*AJ>LI`id>71X~g9KbJm-Wl}$1o zEjpg2=z_aZ1k~9Xt7TcxGHR=Pqt%QsO>Pf*QJaC$Iwi{Srdp~UB3%i5Klbe#)TLla z$;)weY>gIM`zR+v#>}68mt5=mMBS|*eZi-G>V<`Wp>MrbZV{xex8l4)FE`~yX9Qc zQvnN%=2S~?z`VRXzbmP}JyCW0e>)@bbVJD*G2^LWbTkBF*~Bu*4eebG>l@ZqZ6>Y! z2;rjLEg$w(wsrR;p!;Y4fRl2Po`kQeG`lf}FW~Fm<=+x7z(Kz^GP&s2d=7qGxP)uj zW1a>Xrs`;@BW8)SO-VzAsZE$nx0Qcw0z^B}Yd$LBYZeXR4^7H&sSC&a_Cv7_NF_~Ff>s7?&Uh`5!*2#;~^=@cOVx%HaT2c02@2o z7zZ9Yg?uUHk$HMGdtPiS5IaD2g)H*B;R4 zcS{zv(UsF8zY#6QOxNad_M;&QaSxA)T>hIsJ7=R7?Iy1JFqHT?8!szA0{#U0J-U`W zi|nuE871&+y`$aijaBBANZANkSX!`Iu2X^++O)7Zr-$|T1YEnd@>;vLscP zyR;>$YFGm&$=HWSCTvGWQ}H{iscPQ19uYAX)p_Y$1j&?*2UnqL8mspQfxZIP$&54M z7w7x@LjEB!%ijpl#T@u8~W|;qVkHa2Co{9#dw)pb?Q$rxdB_dAaAJ|9$84 z-trwdlOWU-c9t@F5F;LJSZRB>mW2pd*=&m37j+dSaQM8eq`R+2p`H!zGbMp}Td9oZXuVLuzj7uoqd7MX)Q~6Z; z4-83RkJBot@+c97R7G03`Do^)qWPTF5d<(6!9cwVd!=8+?;U&sY@;(jX~(d@=?p>K zrTqWpGVhp{!12O{Vpk0sWI@7CzHFVHJ0{8+;! zj@QnhFSm6PhqdjuW94_5^uMmB(1E}U0<9~>nP2tCyN%5?dJA2RdWn{Yp9;1`eSIA_ z(y;)&#-P#%3)J}E>UpV8rQ2U|8{P8G9ps4(WogyKue6Q|q4Ygw3^m~U;kb52!sv;% zBL}z~!_)T%_el8B96Hl(G{3{pVu&RK-tUQQl@A{qffp0~kZEo*Qxhg^G9UTh5}UU| zkz+~tgB31rjt|g&$gZ#PdlluD|JqRm2Mo<~{I!mo)5H^RHu$hZp0KkTsZr*o z^MSSwtx`ne;J+*>QOca%#uZqWPChy9Ud13Yw*-FGJlh7^XdIXY&K@#{A1sQN>2ysZ zbj!L$<7)<-Ht7AA2DSnZIezr~&RgMv17}ft{qu`8@$g)a?^{h%^`HM-Qd#@_r&R>~ zK-7r$u`>R>40vW6b)i7>3+8SElK;ZybUX7!%Hh+?l37v2NqcW8dV&v;=T>hv9M`iv zd(Cg!MPf3pvL6eS@`gS~(@@2d0KRp8uj5i~3fqFQQR2<1^tkGG0c8F_x}jz72|hDV z{r&!V?%yh_(yG;ItJ^*i?_4|Ui^}RzCfJmb8ov#E%eRh>vot;E50vWHl) z{Z+YY`Aci%xiilKj|c1avYNm6aA(RI>vaw8+W3B`Q6}(nY~1A&xInD17qxsdZAj)lHDWk-uc<=*msu)#n{~ImSc^E(QgT79 z!iYu6I6G2m+8jldO9{9dGR_s2N$O9lW<&Ljm2TxTtBEHyWh74-u}#J~{;wJeC#m$> zynxnD_qKoL$7quLQ})Q<)AKa*$be2^ZE&8tH&8TvOo@$rH;%UTr=1u?$&fLnP}T2e z9KdWCaEYVKsSz?T=l-p%v+#@pmnGK>@m5-_w!89%tf7F-NYd)Tu-A$!42KH$;!2FhsdF>5 zb5^eYMgoxmbvwHBqG-nFjT4dqMWMF4vb?r~S#mJH~6yKSChZQR5jwLXG zOw>x?aqztjg!6UmXRJ`}*#QM>;j-;c){{2NvS zaNIi+8G;|uX7-6*`?K{=uU`|mJwh6McP^mGF=t3V`t=3g`tuNMV=L1N9e)Z6dUXrv z=obYq|9=*s{fYw3Za?&SbH$OeTPM@_@1V8cgIq!qk+QJ&UaS6Z%o-%(<@K}-;ps=8 ztGqz3Jx<7^$K4dPoj)|-GdU$qncJB+LK&uL#v5Qb&W;jD0vB3nwZ)-KabL?45WOsS z{3QFyyH2%!+1SX}D_`jgRuhQh>Utu!zi(YU>vv*S)3o{C5S*frLGQ}t`}~Zvb@-|z z-ugFlTFCEGq;0b0&;D0g8QYN-(#T8U3{1?25r!Zs;_aqJ!+VxC4VHZZL!g=)5V#k%3a<}G zaQzWd$IN3$=lbvW(6F3rT%YZD-=%!8H+xHsb{SZ{8b}IM=GRw~9#WTcbGBIz$e%iM z(N;zz2IJI+R+U(JIEW9!&<99m3JYwO+0^*NhSg4WpTRKqf%hf0BA5}MRcG|Zsq3unUHuWiWl=lX)oLr({(r*;9o^K zZzl1#V(*lGTS~$@aeVR2%gP$~(R=58KV1e9=watfma{@nvr?-8$BCj)`~x7{h|)9* zFPx_D+>_eg8N=x*R;xvbNQYsm49V(m_Dcj?qHVKR<8{U;a@7MZm&3Dj^K#Qu&AF<% zNt;Jg2J{6+qEsP{{YwUX1l1tfZ~I3gs}`NuzfhhP(;d8aQQ{bSW0yozTN0AGnf3pZ8gQ?T<0_SGqXWP%!ibn(&Omrivuva^sc0wf^EB%i3+$GOG zf=Y<8WviDlu^hOqaC0QfZ>AGo0L8p6aZSw|=n@}64Ly}2?P$hVyKZ;y!HYk}@E%o* zgY|(VhTSz&Fk+qH>P7c&9|eBwavQeNLS{1?`^%iaC%7#fx}u^co~EX=K+av*m;;e} zYTNte=Yr#K*z0CTKu5G$O#PnqgiKw1h<+m?`WePv^q%B@rULV6S?lB*_H>eYMK_@- zWwYx~S~}|)_C~t_LURLHKCFOV@Uy&?RpqNzT@@8@2`uKr`@Es;Dc4)VKH`-hx0TVq z`#Qd>aC|5MqM4$0_EMu#ymqgp=B--cX_I)k%CSE-f3hWUEnw23jW;Wx= z1(5BrUVe9CX3h&NneVBG08abo?4wG5`nfA{Z9an@N#0_EE>Wn4 z!|b$ru!FdALf0>h{`45mZB|W*$!N%yx?!0X0l*Pk?!;QVLtM&v?>3!qOd3~<&v3NF z*(7(%?=^ZVjGp(pp*WBN2S3O3!R`{T@rQ3`iPoQF?{(TFIw%wrwj*3{5A(RW=u%s< zIZq&+0Qs^K2mX=v>SmGYjGIEPJ@uqf`(!R3gLAJ6@v=K5yO`08d~nuc*l)2w?eK7m zsE-?1-axvaEE3RViGvm75lyRBD6uw%tlcm4e4>yW_veM2puh>;7G9Hp2*;?-NZ zbpfaP1AHSe;7sEuR}3z|G^@pjA9N<#Y@xqZ1mXs6J$kQx1`#S~<4DY1?2i{a;QcFD zjNcU7ZuCIN!U%VMzZUbyq>Q?q$aybP*7vM4jNvNsD4a+54xOoMH<1Y+VRT<|hOuDf zBzKYg+Q@Nt+?JHDdoIl)rUP2_^x7W}&uP3=_AI$9f|)#3Se5cu*(QK!a|>W3swrL0 z&JD%ZW|50#!p6;vSc)%AY9ya@`PUn@^7C2{2^!MPoem{O$X6!;-|AfO`ud3DyUemV zzBPEGQ8D1m96gYL0NPm}`Gmi}e>2f7PgoYo{?4S~SwD>5m)`Czq&JYsXDsi)Z|3m~q zQD}EB<)AW4T~Vd#{nREl$gw6&rjCmIn=3TlzghD6YB*%vc6Y8F3SWjZwtQ=AwN*33 zi;0n@AW^0pXUz#d=b1K*ib(BKt4%hQ@pM>j@>vxvh0P3ONv1^3NuLx^*ZwF* zpSfpZof&-Y9;{pkOh^`}(!z&2j2dZ%*3G=q#%83$%l1Ekdcm*koHe?Ime=xEk@Rsf z@`{LQh9>pIKqYp!Az`w`m-^O$q=Gew+UN`FWPq-r@l z-ok->YPA9;+%}3zz_*{HIpmP4(#9N#~*_bo@((Bd3?i(*m3iZ0E?%VD0w_h z$o_#8%f`x>FDU3>Z>W?t&`L%7wWBOD$tt1DVyi-{(Q7+V&`~*$kGu7+7Zz;qu;7!~5=CiO|I(jMvqbShQ(I*1)=XV)Qc|<<@;~tOSe&N0P*u4!I~(q}??Y)sxR<-ZZ_-UzfO{(rSvQ*I@Cx zN`(F-6$?9!t27vY@f|r#y-rNmNY@8w@~ri$5Asl5O{Ni*#MOg`Wlk54CcWxl0af3B zj^Ge3<{%|v2D)+b1sj7}V=jJg^`#m07%;(&!|Vr7_YR^4=%lmIoSb(*-oY;rYEsn5?s zp>On8l!>aUbEObnO?`4{DU|HHB&3D`>Z6hfu>(9LwywAa^L(RIIu~<_NczB0GMx~O za)3enhLj{exNw$ml_-s}S`!f`sbmmv!G# zkgt3Esf0jR57Nd_+}navVCkEq;)bN^8(boZbBO2wI+x{W(79F|mrLCvb-3^Zhaud7 zvMgKEk8~JV$}4_IC9I&;vec2~F9cyNgYR55`)Ne7M12{amzImQlgTRQ8*LXvz@&Yz z=j~oZkvS;YwJ>IpxNe*rD4CF&n#`1MYjhS|<`g#KB@NG0< zlz=~EV-r)+_*dVLb$Nb~o-s{#2w$mDivT(|4frVNVquO8>od-iVS9L6&p+?I^61Gc zpKml{!tosE1h3B#CDkN}TK?wEs|`CWErmICq_*Wez}Q@P7(S9R-Smf=7b`c#yGdgxk-wviDMu>UPYaQm3DeR`d>MYc2J5no*QLyXwAEZ0CZCE#_e=D>*JTdo#-Zffq@V&GhvE#r` za?&btN5=^IE7r1i5BFQ6oRx>x`WaGv8DkF|5)JEA7e^y=c4F_vwN2G@dX<8*5KbHD0LbzpwU5S{V1S{QC!S74i+b64q|8V_h6OGsC>SS-*rcIX+`D-SjFG=&^M#0la3}aQ5xF zT=V^jX8#wxmWE?}Y=X6dP;LiB0f71?>%6V=WA#z{r*W^t?>$uv)Ky7Mci5#Hx5Iqa z9Xpfh2?4S^mtPYPo!(1NGe#qEUwMBjpG%8y~Du=g{yBz0(v(EU$MLK@U4lUi7}gz zYsbrWv(EbW%{hPZDV{pDbdBk80EZBGl+MU6X;g4km*1R03$awmIdCUCXZMi{F`Xc)CWXhLbJXZ<%n6S7GamFb+@ z7OS=E!*@DlS9I@0PaKnJ-sUV-(FM@z(;L4MNl=s)JWt|RK9;Nv@3!)e2nF55xvd~U z>UDtN3JNSWJD%%XVy?~3c*iAXHcrwuNmNN`>Hfp3)4OkRpS@|-N$lz&WoV*^P@iBp zl(u$Cqrobfl408T&-l7tB4}V&F_>9mZ~7Hk?{|iD!zviCq*s33zK;Go#$GnJK&pzt znFP2!b%OQ0q6f986N@;h5ByWS#$lQS!W^Yr~wyIWdt@-VSelR7z%K~bB;kU2hx zlvof5P8fk`Uc;hPJP}`AvphW^XP$$ijYgvDu&vhidBRfntOEU>1dexnPRyT&^_Hi! z5_IsD(W}u`8PB^%K2AM+JfCOy_BzcJugY5|=v7X>UT)D|UrY3TwbhjFQ3pjHfr&CT zc#LNU{iz*NN)Qjvu|7YT0sQy4MHK27=hZF@QwwuNw1`T`r<0s8;dyh1!)O051T8Jl z&0T_?#vf;;^Pi4Gr|Cr|;>CpqV?5}fTE`7#KkS7;kf}Koz(G)7+jf+Q2A&A`#g2)h z_N(`iemx2h`u5T~KR@|#J1~JH*!Mi#;Cx+1TEP5z+P-n*#AK&OCarl7n!=ABUc9tN zbox=RK!LtLE6V&Dp<7RL?O#&#og`-Gn_;h{9*a2|FZb2E%0B)J()hfkxy(v}T$&6! zrv6*Q^xPLOOvHDt^~S=0Q)ly37Y+PCQas*(!ac>><BT$T&eL?&#M z4F?|d!Tf@XHr2`=VQGtE0YlZcya@EJ>!$WZ7saJ6Vu@VIgkUqH%`zsZj3%YoQqZG+mVRam!~R4Cwxg*` zE_I?vDv6@DJU632{J(BC)$i|rcqf`>YPjRe0{IuPir6xKG#|CAy~hpQ6%>h8?uEhv zJXd4*;-enfOs2H;B}(U;1B_W!)&Cl@z-l^7JwoVE&&w!*nbES9r{Ti}^gTONzf;P0_WO#8fs&1Nv-^0XSC&K+apD{s8{0l4|W6xtiCr zM&0>+>5WBkf0r-c9HKYT2tPfFvDftt0t`O(N2p$Z`q?tuq|*;1rOVV&Q!-=??x%Dp zmNJ>Vv1M@a^&tp+_FDieIZoey>S!vnExNcCV|DSFQEB-2I=kwd;6c>L+U~gj++AHI zRo2FfeW#+sNlCcBe9qS>U*vGgvsxp%R@395UCpDZ(cUcd0i@K9GWgVzQ#gaP*;^Tn zojUfPp*YPT-ZfrbYgy8 zUZr#@gFVJFl|f5KiHAc^v%?$#MKBl@4k=ddqll+L#1(aLE}aZ9BXlfnqQI$7=f8oj zz_G;bKxw#hl6G0wP8Dw|=2zZkmyP1{#Ps;U^`o+uo{Xy;UovHkT<_L%2Q$XQ-dnfg z&398GaEzkIAn_3L_m&Yg=176Uk6!$DV1=90{SFquc)d24PUuax@9K@1J7BH>JMN&{ zo5HIScK{e!VZSQ9HbRC#>D5<|Z{s|ADlIQ}8be+dPY%?!qtB$PSCo{)+sZlbzZl%? zt#qqmU2YPmQq!wmO5%|1OouQ>Yp2Ue{p(=8pKGd2yZy6bd}^t_2Pbyg_w44;=c=$9 z*}L(r+IsM%8{K%q7BhpN{EJ&Js729T_p?8HDBDs4E`SWDa^ohcSg9unkh#hXTiV8t zSDRS61eX#g^`%v1V~pq>CS-Wfu`mT^qlgm!>M1<9#DN3t7F3o`fuSQR9hL0u_UMQd zDp8*=szk=O-g8Cv)Vit8D7F6U77QC6R6Mze8*bjb+Yh{eCC+FRoxTh&(j`^emtQMP zT`dx;77}xI!3dl9{Z~V&kvJ}wmUPR((cNUBtVlFEA2ht%#Ij!KCB6 ze`@Eq(ZeD(S($+57SDlcCq}Wo@Fyq}4#ZyJ!56TM5By(zMRo|`Lb-BzX`(Ys zYMH{$O%8ZT&uixofTOG!pO-!!FY<4|#>ybJmeiImWPTL<&uy}!HW9UcYOO|03Ga^= ztokK3#9x!k?89%Brn2{wk8b749eqDo%j5L*sPYZU_)tBm0VAQ2gd3N!;7893Wo*5| zlJJoCRC#~p2n;5X`kua(!!%*R!nlxf5(S?ZRI{$(MnXx}wYcTgLJp)&BS7hLihGSh z>&3w`aX^7KJX4iIWfi%sPAcjRwJWf*dfk-v^;* zDn;Eu$R3f5S3Qw{West$uy@MStvVYE&F%V6h!H-h3-BB(d@tP;vr^`f*jz4qrm`lK zc1U{YoaA`I+n2!V-P4} zU;&yR&I&s|SBjBGarLr+`%vvDxZ$&|e#5pjUX@95NOCWi4It^Aex9LQCRDAosTegd z6}g0ZN_(tC>L#W{jn?RxH-41~+UY5*s|Bv5z8oB%9=_(@5q**6i1#}i_+AW?Vt{Z; zdzj1_l}PqYNeDPny4T=qd+q8#?HpI0wl878H<|3B0P#M%%54)`B~c^@k-J2DUzC7Mt@9`V zv^1f)=^2#T4+fo5pG%eIk>G&lZN7@RN{j#m82S3%FHQ7n@e&1$0pPW%63w=`G6+)h zjorM)34Ns+OXTZ(TYK(C#lxLQD!Q+6OR@)F!@CA2eLX$#QORHR@^xmbRYfPJ6*8^H zi*tuv4l$}@-l^&o`72=vhEg|BkgtWr07?mCrfxEB^XL<)Q}Z(2}GHA263O_4|kOZX@%dHy}2CZogbU z@qJvJYdBUD@&*NTxs~#NeQu&cCwP1|E`s1TeoN}LkFnCYtX6aLPO$yUby+TqvX)c0 zm7?q9RWP+}JK5N!O1RYkpKbK3XxF?bWlY z8yjg^QYz$>wBTQe%*HYL)?On@#wrxm=e3I;=lSPEai?<`A`=HTk~#`h>@_mKyRr3~ z&+z^wu-`|^?7)is(?9%;j}xyhuzvM*vcrX2Zz##d=Smf#-{->f0ynEuOR<7LCeBS6 zdvBu_GqhVsO-D|gS?uc(ELYudkP`uD0Ww+TmWnx=<|tKswNBQkBR9M<6&-((+_rEB zHZ_7qV?|775htauJ^<#9)3^*U%y0LJC}$z9tW%-GloJD~Oa4nxKyLAPqL)@c1~$y# z#wTS7@A+7l5VqQk8;uJ#a`5+3R%BuaP7hwb(LP%n=4=&irm3P<-unsbPbyz@ERd6C?h zm3JMMJ$N^_ptXaSG8)`36qES{5&ZElvcJJ)S4n^KaWu^7*QmCogD#nw?UEV)f z9%mZ)Y3NasqTs7+EKkC}A2evHt4R>4fo-U#{@FD=V41F6yIns&n4+l7ZZZ}|yOLPO zu>H}ue+$n@(HQ!|s9G*a;0kCMYT^R>!*9TX>l7{LQC7F1A%j0|Z}Tml1Kro}o_=SK zhN;wFQiD3~DLOp-taj9dWwvBfRIV{vQO1`!v1-&s8^MF831=IVpU|yIy7Q8Vw`9e^ zSV+*pjEo^lL;PNIO&I=Zj&xKpqqCtT#dt(oMrc|cAr!vf*OzeMtS{ZWN z_2#IF@g2JXtHkmRCf+tAqCCjO=hG8fC34TYq65=HNezpNws2~5r^uUjLJ8pezIl3E zV}>7O?JZ;t+zTK-h?!tf)uq$GquzczM{==8v`M1}FQ^O} zs-D=Hi_+H)C$SO$noo1^z4<$r4!*ArH{9f! z@6#ti8y&P*xyN1tb9h?Mq9}mR!$5bU6IvXqmK9`RQP9!OGh@D2B;R}7-;>RH5GJ#r zvQ=L)dO1QlF#caXc(=%t2y88yTn1{G&20J88%_|Ctv1@{>oLB!r~T#4*)5X8 z`uyQrN5v@kdN={&bPhL^NEV1tfX41d^fr5kWn^6)5o2#7<=gv#=aR$~AG|0?$C_~= zQ$M!iTSI59(ccH7b6r8=0kaz-DxDhyD>|?l|Vr`ML6LD^l|wW?AfzmY(5Ro z(Bkr05GFfi9JFNJ)t@`K)t_%i(HjvP|DOdgXhZ1wB~rceI}aKp!-j?8!;igxRnPt5 ziG7kA2=~5T+H@b*$D;wxx7j$=oFW;&-x(7m8n1>kj6-F)Rg_k2V2wE8?H!EGwp5O> zUdwMk@v>R@F&0-)s$Vn8G@|l%Bi4Et{x|@!t=SIl@QH-9z<}w{Ng3YP>G}jSm|FXz zO)YIzb>5ux$>%oA7J*u-2HMoR2^Mc3|VdL7rafT=%X8a{CGpiioW=MMu!!O-FH zdTlr4c3AmW6FxQF!U}b>Wgd(Bqm^`v6v@B#-YjSEY0u#3FO}}HiL1hGZ^nT_G>eKp zmWC#nDXdv?(kAG>9uvk{;wu{+_nYXiKEv5x_7pX`+y;&Nc-K9B??lvO=kLp-h+8a6 zp(z8S-sr&WVX54*!?iOHCz+j(h1Q2Zvx_^^gc4%`xjR`&1(O9E{c&&P0per^g_;h1 z{@kmsRy|zyb%eD1{TLffb*ffN?RkWJ-O zbqxFSz0&1>ULaLE*c#2oNS(Ei7JnYb%Ya~#h(-@k5_U3n?SFr*@BY1y`x#CL%B(3% zM{BfGL#>2*`l3bd>i1_EW;&0fF`whHCx4SPIWckKZRN*;H8C>u-{`b{n+Ha?{v8TH|2nM!8eQ+;LDRtP(P6S z<3@!89;ENF+29VizXQGsN#JXKyTpRZcDX*!FZ28L6K*Znx7;;s2z6{u|LDi}D|r6< zn}VZvZ$=V=x3Z9L*QO52CqwF)OjqIQ)7t*i{ZaGg%SF5&KK^bzpO=5nffb=9lMM|m zCJmXTnJc~j^9rHMk*OFPey@PXC&&{X?{5L$Z+}NuD#X_}wP;j7f0FyRubE4#aTVo2 z178=$-S2wJirx)qmY2^)Z(Ulz!QGpu&8|}4)8X!aU@xJc0nvHI*glXEtOr9E+avtA z%?Dn8>ffAdFdde}*!RFH$`q2{7f;`FGo_VvBa6!<_`R%kV#M01gDKQwuzPJeQPSY& z!Bg+Yc_*cnl^q#h@omwietkS2FiZI%;1wjm_pHOs!_$bKAt85m)F^Q)5#h7m?)Rdj z@BM(WrT-H$IDowWmWwo$90)ZZ@qEAX2q$`S*^Kf6>AZjMA4t2+fgik~rQTNWn?8qQ z-(#s=qhu2tnfGujKKq*jr}God0QBQ@X7@7ZjPzX@vg9!^eudo!59Rf}qVHwhZYm0m ze&()c@xKlNuk3TZZxml-tJhaovIOf*N?J0YAbo#h^Be3=ze=849XY4ZT~d9X%M~2I zlA7w}GCAXt4zejhk@phme-v|UvHEY%`U||$)dn~0?&lFrhmODNO zmIpT}BiPvg*D%9umO5(;#lX3ul^q<)dNP+zeT{LuUw!6O+<&tP)`g*`M^o0*>`cVkX zMa=9Qul_#t`6%R>=pbOJrvBG-Uh)8}RZPtJzw;*1HJ|Rm0I!CSxH)$kFIrjn(FvuD1p32wGScXq$MFD5meOVI}?@WLmgm6a1Qrho9F`Q>AV^F@rE3MKhKYcmqB z)Tya!PxpTwQojB@?dQ6>h7UW)MR%?J0s{3c4u3%9^Z3Lx8luy8JfiKo-HfIuMvXa` z%Nhc@f7Y0uq}&xRQa(FqPi02EyqO{Gb`$TnT7!)w2=D4O{=s%ZG2zOPw_mv26n{ zUnIgl2a`o`bShVEZc_dn!Clya0%+Ql*xZ30Ew~Ov*C?QjVXm(!xxeS_Pry6VYQ{|Q zv%^88g}xB1Oi$w}6VDUD@04V@!1a)IQ_<=b)U&JMot?nq-rzVycRV3=ZQXG!fd^=V zkEc0ENx-O|eIv)+(D$ovPauuR;mX=G9)F=wF$$3Mxw^(*yOQVTy<;c%S*JDmPwEiz zA6~xKKmA$Vn!(ElmEGk@cfTi{7F>iAUQ!5im7M#M14)@*9=;uX`ZXLDIT3S2^(+aW#r^@oS?TT}jD7YdR|!xK@`Kv2DC=`2x1JVqSNt2VB}%%gKuA^;DS?7WWg=|JY$`6F7tS{rX}P#?_2qD%cJlvMlYO z4(^RR5BxLMgUG1G1L3~=PKCdzx1Tj*9}wi+m*Szok7teF8SDR^BZP(+QeDw4syabk zU*{f8Jx_2GJtU;|J=Ea8%k-!BkQF5)y@rjR!QEaD|8&&kOw zJ)9%$&LR2VL6K>lh`x#el>x&EWn(!OgGu=^8|;NdU$gQxZj^RUZo*Z_UPANE@4z`P zm&X}{!-pk>S~si>H=`A^OhV7ya=6R^T>av=(24u^p;<=NHM(QB>4-C&y@woB9a z94qsvvC-1ov21pZ$M#N(J-Ig`{;9McseOHVdEVwEVcu@oM24JS9*l}xknao@&?66> zSW+TKT-$^~n18*xwcZfaBntqaS5bjn4szC(jza zJ}R@npl;=|dbKo> zIO{WdSg#C9w1|7Xma22y|4z}^Nt88(tMOmDyG^cHq@(CQ-p@p?-c1AQx(<;+ zuQO`%^sw9D?bojSU#8eyau*9lZCy!`=A?S|#+sB77Yi~nCD1B2oJG^R8Lfxc)c)wA zaUl2g?euS%hqv1m3&bCw1#EqHJGN1l4^Y8^!ktd``#cf}esAgB6@1;e@ zMSd;!Gat#k+C96VkRs@K7irNd|9cXc+tSSqxe^X|-fawP9KrN^n5G57&D6IOD<~M! z7dA7Uhkwj`jsoStm#@^DzzZe;k8iv^-d!YlmT*F%6}UdtB%cyTb z#gzOpG=VpbJTD`j?x+4}vZ;_kBkkI_j=pQSFgCtRb-IH_q}}igBD^YEY*JEi;y%CQ zrcjrciJ$!gw|Ty)E?Cv1x5aSzV^K3kV&xFkv`(ANtgNqRP#le(pRoG=?~1lpaY4sl zsdN03$^JW&JEYPV&DBHru|eQ}yMPMe#@e3&`mJu;y-o;7+b%p-R&QrJr7PBdD~FR^ znnF+vyu+H@>vY+|4Sb$ud=8=fj~7#?PzK2*fxLh0jNNBVE{<*2BO)fFrnvW5qtbQz z*q1pR&f6XD!>Wc;3(veI5&Dyg&TV;HU*+6fm@qOT>~tP~I@GOS#(8oQBT={4gsybo zgP7mv^i)oFg=hf;cXyJP!M0|r2Z2rcZs=yUN3_;@q>NBV&>f1x#yBU6+9!`u4JTE& zQt^VQ3Uwq#*9<>b*dIN7^!uJ($`e$n|8ds} ziih2Q2)taJdS2Ip_59ti2MxUOtp&3X2;yBh#R5N>$(r5$n!$ATUSCC>Lvzx!lZ_Q8 z!%I7`9Wr&=ywIUypxbkw>l2<)Gn;<%@w)&%xLMRd!D^Nn98?ch|LVMXYNsxm%%_|J zS_UiMv3Z|CVj=^RRZm)^*`95>rEQ{RoAiPq2+m(GGwU8j4a($9`UD5aXwQG+16Oq8 zv#5qW0dq(k-7(F2o(!(WVdzpAZQO%`*uB6rBk`mN+)7FM1xpRe1i?=ZJH zs>4x-(|Fr?`lQz5az)2oTQ;Yy>RzKadJ{aR)$a2MaP47O8)28!(7j-Tj!r#i-*c;s@s?>Cw?KeCIW&wKK4%5g5gF;=>S!_0Vxr4{7 ztnG?NtjkMh;#PMj?jf3!NR-1(K461@5V%(cP*0-(9W($Wzzg*^m+b)1!$lRw2*HAa z1w8#+KPARQ+-og9tH`f5{8P%*X=m)Df8fu?bx?6AAv58+jI)}VaNtn?&>1e%Nf#3% z@e*l&Scuh9p@i@Fv<78LWc8-+N!)M@B62*noANlz3k4$fAwU@?*v-({M-ET!Yx7rR z?t8qlYiS;4c5oU8576P5N)0BIS;#7ZkcVPQM?c^I#T!>v$yC!Ci$q{gzmWrIn%Dyc zD&_AKCDtQw69+$dqv*_|?jNXV=}+R=Wu#<&^dtpQQ$~*oyfV4(wj~9R%`PsQ1C=)g zoip;`n`rK}^3~+4DRTOCD9sDwKw-sNhZl7wPOpSl^{Y~B7=cxhS?P$+dp`eEqYAJ> z(=`|>{R83AEwo^PCR{!27Z_LOxv7O2OJ_|8P}SIMILpRDigE&XDr+LE#GiSNBa3gq zeeiCTM;%`O@majpYDDfp$SWVcBCnE-P~8j6Fi~J9B8nu4!T7#6F2sCJiPuuvmX;06#to}B z?lbsb`psiyDyGaTISyqVMyb<&?S7BSX^eSOI#6*y*^PAdjF3$>zCl6qd9u0F zNlwgMHKtUOlnhw2RzZ#ElyCNGquYq_Q_lm#jGel64dTYe73U@oboCQ^EK!2VG{tI$ zT;9U?TBF!j-y0?@9Hc&j;qM%)p073>6E{q>QN)=r5#+T7a~uhUv}Wh?9-(dHljX>d zm)*XBFH*|Ns><@#75VJ#z?FsBC~}vb)uVj6->KEoq8iVZ^OuGTy4Mv{apjICBFIFH z8f1(brf=w$&0&=eNtW(YPT<+yBBR?NuB|M<(JF?01JJ{>|AaLMJCp;RN|9k<*6>&m zDLc0RA-i9|3Y$cWn!pKWu<;$8(u5RHOOTP0Vi0ExBJeZTwmqqqPN6Gz{6;|>ssqzg zI=uL9e%`rr(tU1y>15q()VwMJ0~ZP~M59(NsbHwas@7~f!qxdBlZZbyJLM92{c@a~ z-Z3nHfA502dDo2ZKGtNqo<^rNlSD3~jwKbD3r;JzeBC=Y{rSlpoy(&GHDDZAc;dtV z;V5;*a5B5q=>oKL-m|Z#PG;0)3)qf-8+u@!)}ZTpN<5vqoB2_^k*46d%9HncTv90w z_@R29x|+DV?xbawcq=f2HFXDNyhBJTJ?|hcg5}EtSD&RuU}h0C=zO~gKCTH>&CDT9M}*tM%(xv%P4hplw|YQ~LJjwpggn_JaY zd<`=Cn4s(j2XtJI(%vl~?dU&uKNFz-ZR~%=0~Z>2<>A;f_}-sW6Clhk$jD04;hvw` z*TtvB3NnJ}eu9AzjxaoZ+E}&S6^au5-EVs-PEh^kq1T$OyjOYZB8F=It{#-ey^pO= zI1;JioUKO>o~~!9e|P;4iu{U;$Uq|+qr*|+6XbLnePlRfYZme6@6gTc&Dl>0a9MA- zIdZ7qadsP{@s246e^Jc5ye3{LI`n3I9X&o#cR0!N9rBiAFR5LZX4r)Uec#0A5A3*ttQf z7oM#d=5Ncy#Xy@nVr{MFAAl$rq_hzg00Da*#Dl=G6;%|D$2<``v{%%5mIjPPF0R?) zb43~h*3$;oiYsi4)2jAHtBW?&@r_ z##CxTz_Uprt%i;{S?PJ`KA*P!QGfO~4L}a}g~09p`q#x=ePnKe3vfc*4?slYm%rUx z$Ib#a+RjqZbw+Uv*l%IJGfW@7MRZnuidT1npdqKx_~!0l8}3&qfJ$=|_rhT%UdI8_ zV%8BM@xaB`NUgR@jOId-n1^g&@*%o@eUWke*zw`*-*M|Ru<$9qdRxo^QxeHi40b~X zI6Q9IMk6pG;_%S`kdnoLOsObE#cSVlXVe`3I;#Yp4(tALFj!2 zx-9VHKVok|P)qo;OX|!XonvJV*iJm^{IQ;? zP)t}i5LJ0VlfcqkNrE0;CT&a#%pZXosf&muiq1{Az6}9|IpyHmoGMY>( z=^Wng*LSfa_tgvGZC~d(xyn^ZQ&OUzdMcpib_6clL)QU*+?0BFkWU)GiT`Hf9i*1O zCRwRwar~8`%HNy>Ca4)wjLLel>@ScSK$fg?Xyv?kw-%yF26g3DP^`Dg~Bv3Z0RmJdRNh(UyX@_|74=Fvk9fOw9wJovZnpEd@0tlE4AQ-@AC`g%r zfvjwVs!kyJ+vz^oYF3##y;zQPE5mTH37Z+T=gfQ<`8Fpq-%bQA4sZjQvD3)d;(E~>{yBE>sOwtmFQQieasufUG8kx9SV8w{j?`kR z#e=m=YhxZ(oTx|~v%iFAt6$xe<=6+c*)|tWb4Gv4H3`>jQ)LVfVc3on#CzQ}Bh}y;3}eR-+`-hqiCmNrco`mOsT;J)Xf#SoJT$#e z1%V0^B?_961E}E`IE3Wpft~B5a1+Z!PLUFN^&^fLJ%-Kl(5+LfC_ybZloT>^AjD*y z|06xWK|%|G?*`h90Lg4wP{;%=2nP8JG+sv@r9_osN~+9Kt1^2+HVUrK7SYnmYPJ!^ z`0-vk^3G#*X_iR_pg!q6UXr>xOMx7KH)f=!fK_Jk`7-~$+gNamT>47At!a=yQiW$1 zv*qYD+D`?_G`Q^G*4};DXOJ2Nr>Z;9gvOSwb_zRCpxU6Zls&EPW{YoA;K-L;^*S+;I&;E zZdokv;->AlaPDe*o7Of5rmOr}gKZ5^16Z5C>aHn!Ieu7T}Q?Pz4v<|bDa zUgBt|Me3-e4_fm+?sQIBX394JATN0pmmV<)lV`8NrD5~PvuDM6D**BY>VGdoL&h=7 zw4ssGDH13>;-mMpIg!p^mSi=-8BeMPv%b>f)EX^@dRhpg3^5I%QGIv@$lmSi$pf!H{S~)aIgc0y&#vx&dlMPan)XK}Q7dkfLn+Y^W3Z|rfH8THhTd-f{XsQ1A=AG$o zd*yXBm+mZldvBp-nU$rf@7|bb`Zpn|N<&i$1M=2IOC1&{nG4^`j-dFhRJGGm*~;bQ zrF&Q8+|3F9lSWbO4c1(tia}Z5T#xKxd4uISNj~JzjBcMg%J^SZ~ zO>i{7&us0Bzy=ipxZywqK0hRm5SaZH)uEcK1_O8<5W=YkjrNwYLucgo+(51gfW}?* zpR=B|X04zCmXLx*qnM<{@$#Vus${7tqd75@s&`dH5-*bC38=Mm!-&xQ0RWE!k%QK- z6?Lr!95b4?oL$ljj1C@jJ^%#2usm9Xi9}%-48+i~_3gA~gK~422wAA24qz%1;E6wj zwcb>{m^AN!Iue>T5>s~F=M+Mh@d36hs>ug-tgLL-cw}dw0ae2R*OZAz;QL0t<-C1- zW@(fA?K)xlw|Xp(UKSPx63XkMJzMEnE$gF{<-%L?c69n2_sDhKJ2T0VuZ+XIsl~$= z21IxEEkBagEZdG->Srv|m%luMU5aRHPy5+o4f0+&5sv_LDwe-jgo&RUU4WxKPB6dPgATHZ`(EqJK$ocZ~Whn zkvx=$b}!1CT^b<@vt^fx^?o(zSNUHAL$36EMIse#uo*>+$+997a3~uPpbri1$z0h} z_gr8BCdi8*Db=bu{ZhPHHx}=Ihi!ZZ&i^ly@vtdZXJKhSaOoUS$qFY^#tI!W=wUWT zJdDZ`?6Qr4RbUVdnm~VB+X9z0LF4Bb*G$x_sMn|8%NGQIp6*-_p|;iPH@p#RhRFJu zP@Y2GYu0Qy?$P#maD*QTO&HnYO>GhlY=kkJzrFcW$BUh>x{Q>^0ji+$@Lo)$i~+K? zs`o`e1Hx~B|F~N6IaE9IUUDss%pSJ+7PAzCp9*Qx@TT_r%8MP=< z#8n4m$8;_$q6GAG{nK151XV#sOzYNeDY3s}i8K%g^PlZ|Ka7o;Je9RmUD#of#( ztV-HQG`s(LfU;y}8!{ykGjYdk_N#*Jt7?f@RMxMC&`P!L?y8jtg0a20*h5y3tXkaX z>d=Al>N@ea)x(#56k;=<9@#-3j><*BD`OUY{5L3b#?*xW{p;I> z5N68cih?u7#NcXzParm1rfI*h1)NZKwul4|)a)9MHp>6bJZ$CDClL@MMtuMi^ha0< z`x0iHAtoKS3Ux0@DRcsALC%Y)IwgB^Ul|R0(xzNRAo)O7-zdzQ8bGZ^OY}p`IctXE zV^hEfFJ9mQ)$j48d31%4@Bgy^e_ursDxUnLp@q6PL$m8U(Qo@6aW$tmu&cQs_Nvr^ zGqU(1A8l4Z$ZCFf>Yc(2ye9SOT;?rRC$(z-Xh|VAZ$dxFX(um;c5c(u&6TV(6Bl(Dip!cHd{vE9O~ z!IiG63|z#e3*Ou}dC}i$^8%6hyGB`khlyF;$%2QQSCC1ugVCJ4Mo;7tG8~7gA!)Ax zjq{2Z^3BxMi&q{cP8vFlJcQ&T)=v|i{VJStB+%I-EBhvbUQS5{^bS02*pd6R zApe&z%+B8sTe_o#kTm_AuXKufXd4f<;*sPjs+v;tH691!5qCUxO*vhO=hQvr$GZv2Igy_XWvj*#kt}ZD zv%S+rhXDnN6(L9j` z{L^T_LXfDm2CG1Y)L_4PS+`JXmCIHQ!<_2%l$Q_vr%v_Vs%=WXD?ETI@S5|XOBqIV zRU@v!^SeVX?^Y2u2M^8ZhQegsQZRonqK9koP^FpG014N+CiVC9Q++MFPMn)uAV#pM3f5 z)RRdkFz3i@=&JuwO^aj4e(!a1`bHQY_*Lf&Dm?F||L>3c%*lo{ejECqN)ZJ{X|rbA zQiMl=WJ73?c6qnLAz46#O!T)wN);$!R_R8j@v_UTdXcBCDH!`zTWD$p2PkXIbN;pv zjlGYod?i+j@aS#8;eEOUrybTCnRaTRho*FRUr9`r49@{uQH8gE5* z5@=EMz$FW+d(VPuu(Kd!&1%eE9(+c#&N)>jWsN*!`y+iQqJN>HyhsTx;4Lr5RBNz6UPm)kGa8Z7 z3`hKR7{!vLD~THpfI^P0<_g$zTltm^xwEW3GHORh2G{l>0QoPbnM;MVhDTtVt8e(F z^z%1z#`f_$xMcZC>B@F4p82Qs#CTWXXi|DrWA)^TXjX4LKKO4(GkS6NvBCIQ!~83WG{wp3b@GcZ4b; zR0|_-*n)G=hHgu%_pmGTLy;|_SE8c{CMAACv~s>Uio!fPwqe zdf{JIPvgs>k=4O`Ds~G_)NEqMyy8WOPEH$ui653srrj6a%Gy#x*QR#uR;@UHP11DoHwMMrN7g zT3}w?#uzTJDRX#-y@v$&v6`6m2NM!AEYS!N3Q@WslKo|D=+6myGoxeHRvm&*$Io`7+?$Ubi z%``*~fP_Co$7FTfF-LQ|#e(I>7zi9f-`2Y~#Rd$bRKCn>Gc@psdU--OR5p}`C@CLj zmoYAql?#DTL0^pIPF4DYDvF(@p$4EMkG#?R=q1t#?lJ#e7Q*xEAXFoYOytDs&K~_< zRV;`HpVnV6ijoWiM1|2?2z7-gC#0&;G ztG));hFgNuHky~mAv;m%uK4yOt7?~Fj4H+##$CFZ;QY+AiF|!xL z_cfA*63urR0c2oOK@}&Y?wr*bb3#6&)Z`O!nnby+)hPA#w6Eha`Yt6YJ zoF?L#}#DVa%4MJ1fGl@gOkQl9hbEZSd$HJ_2%xVhbG7-&{!))lf(Ab#O zV2G_(k>!>GBke`2DAO!VX{#v_iIeWStm=bt8*bgH zHaVbRkpE)Y!FZiL_l`O=Gr(0aUQrYjJ+|cVN+Po~jVCaQ&>$1GTTP_UrNHl}=d^#J z=MY6$7fmULo*ApC@!7rg3rM^3$dTg(PqNkv9b?dz-u{7QqeeiSCq1Z%QUU|XFdV1o zO}Py(mgVZB09EwdrmM$SdkL562DNe4_S{~PPn!u}yiAWW`-2HbEhATkx~KMvelN!U z?x~aJhC74$wj%u|CgiC=r{tM2L}O-xhB$$`~s=bT+tu zrw)UvPLIO?tA%c`BaH`>5K|n_E(laK859*o0p^X)Tq&MrvTJoKM5>Yi+qr|geY_HE-xvWv%$shvGLoyj#M z_h*i+Mq+ct=vN|oq%0eeHK*^xDrP`6;Ua&l(*~}PeDB9beK#Zi7rPB;1#~VJbD<`P z(FyH4F>c@1wU?JX0ZO_!^KD_6sso}aF_5U5VY)Uxjj`x#&jqQIXp%&~NAa%^X@xwy zwL)W8ioQo=Tl;jL`jYkld_m;ZI&5S~RjTpanjMp7Vkw=3mxL}kQh)8kz74cq!bb&f zbrB=PQ`%~AH2W|{k6P}xuC7Egy{55B#!pZ3j4ZRhGs!Afe9~~+5L^sZ8ns$FF?X@n zlIBK`1JITx%~Pf-Qx+ee?>XJHMfIr?9Q>mC@+R%_9$ZV&&(04};*@34Cp$ic3Ytys zPQS;Qqbz@YxunTLu64a$k&Z&XLHqb=Er?P(o>c@yyJxwotQ!psNC&UeIn<0lq;LF0 zrC(c-Ov)K$fOd|o*9^xd6Q%eI4cH<3wqwC5*~!NL-+=`^4)NMz?)`OA5}Q=hL1u$3 zxgu68$}?=6<-!*olS+OTGW919E(Jl5me-OM%x?o zc$E@ma73tC8e~LG0Z=?%GKUXwG;|9JF(5vk0S*iVKE6m5H@UPxhAsyNgpK}lB{^c6 zz0wS&>;9@#s32|R6ztGS@IA*P(4nD9%2KLM=L;gx&^BH25nc-;NhV$o-)QV5%+VwX za~G?J4F^FgEB4ARceV?_6^mB8wd$aBQ2_(Up>Da9fNZ)}DLYTGdXDu!!57S!8c?mv z{{4%)ay~9M1{@#7DmE`rYC%;1L%DuoQ1&0J`o}Li+LKf1#mrSCY8E}{OFO*ckX$te z-7PAXZVy3+v`_8MqyBphf8as{c#dX&T$M8#T5YHMZT@PGcKy`+M)5v-vYQ z*?Z^CeDlpWGo38^TH*}_ln*KnI54sF&EZ=-MRFc1^kfN%^G+CZm;{U2K2gq^^dg#E zTlC5OBz%ndZAo+cREgkf3SztV|DKNd(dpJ@D#8SACZ_RcG{k#mffEZ>3|Od|#&)Ii zTs6J^BY%L|#Kcpggr?3==hwu3I@SsdWao=|oypilt$Fg_q93NRr*gc0s;Y`?Z0usQ<`trl{4aB!5t5}{A>UV2{_yH^NRXJc3 z?Ps&42QgwYD5+r-Fg>sSo@|QW9pf}pV#>u54 zx0~u)SWqAERDibkBjr@d0gk1U+^L8WcbtE?@FnK+07 znA89s&6fc4Wq}UdN+{}Nt>^#GB5#p)(fw5RQ(kaUDPOCB*bR7PaLGv-d};k&Iv&rUf(uYXqrsi|)_vH8Z^(x^+j zF`L*6MahE}MWYu84VNy7Vls^hfuWl87k5uI2VOs}d0M@>u??34zMk0!B8RdFu~L!Y zrh+dR{Jk{<|6`FMqM$3bhSN~}(b*uVc#QzdP*^ruIg>QdCxihOjbk#viltJGa_1%} zf54rr|3E`2WV-(C!soXsvy?^8J9`sZ|1(ZT1kYlJ6XCmII_wE-mF8rY1hwbSlBt4) zG?)pIrUFwC`e!SGTxY6-%55?1lw~dGkO3xxQ>f`h`(2oqFLXk?$-d3M4z<)lbDZUAS0Axdj7j=mfFw%J%3y+_NDLL zpP_zE@&lGX%cP>p6#tB7t0>z?I%NSGast{QSbOU-4S5mpwX$?X~+HI0_M;-}ywkDrEXg zsyxH}X9x7vNiF@9rgVO}mz%vpUNwMf;DkHum7Gpx+0y5qB^YXCA!Pi#*3ZevCL!ar zWFv>gEEp=Y-ZdFuB<0!4Lejfx%@~7tiGz(tLx#3L&^%L8r@&HO~WFP%74}{24HnmQqC$AE-`)6v& zy`Hl`9F|eA`G7PW!J)*u!3bzNaIEfK$5%8b%u<+*W=fABj)p5BeJJsZlK`2o)>Y~Z zhTF6E5`rCU=>aK-{}S5n?tEiQndqf!QQDnf}1%5K}Il*UMqQeyHor*Njl}Fu5j4eS%74lPLmx-a<2pcIvKQ5?ACBshf za8_ts4g9<*yO&osXNJ)~K7$;IDF}4mSLf6})>?6MCsjzgRX)4gi$x(hq2u(3m}l^G zi^8gfWtR@0MbMrh8c0gh`p`+U8XVr_!47naVZNX!Lk3PzBeu1{@@B~UU(v#uVvvK) z9sIpVgGB&fr*1T3q%L0h8&*voa4Z5Wr7JLl%^N3I2aX|?A)|qLZ~rWTxKK}cVd;JJ0clfC>pepNtM1npG0OV4W!2pewgAH=a1k<0vqh;Fcu`#IqczHDSXi?PA ztyO*CmR&uCvf})WVc>{Hf?NSDZp^$dEN;fbi=7GkWD%VkZ*yiQiM-wS6K4N^CQttV zjxMv4dT(FIUyiqKPD23(GO9c}Q5m~#!`~B8!3f7D<@NXHjE1QXhia61gr)jiRSo&# zO;=TTGY%TSU9}mMznn(7dz=P@ENRPkRQn_&8RCh9XJRwk*4i;?Y&jh(5d(lXaR2q; zyY-8H4+~>rGF2xJqz;GN=f7S0*+pFFTMul9UA?V`+{>0uWn@-TG*gE*7_u=M+Vwul zHt_Y#h3)6ZTkLm=Fl?MD<%F^r;fI4RNzzXr12g~vG{k*dvLkb~d`qfEpGh++$CO(} zX;3V2jofia-+r(aw_M%F@GC|*4uq&bW2RJHum=++1v-ZmxMq%stM&Cit_+a@ADb;; zy|YlJHnT>FzK-EyUA}C3zm-08e^;-!hlc$Z;>Fn}X4K@!w{ctG8k1e_ z4J)x@$NE}*ncXMlGF;L=Fw`l0T_iF4V@-%!^RxZgp6bm<7~7UijHEz{h|&tCruL0}*J=&-P!)8$>bZDF+xyC%j@XC{~gRgR5MS)zUlQFGFk1Ko@%g0Qt26! zHXEHF#2*{{*2+IvVsUl6(dT|Na(Hzr>qRO}Z!^@z1RQn;9Loc7V+XG?H#@)*oZfu|((mX*q9LK`h~RapYHV-2EG;@#+6Ls{9khYHMC+0#v)GxJ_HesR^O8VZnd zF=Ty>*Hdwh?Nj}ngc{ua^;F(5eTtgen>_Ekcea1N9DF@Ez0t#l*pJnvQlru)jlgPGb5pen_}V@s zEqeZ-H{Zw+JeS>NB#@|or~STj4{3JVhtVga1~l7^eym&}58zTGS6rb8=pQodjtm&# zh63A^739h)_xR(Uc60mEC-Wlq9!JEF%lV5y6?lxH-5+Ca)uo)Zdn5t%N!gR-I8+D& z;8RSWYKVyOmc~Gr9>AG2slKS-+(p^(df<=N+~C&Ih@GD~A6$_CM1SyOK@+fW534uw z_!mNP>uR$rx-&_E;a}lPn;)%V4Zs69kd* z>o=r(S^R`DWUp;{P}AlgU)hhK9)8wq-aTt9xX$kLQBoaVDWQ( zE^8O(*nOs`;kd2>9dF4hPSHLGzFSG0hbb)EirAT3!FOR&KM2f_jL5;I4B0m6xt-^1 zHeA4VUcGq%0h_NSQ+ds8s;WY?u|-j8<<j8pqayO=;;&n)+s7K+k(PK!!L0X!>Flf36TSl6>rWPG^lHh1$vHHTM>COVGLH& zh9p)eem7?SL*)StaH0PS{}4#Pwo=)my@4p2I;sQ60LNcaEstUeSc}lEhq;cCDzQk= z+ER2|gxIU^1KtMvA)582#iO?l7bJ+?oW3R=6ks#wxVrAjrrAoUuFF7 zT&AAjeMnKGOQq^`I@M2KDzSZHIc%kWwoY-`mB&WEK)ub*4sh3k$e{N`|z zwZd050~=hp^JdbxAk<_cghW^K;?-*YX(h-Q&cpcJ1M<5|DT^SbgDnNf`fI3yvB`xRv*D(CI=>)&H+T?iLue`+e-XbVS2&MUz&cuxp; zz=Nk3$`e)+Bi5#?49p>3yl?HaS8*aN!Q}RcG#RXT6lhtOX&a)Fu;r5^TcLr9&5c)^ zdbIf2Csyklj9H_|3De%hWymr9Upzo$NBO^F6p=*;SpTw@tPDT?Y}F$hYpqjSlRWT1 zxTHe85H(^lbBNqT2h~ytM;G@CAF?;9?S6M7EQjvh%ghR(spn4odu9FT_}0k1mV`0N zSSk&IL8Nq-kyT?^^TfbZ45E_vY;4(MEv^wHYym;We|;;P{^Py}2eA(amQ35Y$acr$ zyNl=a;(9>mxq__$S8xRrAITbdMx`TrY#;UD)=e18E=tcKim^3Sco}VL0Ka6dlQV%Q z@5;>FJebFJt;9PTDi<7RVH! zx^;2;*<1plb~O0hh|^bapJRmy1FBXIsiq=>-gXXG$uoykdMP!-H@hx`Y5|ACWS z%Ct|1xTc+{VI%@FL`X|PFpUTZb9;*_Cto&}097YU5j#@8qV59;;R6Zms@#biq&0DZ zJIuA|rLO_gpL-q?+Xd*Zwl>ud7Mf(FM~@?c=(WNie3}1^dj`0WKf#z6KXl%QFg80? zo4p1_YraOmtO1=AwlWTXAgf0`M>$aIJFoR@;(kmdsu8y4Jf?W7H}PiM#ddEa`?e~H zuTXWn8DDtpu?4spAXN+~MQiuyF}9EOtv~~gOV;9qbsSoW{@Y1Pg{F)^>_F1v6*Ebn zs-HVjAk6{^jyM|I2Ed{n2qb0z66Mq;%bt|4*j&ne9({s=<`ZR>({qBp<2U7dH(!`Yf1RyLfTjOoB zm0)q_6G=P7CmRh$E8E;VP38|I2`i`9Lmtv3MiQ_xE07cC>xvfTAGiV|Eb!cI+dkGY z3U=m@UdkmIz0CdoM0JVn+YEU4B+ z5c!_8Ye~Z^PY>!Yj0wxl!W4Ze4cSni*M}NRoHH&%H@xcK z-@}+zG@>jERNz=wAfX*OQF}|eZjrPYExdQ5asvxQBBfpHbSH2WQUAzH4+JkW;D|f< z+8I4@gk=loV}9Iz_y+of#nOvMOhlf$a;*q3Ez$Q=N96|_QG^P!L~DssO~&Ttbc6q- zi}!YoP&7i5-K_Vk10mtSqTgfGXV7^6jU)GIysgF(ycu{{wsDhLyj*btJ)&r`3ja;7 zefzH$QbETT-I+xnk1M`o#?p(oyQG%Go=rN_jFI5jd(Q7I`i@P%lGo{zK?&}l03%#M zLrhFze!RY*xOYPPI1;zclhog5NZ3E{VuLTc3m!~o`HG);Bw8XS@p=S3tcVAy2O0WQDm@U-v{o3e^*lR39SD#GK^M zH_4ILuhH)x{9_Ggo7_WpW2`0gM{1#-+-5Fj=Sw{Nm46aTt{0ccg7 z|7twXP1RXnZdDY-7)4Rov`GfoQ-dVEyb1Hur1*IDYI8g!au~qE$%aW9B=8y}>G%8C zapHeCCit1W!}sutzuN5mW$qATg#CSA_kmO+{tT(=ysv7}Ae2a#E58d>q1MKMxF>vV zaGNaf-QWp7q`>Kv?>nNO`@YL5AA6)6RS?PA1L}s4vk){)C=kG8c{gwyP(XdvAo|of zVc!R{;R|8^`x%{E_w>ig+h7lc?|t{2`%~kgNGm_F$2CgJJtIzjO-aS`8|5fv9N_X2 zqf4BH7di>gv60v5MYpDZvWkH9GrLklGH=p^$!0)DzBPS;h^jW_< z#0aW@^%jH|iKj>N2BP8ErKR{dA97(A;mU)k5JWmJ8H8MA#2vW8^5*%$wXCbJPY+)T zFeMcLnTs~Em-d*y`Sx4;u9Cj}t)~HcA;T{Ho(X<82!i~N9U48^(xnn=<3g zu~Y^P)zyQ^z-vQ|n6aD2Rbfg@oc?Q%yq1rd5+J}e49W2E1ZDS!?9`&%J6JZL2_yJY zhqAM9Vz$5jCmN;8<5)sI_iY415p$%gx$92G`wStsziLt6fZ{_&8iNzEXKo>~f_W9Z zE&fl~mC(mt#}-@wDIiYp$%Y3jtEQ^<_s4dL2*TT0lHa{S`^$n2dy*d@UP{MtJ%wvK zw)qWh9GjFH_VH?pr0gj}Sjym(1Wy2*n<)5mL99+{hk-XXT3$&ybP=C~X)fL=|I)5% zaeuM!em#HKuJ}0g>shA?LwvhVu-rnC;2`p1Qj97q1t^Vbd%nrY)Gf=6azgLjD5^#N zvWOlVuvAXT;5|8{r3b)q#$48>n|F=nR1aQgpsB+CkG?=SW@LDWK}cS2KkApR3g!gcUL|TL%FTUAxdr@YK(DZ;~gSe%{}p z;{+KoLUcJ1cc+9dk<(@OqFMv zVTv(80B1EpFBXnNuH|OFRPjEW$9ZwpQj0wYz-V*ZlmjnO7#1~{pV;r&SgQ)MIu+ad zz|^g$L-^}Tae~Odo5CKfBJ_3NbYSO2KC}$C z26}Cw7m#QT&u^6Fhq$K|BX6ihAQfUGwmghhEijtw_bMjUKjRh2d5%$Gc=D#$Y@sL- z3W(Ui?WKV`DU4RJ^Hs{?a?qXj(*2>&!D6_7j#+1lXBQJ3zJJafo$u88N(s=<>%zhs zssr6!mHkgag+BtN5-Eb=tuterII|n$OR*;?ZH}xj{%pF8*Zu8G(R8V_OgEUTR2R&4 z8BE4Z0-V~CaSsQ}*e!= zj4;C&Rvs7V1T9ExdPlGpF2A74Mfvb;=Pa}C>l-Ryt99|-8r~@*M?F0RJX7vVVqv1p z%eBc<2blM$XlUI)$^W^LPTQ7tV-02SHUB|Hpm^!fP#%g@U00TY{jM>E43H!NMOwC^ zu%P0SM@Gt!Hwf*|0gikg-0)M{(jbM{dCM(sWH5MTza38w*6J}ZS0{<1XZmbv<*%u& zwNwR36x~HEY1UhtBz=JlO@mBSfTYf29ndFI`=*D?`9+yekkNSR{gpg16YT52SD^8~ z$T$`9lbE+Mhe)j>lrWpJopBx&V5%Ce(43V{CLW$TV6g&jM;nojHp(gRc+Vh* z5xDR*9jOAnO!6BAp6JA1QYlPpSUU}bCU8aX$n@{+u(ejM5Mo)ZxA_8f+O)16w(YW3 zhPPZ19(uDvMAN**KzBJAK$si7GDCqtkxuRi>d-#RjZX}%$PO$C87r^_J-+rt=E6zt z-_9zr!^RH3oAFJpuEh(o;QSV)gzGeFIq;gpi&W~thy@&-spOX6<$msL(~%n33eRDx z{u{tUm!HY(cQ9Vo2GG75c0TP%c%1qD#D$)QA<||L9y~B(e z>GZHMLVg62$(B|Wa>^wL5CDxk^d$reIw;4-7A@P%d70X;L~$n@COt)mnNB0f7)))` zdK&eU&fT%j6GtXems06FTWBla@3IF#wnAy$Bc)D3Xpw0Tuyh3Ax-1x^PP^lhkicfm4%yWxWbX)d;GO)qSnXMId}O12Hgx+mlz|#y*Zh8aB8zs?=KA;9P=OEYL_9SlxU#_=h9bUA-aFEjO8P=cHG#vdDrWT`SGD00Ng}V|}hoLc}z~U>IX1Vhzpg$7n6afvx$D7ilg;NwOjaQ+>O!o zWAIk{#L2<>Bnw9T zwmk$tA`ln$3!U%aRN;qCpn*jLL#6#ZE%+Kkyf#~8P#6R%B(PH$ zcSeg4CQfM&!F21`7a6RFc$u)kSgUruePB1dtGowLl)vzxE1I0jf!GY5w9j0x!m0UY zR(7n0FN%}NF(V54cIikI5W>jeL81wm;;cy0iCf=!r~f+P99kkCMq~47vxtnO+E6E5 z>v=4Y3`TRQzMd!TS{y6^YnU|&F+N=lzv6rWmnC;cN^_Wyvxx(R$r>O2qzB(~R=a*? z1}-20Vd5}nTTRi6EhQ?CRgqHk1zE1!*&i&s16ZD52HjUub(}yr!%HU$>BW>mRNzUTc+XI-5anra;% zT2?Q2{XW`$gkI&-Y}Z*D(CICrzV=AXH;tp|`skl&HM^o-be%mHhta#gk$GQiY;N84 z6>z*56`7I{>xDdYy?N@n_AHbaGLQ*7xcTIhrAlqLYHoDfyddvx9gXBG;viH^M0Qpq z-@3W%ED$jD#WE6LufIp&k(_%y(nc$KZX*S6Jy1nOIaVOm;xI{)!#lF{o!JlZ5d6NZ zUS%4fAbzz)J*sWxO@&!Zud3%wNt~ADff7wDHs&6QT-#V z{;*q_|8^B;3kh-?B{ZQ-xnh20HgMw{8S&O_TcBAlDsSHB#+p;o-&-)O#`lIEHKC`= zcl*;)y;Gq(K1~rfhcCzr<#bSygiwqdpE=dq_tvi+p;_PWDPQ5mZ~cYE_wBI(%kMrr zS5WKD*=Dh_*U$HFO(WwH9&|hxFf2BwyTS`)8$7X_br%6sxAn}TeivaUws$q)}XjQACqPb6$81l%>jh}2fJb44+yXp`HO5eTZCSMJD; zz|0)fe{qw{Kk?RD~r$NeSRChm7clPwClq z#Ko?t{B8RuG%ZS6GUE!SuHe8UEwXUoC}Qz4=p`p)3MW`<-)vr74UbsgKF}&SHHJjU zV>*_grXBXeXSMO@mOTtH3xP(aD3P1}H%XWKcM_`Nb}0(gpULD&(4Rxbj2c0k9cf}w zeX-zktvo*OZL{yd2jgSrBe##Yj|crz9!E^KjuVUa529~7ZKRRzUl)D(Usr?NeKu*( z%OGu$y9f1rqeg-!kx@K(S6TVpnHFvhVSAmd?6e=NGX}DToS6k8R833JkYUK2l*7>_ zJ{ugZQgyFaQ$>=Km6fhJbDM7td7!CMr2_PRoV0=aE1BCcW8lEx&a zH;^HNzHM@Qs)$SSaXGk94gpsuS$p~s($f;3FE`X5}ncUo`R`{?mwzy=DO@Q59 zO!O4>4KEY~t<0@j-=*&hcEA4qILW3V;Tb0c5g(G>}I=dm2Xm5E~R0ILQYvnh$emCpErm4P6Ui+YY zAOlzgIdm6|9=m6f9(NXf!ztSI^&r6X8pfP~oSavk&89J!7L9rwhPmh-{_#YMfJ~gy z@e?^VN5kjA&F`Lt_~mU(0wmnABukn()@N2DXVu|rgt_^&ES8@BW49~5A7Ic{Adw5f{4s+?(b*H+w^jkP4UOGwI`-woPcVba5vg>*7f#C?3 zrpSF~S@W{sg+z=$qw;CPmMW?);%l_L+-}k0!|v=&^NyHXCy|dn(an3uh#K?*|D!Jd zbsLTvu}b4_8-?LMoJ;cTo9*d{K5oC0FRxG8&8D?ol8dJ3vH+co5ET|o+D{+HWX!PP z;=Af_-6PsUonBL7ON|$`u8EWx;;-M)hZJ*r8koBRbZa^g!KOqtVT~gSFf_t0lY_TF za6H{}PXG`K@PvLmP6~kgJ@G3i(FX#UF%52?kREaFi2{@`(TiNLMn7vSX+3@sb-!K? zWBDtjvhPdZPJ)?W1ql-??zA-w-X^JO zM7|G0%}5HYsGB-l>H+Yuvk^kD8;>U+o7uen~t9no!H(YIxzG zy38*^G1N>(z_!$~YPU7@uz7>~UfJQ*ZB*MO$;V{`CC^k5D&D##j0$D5z*l>O?O>kU-TR?IGs~S7w8w?_I>{Zgdb-5tHLlM4yGXNmR zz%RAhz4!ByeG3U4q1d_&_C{Q0sQvgE9CHH4e|}JJ|JDJ?h`e>gszc$Rn4N$cvtM^c zm}IYd@*n&r1#IpOA3}Lwoe1^k_(-NpcM@eTqV(6;#S6?2JJ!rPUw6QnJ=e;rzGJF46E!SssL5rR zC~od8IkqBcirjA3xd&=P0O|YAA~@aXb%vT! zX8Kl&NH3B^E+}ZtyPe3W$%;pP8;v`Yo6ymB3$WwJeV^q*jiQcxcv<17V5zsj%0h-Y zrL6mvD2^5>jt2XM^$f*mkN}WE@z1+BK0e}hz7Hr`Eh3Qq!2P z`Qx&6xvYsBDB)m3gB~{&-!Zhw;7Sm-JdnjIG<$aKC3Gt=>^14BsJIK~Jo-(Pmvl|i z;oKACioyT#W#h$WoDp{@%9`&k|486LtdEYYKc%t;A2yt@t|?A@&AC8y#8(f7CEv+s zUh%?jNg3s+S&6|WvrGW)V^se#Orsq+iQZ3b)BQob;nbMLBj=>y*qGOV>Azpa{6Z-9 zjnZ4c=n)eF-BovGCgr2W>9eak1NKoyhu%leaacI`Vl|rAgqSz#u=KNu-7U}JDOB8{ zuWMJ~kmKkUWl$l%yA?SdJ*g+_QSC~2O2XG$z{*~3b zT%W_wCtZJWpN0olN|o%HUYwC_$xB0uD$Biq(tlh9s6>{$*CK?)#%${vK8?4Z%7RB< ze1RK?@tihEEMkCRNM^8%ll|){C2)1x$e)f3~~~ z^6Cmo*p4%PyL^@EhRJb9-t2lX_K>Rs1g}ib%_GFE1|_)I!NQD7klUG6J?lUQqFccC zFn4a@$vuBLylZ0|FVo3imGL#G<}|kEj5E`@-{SL)+-YZQ9HLFiFmi|G_7&|Uen%bX z{}nv{hOo-M0q)RQr`j2YTUJ%V4ER)lDQ07)Qk`MtjCQ*8#qo%SQNslC6DIR{s&x0H zYXQa5KP?O*NXgQD|1L=4dTQUcXXwJ0glVHrJ83Ej3}LQOYIbs9a>Tju``DPzdseHx z5IAEIHMDQh^?YYs|GhF;$$akbw-ik|1rslaPmA|u?{Bl`K|kQSEe$<89-l+$t^E%8 zgnUY+-t|3Zki8$PS2?I5b29FCO1iv3%%>YLBA8d}Uc`eqLT`Cc`f0YDVN-s0FX>rV zfvAD>%qy`d?KfX4&*zFy6KMvT-(PxmJi4|=qrf~m*VlWLvHhFJi3@}Nf52kI3_kAl z9BR$`j#8_k+->A}r$DhwPpz>1=D^1BfuzH3V&@V|-5i7(SU@cvEkBwV&?y+$7?PM3BuSGGMZ%yt#z5?I@6_&O1a{WQLM<0) z;B3V0*j3LYDNehP~S8pq9eBz|E`8;lnyO!hY6Q}nk1aKl8 zQ{!`N?a&7XXxgt24!K?uWB}&XfGB*_=y)88*W33CvJ3?i_fnDz-yzDD)4-e2QES81 zPgp_1Osii*2NL^gh`q48yk8%NExtYO7ffvp(ld!#hItLd`XmmbZ<*ObC$UaO-$*%!Qkkzf@AQ{>f zJ@~vO6Y7>76E>Qne}4?q&;1NZZsO6=>K1cywcU3lmJc&xdogZomr;_t{jJJjVBO6C zNZ%k`|G^^B9zWS`mjw6LG0OjKDxlzThMBl;q)u9H>iKHgA$O?FA={56JL_uu!}p{l zo@PMe(4hw@%@9`e1X^z5oB5O!cBc{U$9-2HP5`d+LB07LA`mRw3l!|qMYk#lqy`kfj(pEB`+y| z(owpTI@U-tcr7k*YcC8=T<2|4@bUrL0nBeZcjs>)u#7$$G2;ieyXil!+mb%o_*aBc zip$4glH2ZV_MvqSYKA*;vz{}a;6s|*$cdKB)fxV~GQja}Ad+p;x#oOcu5yC5^5AkX zPkHa#-IzFSk$dq^M8{uCP9u}f6`gM0*4RmG^`0g}3o(ytAMLViPcXyqLtSr%e$jSN zVmIqAD5ekZpAddCZNC2v0zYDtz7>(zE@nS`zne6-uT)_DYnf2H4nxH6;~k>M{`HGY zO?UqR+rc*bPJF+&?T0Z0J>_07%%4uYAE=XVRf}^Z1lK!}5a2bmx!C>Bboce&z&eO{ z8Owvarx85nQ)Gh9$G<4M%pZ^X+-|!%@aB2etw7o>)-w^n@+XUq-ENW%RquN z_^?R3k5_7;V0z|d<<|~67c@Sl&&_{@Kj>a}OFjr~77@YoO?*61kV!~%uXYt1+2|t} z5^CA`-Ytte{#EJ$fKOr&kFO8yiD$4eiK&R??xz2-fH#^w z>3cYTv2TY<+L5J{5Y<0oa0DSzx|V`$~Tel zg|hUb||Jv6$b$vba;ytsUH(b}x)>_q4VJ4Pu%Ne7-*ANeh1#ksVGx_>`R& z-cKQJindp;t!3Mdq-g-weR-_Wn$-gUo^9Nh?fmcBcuZe^*2J4AhDYwLyBK|!j(Zze zhlwQiUo>#~WZ!dn4z#M51Aq3_$f(x!ZNWz#=L*sG4-gZ57 z%5TSB&v%A`sQ;4H-QjXlTx91HAAhq~M$GkTYNA71SH!ZzIK z7m(=^mz2WG2kTV0vxD&nSTBNgGebT*hlZq}*+_(ii3ynsuyR&+HqC=4+Rz%fDTD5b z(Xm~!vd;*acsBJY>a<1wUkjinqY4lt0qbBBN2v;Fow1OYT4IgXVSz7Nf*xObt2>@3 zDb4=@@2v^&EGJv?*qlV_NpOwEbnH0~%4Y~HI&0Yx^-$sP{6^S=pY%KCQ_#`hMCn8v z*RwF1g8U9foVB)EaXO??iRl%E8fRu7%7q_zPX3_- z8DR`oZURYm*mKLl!{Nb-I4cKVXa|gB6i}^b*z9YB9Jl+sM!?OY=|RE)yiXGn2!iZpQc)}LtfRouPT0rRbt3HI zKNJ{xI_;lgj!0^!P$1-s#TaWkT~e+z(M@I4{+1w-kth`j#b5-{1IllP!q&3g%y@ZE zUti|yW~#M9VBkJ{xrKvl8V3(7Jlt@ex*+s{*WPbo<|&5d|2b#5aj)+afZzzC2;kTF$7TH5?`u#ZW=a$^Ofb87U33Jm=|i<9?~mCod#j95NBl z!PcF91%Hrd2e=(`&0npLlF$C+``qf11?%qB!y4m5nh~tsA@jtE7O~GIa{J*1#nZ?N z`nY&ygmUDneJ28FD9EvUdpF~ylbDw&PJ~k8spWw)!;Fc3TWvFQ_&1h&qKU7t+Jm=k ztSYTYi2|cVhj<#O@x-0dgB!cRs*C^S0S;8#`GdweDMC8(CJj4P%cK$YbcMWoUx}JI zms_6oU_$V(hL-U3pYF0(-61L(Wa6mu*$xh?>7OEfgt^W-7-lGOT`%^8Uj^bMN!FTw zPA%(oAv+MKVEF`z<=~|_bDi4`DjN6_VRTAo@h%21#x$~lr=?$AZ${3NdvE2nB`59& zRh87)jE$F-yle^$~zz!jYJb~}hx>(r`x=qXk~NoGdqRJ;E3)|IW(|)grHhaI;EN~86U?P)K zcp5HT!t{vbc5g48BGMXNqFG!fzh8j-lK;o?BI8j*6W8KyYns8>f3-6yqlTaW!fqBx$p{TD#=G)9dZM z`{851Vnh9Qe6K|pqyLg3=zRh+wX35@4GRc^Dy=B%wG@0JXQy%d%wkiu$9?N zJ@Je}n8D-G(&mSnz5ea#Vxmn)Nmn13rpk24`)!B65KlvQMoW&?iHVU(_>BR6$U6-p z_pKl1a{FPuZOfIBF%c&RLhL4U>)duFICSM0Dv2OsHb3NN{8Mzm_6+4oR7A-95jhPb zoeVsif|+@p*U3SMJYvk3^xbWe3?_T%j76+HK2?QhRmNHsMo(BW8pp9*R+dCvNK$ht zvQ!$~a=N8{?)~rMS*btZ;L~Tf1M-$H(0b(!!Hd^AUxZTf|CVwEHCg)aO6%#weYSikm%Yo%i}7uMMk}kEhfm zLnVT*ITDNnC(+tq!G zcCT_??zd|MU&7cD`*tyGb4Op7CfU@1=tV~@vm75yh|19eZ&z8!T(?(b)Ol-!*Ay4` zz5Mno9Y&l9$*!=T9rhz5Lc&e0k4rFu!4r4&F=J|=co}OB2i}v=#6W(Dx<#S5CuMo{ z0e19Mfz7SfQs1$}aVS;F%^?yLJ%^uvLOr|LE9Qet&pB~J5!q&L_B{g9V; z4&8i6u^GHM8i%gg5*N2u6q6D$Cf3+!I4FP&r8i+*7O(f}TU}3rvQ#3wrNo!M!6*8} zK_A~Dxe8K;ZRy&|r+06-2{|Q|^f-(b*xb#yiuJeBa+(p(k7nHog!gFCW`yi_qd~g? zy1Q$Yc8$ z!@?dTsg=sZA^;nel;=Zsh~YjfmO-5AvJro)AGJ6|%xuArTk)0)@>%=%FKY0@3FO&? zl=#_QDEjR9eQ^dJL{lHH%`z&ylCbB$&2a>uhu@qPh^C@{MPg97;(YP>hTkz@7C6A) zvButw>K~=w^M1fbeYJ<;7dlhtB)$t@TF!BDdE`Yhc*ZqRDV0V+I_%E;n=k`~E<`oF zIMDl{ead(^iEv3KYF#GcHUlBeX{wW8+k6yHd)8bcW`cZm%Jk@*U|>2PMy$XTyx&8w zGkGZjB)Wa;O3xcayshMJa090sY5AQBzFUg{FMs=68w)#fe?Dt;wEXxn+GyfOh-z;* zSO5!lA00s>Cz(u-z59EB@T+^V!5f>R^;^ixAuRudQ+`5DyRB`aG}Ks7zSN9w!p~M9 z8~r(~k|D&eCg4nXWxK5a(Li<8Zz$?q9GvS~ZSE{?0@Xjs7#NsUB>{IQu-AIa9n|pG zu%{Y<_p<2TP7ei2xZIv}p^fJJ*5w|1wJA0Kyp|afKClI`#jzD(^R))Y(Fw@61}FCz z)X;fQOf=zsPRV0lcQ-C^YO9dVn<4d4Rm~vj;RFP1g;vG5yL^xVzQJ4af-dixV`-xb zSMO~n9v}O*VRQVRTwWjN-(<)yy~!fbK|PmQIF>Pu>NgI4#n?8i*dZFu*KFSJ-HCTS zj7W|DXd-}rjqf4P>&OtX$o!AlthTgDY|~d>vjvT$@e^BG?1fVk9W!pLR2E~TIt)tl zcgl8+C@2k{6x5sg{Eeb4Zt9hFqiN>H2JYCP87tv#l3?be+_(1Sn|$H7XS3N~uYNxs zRVM>wY)KU4BPB8!&MrOEt&G?Ff3QDVo2KkI|B;Q z%YN4r`n@JR5k_x1$O=QFq>vJ5xDPSAi(PL})wel; zv2ewxrvA+5U?u6+@K>gw7Z;}-hy^@@KPjv;vSZP zCGHRr#jRf@f^H2Fq*pC@>22`wL~I~!&-Rl$$QS}BLYt_8LoCc}f$o*ajEheqlC^cv z++GIv&`6R2yCtSe%lSd}0e=s{&DzyfpvlIlqo}m`Ars8AGfb!uiWAx%Xoy-5jIbQv z$n*0;9Ba#(@NH$d%o9lNQ%HPvFy1o`Jq%rdTpm!J>I}v)@cC4r52(RS9vC zB_$1TeL%@;XhQ)wj#Zm^I;yUF;>v#s4kRPAx9g)O_HtbDdh0<&&P|lhBsf{L%sO9Q z7Ygrs9HM63xnf$q+j6&`k@4K%{th}z!})RyEw)@%wbW6CHi5*!?NJOtq}g^^#{7!G zfX#NTkE}jwI2!VMJ{lYVk}>ypL#vQz7{{kZysi)oebLvFGi7$l0`_V?~EPg6c?;g)3L)3q{ z_k7zS7ULWebQPg5CIg7&QRIy!{0Tl(i}s|x+?x~X%LLDcST^Ym+w?&>Uv2i9X@8&1 z?egw_@_<@$8w;w{nKg85qHxNC>z=Vf1WT$oUXM~1(V`Y3Fk<_BUha)#-_9*A{&Z z?-!W*6`6BgNJ_a&n4ue*Z*58{$zjJFMN16@(nT}|GFeu9F(mvC4CHk*461b1%P|B@ zW0BNMpP)$j-kI#Z;6OdG7DQBUn1pEtKv)2jeeB;u=NDpEKgZ9cz+nZk!$YT1hF!-h z&CcOBA512g08{KJ>$VspAC74!ZK`c*2u$j!FLf>r_C3eG0n|%+%%q!)J9=T^>FIKC zIq3k-g<)}HPGtkp_(O^o#|Uy%P3z|%uzXQmxg%8a4*&mx<<}vXD!BTv2BPf85&D-D zKL>|$$(v$)%$DrhRR+A5V^3i~{4dLPibLgI%f^=yg z=%Tf5mTV16=(Qbn;GBaepeJu8c|RW}E=vU)`Q2BV~ zbI$+we%engd*9DIGuK>m&CIsva_D^`Y>07F=xUvf>N}iX&HZ%2+^gB%SH_;3RU4NJ z)o@X-3q)@H2D-G-_1AM2Phe5+#w~dl%{%HH<>5?JgVJa9lz@6qZ(0~moZ6Onxxlf= zL2E)nVx3zeDnyfSLSMYSi)E85IKQL{_g_@tvCQEkRR&ys{iK`_%}(|+`DwAhYz24v z&%#KO7f$L}SUHDHccZF2H%qzCrYk|u)%+0R)e-QW+|2%SWeW5pJ=>xtdFx$yPi zj_XtvZ;Tg7Bnj^Wc-gIn=BNhCqvhowa4V{MI9ai2L7B*=i(*|l|MT<3?dwa^Of3N{ zEi5L~!BEAJhcahHeR$TR2CjhV-r?%Lu@ZA#lg-?k6~#Y5x(FH?4N*gHG$w-V;D+=| z8gza1?1I=VS=p{IvW^ey+i_u*1rHotQg`8A$YF#ss^`OxPXt8GyhB2=quf7AjMQd& zVeRr&8-yl=guM|rMXC7*z=(DK>i;vUk1xMb$EW@8Gvlokbe_A!ZEVR=tGh+A&nBaL zvag~e2j|^PZ8G=bwUALrq1KH*4-?nB}Xc}#vcoMI_}%PD4MZ_t~qAHi;#-D z=ri%zFX;wze0eD5B#OPXkN>?U-ofoep9>0h0?r>K%J6wAsiR91vfFtEkd;cLPGZs9 zjs!m>c!L5hFsU0;EHw}Ykl^19R2cGx?U{O`Ybo`Qto!?`ug23iVy~nuGM7k>GBBem z2Iom`z-VC(ZhZyAnDd{Hhh*&uuDDE0;raK7;)YS}x_19Hna@ruy|g&o?@gpX{9Q-+rlv4|dU~%W zRnnj>9JtFoVDgfe(NsC=hGVFvjdH_GHTsUZ>EqtPt!M}h4oGd z{VR2CvrjSF0VQ*_)BJ{*%62GY;v`k?>EURp)4NfmKdXoB1^)4d2{$grqPy>$Hl?(+ z%gH^fWlUCr7E;~cJtEK{`J%b=MazJ*)Zj$kz?mFCT<)_(4U%XxKV8MZH2+0XEoC*e zrcPJf>qJ`O&>AA|qxkB%XN~qjS!ho8gHqpr;$2qj2ekw;z~4K!HzI0rPKpIIB`#*SY|us81{3Z>bHhL0N3X`20RAOuC6r@}j0qZ`)Wk zbUhrV7PkNHkGYLc1J_yud=m>Y=DIuXKlCf)vC`S%&|f2z6#HV1gczSY420Mi`c3KcT21PQ&>V~A{aHDP)UvDt& zZU$25^(i$ei22<%FG7Mk4VP;yjCJj@>bsRH#I!Gocma##k5}GBU;oG#eIgbbN*gWZ z=`Ty!D&O-DB=~aPanb3q?m;5{bkbR9yfa@!$tf#~a+AxJnNtl}r!ZF(g58E^v}T9* z{X5F!dv7eE>+8|V?=<-8y`|Nb`}t3X?Qq55V2}uxxGOM!cgOA5P<(VVi6J9xn8j8m zi3udIFmY$S^iMz+x9*3oV1|F|ic`swNXE*gaNboXu(|cz9 zHhG>7V-L4KllLT<%o`V6{>FMp3WRz_m5)9hVHg64>F6{)8N{0zQIu5->T+|=#{LA? zC5e|EXdco3{`=Y(F!5CF8vJH@6cGzWE2kTY*D2@iI|Cg#tT@p2x%OR+I5H`N<@Uo+ zdE_oqT~CxkUiQY7kd~IoBLkCqi&jcHu5OC80lIB7*fOW~yVRCcnE>~()CDT+7e)X1KNxb7Oj*$7OWIGn~$#`ZW`E%cO@ zx8fod^rbGVG3b~>)aT>gRO!OzA?Lb9c!ZD#git~EXZW9rz94IXIc>}=oOK`p z6+;KQ@U|Fh(MR`Zz7IU+Dr5vQFl{+j`BLdwXi5RixT*?(j_@@>`h_UQ+xI12A}GH1 z^+k^16$G{AguYKyiS!FR=zGhR`2G_*On_gfV)85F_z$1f#!d?VSBlq?1piYXa|&RI zVZLUfKM0D_CloiC#XtG*Ds(KXwT3@9`%5SH*0=AC9%Q#Y(<&k5LdP`2G;ET*IH5ng z=3Bs5LIEM&G`#K0*X>}&*pJT7CmYCk$n6nrc9gxU>0Nuh^4xi3yC3<7)VhdO0V~KKw*}2q-vG539g`k;9y?iwB}sFu zsqRJv*^$(RBJ%u+K8xGWFnDx1hf5yrS~;RB*psf=*kIjis)ZFrbBi33e(Zv4RkX6H zVJr+YgVjj2v$CcC%!CewmL0Q zQwEZ>@G?qJIH~pAUbn`NFibh|I+&!N*Ix}S7gJ8RpCMmz|KjP$;HJ#~c+v6qH^7T( z)89Q0(6GFC=1yK`ot3C3ywidA>)AQYbf@=5w4Gx5qYGCcUBGtu=0n)yATtLPf0H~? z-U?|@<;UBb#fh^!rYPpbO{cQdiT9gXOBtz3(B3mV91;+B@}{^-$^pIg)x(mkPVGlX|9XKx*|TiSlI>z|O9?~WL@1i>F+DEOjf zbMIm6#Q$a5Q`p+Vuy@k~xmr7|pIZJYFwOVx8~I?9@(?I#f9)e&7s^z1!JqxDW=Bgu zrE4@87V;e2NP)T;5EcukFW>ChuF_vp8Qtks4)D?Aj@j_3%7*%|%KIn9M(ak68OT{A zf>lN`x>1KO7RVpTBa0f1Lq3TeFMRmNV$TW10%=X(j?L-{n~!bVuIQnr(1-MuO7Bg&7$o#OM265 zui2K}ftP$d=!<9KOpO0i^z&UjfI`_^^_f2fffRB=hzPH$?zY+9<3|VE;XAVr3yP8! zDGOO>eQ~YFL(+3*Zn}2_ITG;d65x=H$#lYtwoJy@7aSm<+%`X9rE#Jq@%T352R7JFC+x0L^ zWwO5y2U>Cai|%=Ml0DnQPds6giUg7hqjcf?3cI}C`51;@!q(}Hn923_#aB77&!Y6n zV_f`i8%MhlhPo{-XQ_lls!u4&4!5Jk)pF0 zJJtfgU)N~Z0zF$$gby)sY^;f~*VEakBBWlQ=XGq(sn8>vi~*5`jAb}RV^Vonc3MM9YmkYWmltAIg0S&oi*?7hZqEKC!f$F zIcXdRu{)eP!G}S1AR?O$*ZSXLwQsmCEVZ8^F#&BjVz6LY?+M zC4v>+EZ?i#t%@|f?fcVl-F6?Ab`&G#Qe@vR5UG;8dbo|pqvH}rt@M$FSxL~X-ip{R zDa{ZiKKN*}*;YYxRwh3J;u685lwq*5hI; zl~1RHBR}F-@!4>UkzMg-cD?Ifed%{9H=TgPJ2x*SR~)};8=MjKmJxykIU+xQtsWBE z9!nDPY?1rMgxkiFI%VXuttGaSj~b<-=f4rxjDFbs6Ajqit~r=1QKmU$GOLdbD_U|B zTg2D0t_ykLC)$3J%1@63YvRnm3y#JktuwKrQ1Mn>_9zG#{r0<*8MH3y{pSAu8S`jj zX<@dD>EQWsi(_5)ITn3+!-jI%P@~$7Af5*6Rj$9-gT5)R``b72)Ad#x{cAB}Y7ygy zatTE|?WpYn?HR{!rm!laQTKoZaXO1zf~4aC!DVYj4g?*}YF0j57`1JnF|1NLoo2J;x@46bV#ftqMw%0DGTf13*Do^ILSTaz$G>N0Vh~Bs*H08w&&~_nw>|!L>aX|?O z+bQF)oZnf+2~jqEB)q+T#%rj7k`~Q)MyC6|d-eaH7C?aT%2{Z4W)E1>2&F*!{%BbH z`MU7gmEa1EX!rX47unArW)e9eF#UaW;utWeapL?=Bd z_Q3|=ZEZ6Mc)^^;v|1K<4bJ}WUZrG<-Im4h<&Y&Fue0x-B);H&g875zKy=n9@rYhy z5}p2flJyq8KKdNyDgO0^Nq+mVd->KW|I#HTef0g(Pen+t@Ag^F`Z_?VaroXVb-7vI zt8koly(_!8^vLtGTl=#SJWz~Me&{N!*zPWI*d!b5=`RfQtH)3?y=eBpYv>_Mv*<5j!KrCT2NX;QiGzc)FO= zRQ}iJmzkWg{Ln75U6>5ZqRteZ3zAm8K8Hl50E+GgioEmtauA2v-yssj__5yrFuo?K z;PIxY1m$S8$u!~`d+PXhk)3;<&wN~a^TXyR?{7mngplN+@1ltNpQ7E!C-`pazmDk2 zDbZ#*;07JokLc`K&*!Mu%INs1{Tj~uqsF(eNG&0=F8GNQ$aFItRITgk~2*v$rtHf##f1(FQx{Bpy$vK?$mn-{D5K zQRL&W^z=ryrU~A;p4;!yp~a)AK8pPH$zkSuSU9-6+va#dmB*Lbl)%eO@Ik#!>)!kI z*0uNI@%(7opQm0{sm>R&$ReSg&2Yhpjx$sR+=NIr$C`Ltt z{pfg5I^r(_Y+k;KWvP^a8y4y{Q5>oDf)uxxsec%kbMIX9L(mb_{Ks~WpHGV1`udmW z$9*EgymK*}62fy&m$qwG@#|3k{$!0;2#i0Lz;TBEn6{Esp7!`M!Rwc9_3%}+_H>NY zcSFi3rkp)2m9u~AJQOZ-;MUv#YR(a`gAl;u~|(6q=(uWX!1w)cB6NXts~2J z)}Kh%?_T1$xP%01NA7#_(FO3fnFaf+rqWzzKC~L0^@X1zP=>=i{oH%OmU!Mh<<^J2 zhoySj7^&T8^uKi9?Rglq!mLofcrWUay9BFf^vzXgtm$a-N#g3H6Ay3WHqVF13^2I8 zYBYlq;xfB9XN2;$cHSEoJ5e$iN{GG>nX8U6KJN7DA>X@=wj=dG@t1|pg6KxO*QXuK z^VCz(V4$SOygQ~U9_J^s?Roj*i|?h6nG7wnM6krgXgAUQ>opqM&?8c~JCOr>{m9^V zZL$drsn36}dL^7k$Wu~BE2jQc8*N_xtUDi?C=4IIN^*t(!RtIc{}s`sYliMNSOlKRp zt>bQznxe0bulk9tAWEf>c7mPP_{S%~-#;UJpT>3Wwj}&W{9p$bnhH^z(yg@O*^+V0 zn_G`oMzR%7I?>_Jb^qpfHBh|nO{{D4SK1tfzfgX;?DRMz0H}SlyNgyVv=B{`48%B) z@blAn!1fl9GGyMn{u4uX7-{lL$zluo1X3pij*yQ4uSmo=ZmoYrQ8QZw^%DUuJ45*D z@~3Y`6HHcI@Ehlvq!MymoGH)zeA(~htiOAMbMv~V184WF1U*?Rv?2dV4(x*q_@r*m z3O&|iVZ+~WaUF~#Cfm3i%?Y)wV*I13jjP88nF%qhoIN2lc?Y}o0>`#}3gq3Gh;ca? zw=OG9l}4Geu+Wxa;S3(M?SuZb_uX}$7N@DZZq|#-9M4m~*3AQgFUY+T0k!_8 z3U@b+9EFV2p@4p%L(rHiu%Aabu5gpx4uS9n zCfv_efrx+19hN7#mlGn&MUJwPhN}ymML$Kr$C>!eL@uFgjyN)7{>|dkZV#pS+u+kq z#E~geNlvVOjxUe=U)(pyQXo5h7Oeq$Hm1k$U<&}WY?5hs8?Ck2u-N~u9*cae>u5l` zU9BhJczys`7Dc3+`Ji(2-rxiE7?ewsQ8!^qBvNXNs1v9A7gPlr&J0+j5MRRlGYje( zB#0-BhUm@Drh`Shk-z~4&duz>j~JvwB;guGUnw!+ofum9<~RF9ZrR5kjc`~CgOVfh zJ9gkGDU)AnyWJt_B0d|JkLSk}FKFvtfA)ZNl#G*Z{dTS8_~}WqT>RpJeTiJEs!Exw zo!vyn#2GdN8xXn-}1{Bnl zh0bo|$D7IT#;J6j!wihxkGpc{B&3_J2{{yx+V@8E(4<_Q`L}`QhFYvX@*`)z&7Mz+ znxyQsV90&;az3TYX$W3?&?$`sQ3Q&>mVQ#I8GNnzwdp;B#c3r(@pDhs_(bw zDOYUPq(#f;KspVQ7-&hM>jS>zeCUZGBLd-c?Uxs<6VgCL?VPq~4^xz8ndDn&$t!2^!Mni+)o6q3k z>eYn&!QJUZs=3xiL!)&>^Zf$s=&>4g!*MWVfLhQ1OhGV0ENG7NRBk<8{1NeP_|`ut z+Mojxx~_;IfA%>WkHY^7W~IkNM7~>TOOE5rO+1dIRbaE+##EbLx%FtuM61mP1;%q^ z%@OFwzg_hwkyYxCH(QLirH#_$3;`<0M4{eCOEUoy4;!6{`FpyeLr7FuA!v9~E=ke2 z_zE!EIj6&|ujiL{(-hC(S~5X!q&C1b1F(*ebZT;R$@a(guT|soNKDbDo$-{5EwJxN zJo$)(#62s$Z}LA0+X;#6ttdG4*5N}xZg2WxkfJ%n_(}BPq-i?Zf7oQ6FyHryir3L3 z{3DQJp<#^u9y!I_sE{c5Y6%MsF_2#2M+pKMZd;;sV>`c5ao(%G?JuYeq5bYKEbdNv zw?g5E_4?4g$HloL#fu|na0=@1M*R1LomLiOM8h3_u1_bKbfw*{a*N?+r6)x7c zGInhrzNCMj$?tSp3vJkv_PspFXFf~|kcd$Kr^|X4bgzMJJz1;xrZ*dFl>#<->QV0E zg(RsAXs3SO?QG}$&9KPcA+(Y`!FA)p^u&s5E>|M|3;}bds8$dXk(tfmj4d6aqz=go zi+=iT>hNJH;-lCz4{5Y9R*Z(KxwE2pn#yVb*LP}h7qQD#_`53#(U4B3F%x&PsIpJ8 zMOvgzxvRofu0hlgff0c$P_fV|A!|YVi^Y3i<>wBdI463&D>35#e3cGNSZbw=#OW{O zoN6)~yCa>%#}&UjTW#}SCr^DySG#N~BNRSuyO%<{Qrmbcar<$=RmNp=cy~EALLn`u zw3!r#o`TbL8n`~d;s1!5V<&-qN+T{u_xF-sfcr>YebQmK!xSl*8| z>d7retam?rPKU)>fo0gW6e-hY8qkqtN*n}w2AE3so9#NIAM2zduAMi=G?4 zdFDR=TzfN2XsF~hF?Z#bCs*IO5E~~g?+G5!q4}EJqkEKI+^k!%bc*RJ}>;#jUOTJ;n{Yb1-IfBuOVMy z#&5N(8lU}G6`1b5bRo?;{I%V(x(o#d?CYZn<|%NJ>VJMjrm8b$V;ps}T3zB^@%iiI zyA_PN{nq0sbkQNEH9a7CkKMxNvNWa(Z5NrjFEiSp{&d)Jp~Y*v$i%oa=G&Pd5$5Ve$yr^@w<)HXq@VL`Zxf>ZU z9R|1uhMdoTgQfzNq3tTaoqwx|=+ZxC78Erh-L84VUYKA&{&ZTj8cGTVX)+dh>bi(Z z2?FK(tj(sqLVHIhAXsl$QFtPKN56&cjs`QrsEcIIer<2##JpYWAknWx_Rhr!g3>@@ z3u{VoFprjb{yq!l-@1|Z&9iG|uKd}9MIe*XFiVmuuh`J`R(2uni?Bf}Hlzu zMl2UPi;+89`KN^A$V9y0ubYjvbl#$d2Se=`2nm%d^phMxbGqk%UR$iE?TEiA&o11w zcEAdA9XWfb%W|X#nPOjv zNs!{S`?V!zdD5vF_|3+3E`D@JpIIogs3JwFe@Pr=8T$z$k3^!M)AShUeufa^#0@@0TS)_Z}K0`jk|hd1*0x zSZ{A+;=}CvLT{RJWl*JFo=60QNBl1uf*7+hs+O5fZ1zXnKAYDwSm3w$j*WzBMp)YF zhCjr{E*Rzar4NJwe8)(~xGSLG0G~D--vp?f|7-}Q?Cn!^yb~In-a$;(FniTk7bT{{34_jh-)-{QIn?O zB%D4fCn3W*Ei&P`rePJ4q1a$@109O$L(=UyGy$$PIeT`2n*a;E;7B?iB`90mu*Cjv z^a(+(dM<5V>JTSKD^NG2Bt)QAy_x(BkOCn)JOZ4lX+Z6E;R3*FM7>s1xJOpB_V`JA)qkTwgx)m@|e* zaw>tBwz5eYsj$8Zo~iTp*_n^%tIO$o4>Phijf`2s_OS`J{P{kseF!T$a}PpcD6`_pH7fqqX6+X`GwL+HDb+I&F8 z>ly{j`jgkxDPiB6rUw9ijcIYlmMHD?EsCJ7!G(+aw|`G$hr9_3>pz?vO!IsfP65?$ zz$Mv*YQ`=L!wkm(Gdl`4%Qm&^$+^rImHBp?psY%U#%v5aevS3QbwVu z6iL!58=&8p^;pi54HK&L*&##Qozai=c}&zV>^8-opzZZl6D<$Ko-Nz}U0$~i1C=SuHSPE^9;T0DBZQ`aaL9zuc&?|e)=G+#4`!9T55S02ZR zPY98G#KQ(eMoit-1nyMhFdtYvSK4I4lcbw_|87tY)#F0CVIhWLpQqh$n;hsD3@7?T zOIW?k4g34HwMfN?hUyf?$IxYgt1!v`zbpB7^S{#QTFXY{nb^&WnQP0>$5JI8t^C}d z0`Fu3Y-R$7=DnUh$;};^gQ>Dyy#r< z*`-!ChsNdi%VAuehUaz&jl&8VY9yUNK$ZfgiJ_i2&UpY+5}G6TuVh>(H{$rtD!m@9 z`jp389eQT_mR42y)O}_20$W*)M(DaOCLgxhsuIyVsDxS|8Gc{x)2IY52-t%yLM;5m~}JV2zx$VwvX_ z(L`_R``Eo#db#ifleN|IA#Izcqu1mDCgxycM>ry|sCk1nTM5*v+U`f~C(NhSC%KaOGbA=uYH zU`w?#LI6X~xt%A>SvL8fhqrhqO#}MZ6GeqP69@vNxNSt1bd#)KN=P;1Gh^W7Wh}9g zJx7=XQ{Px!n@aE$+nXz)rrk`aVM->sx;Sx;(tV8N$;mL011hjz!x`yc>5(c&?lje! z*q*)W{p?EX+4@;s)xwTiB0X~Mop3Yd^Sl}6Jnn&#g8lWWa(9`Y%l_ZWMy+`g_^FQE=%)wEM_zn{m z`kFPe4=tix5asTGDJ6Kyzc7NkkyGCI@9aJEQ8Ny*v`WS9^mqp%tusN^Bk*sQzv?Y}R5sl9|{cDmi=rjiY!_V1(xFLJV4W2)P@H+G<$C*N7E zi#R#TZ!Xj|L;6{KMDgH)(hy+yJ|yokM@jm0hD_z5#pQxXeqmP`C0~)m4hLA3S+@O3 z7LzxqrTJEgUFVaH;icZ3e)ay)CUoJbVS@z>6@)pn(BD5qRlic*0*JN0;qGf6`Nh?SF!#Zg#LFFDwu-IO0% zk(d*A;FwggQ{VY{y673ed~4HF-Z7F&(8Hw1lo?84VWnR~pPjt-spt$AP}5TUe_a zNJEe+`9mOA(3-xrfNZxIBn^_RMf_Dww@@ECki`f0z+`U=ya|BlR{%ra`HwW(8nPN5 z@YuuNnTXh`{o_i|-AqU?|7ov2^B!on=8gOjhWRjlpCkCWHChKBwg@RT-a^pV4=BR` z&4P&L7`;1#?8; z)TQ!{%5ALhHn)Ku3tRa@VlVa}VDc3qp?0N>WdG0P`l@LnluMz15kZZ_b6$`z7Mz>g zK<#Ync^@Gem##E>%ti{hK~fBN%TC$d7LgU=0pJzfKf*WY%F+c6T#5NV%fAd+meVwv zDsE!*2-D7k9naWChtGt+WYz~Y>_*lj$(Ve@dFS?#dP>d6q^{058TCf-(=}Gt0np>1 zGtOWzhNb|SAD4g2k0dGe{9F!AYjiRBjBJqhgFiDO${B3U=hm@}5#stRZrHOy{mVaj z${8d&QrcG2g>O9(0Q-d!E8|%#^gagc9P>waGQ9?mo%NMWL4K)jX7e% z@MVJduW|M4tGJHYv^xcR&@M?6Ql_?RejLbJF>@b9m9jMh*~EoA8oWPUfVN;CSQJzY zAtWBF=AM$>m45a%T@)JVbO-ULT$h)>)L6#=X~~ z!iE_ADvHAEnVGA>Oiw=MCh zh+r-Lt?3YMFQnJnxVk4?;uuNWC93$1J6A(c=Mjzp=-;ADP{RW!44C5bQho?;%HRFG6|1P>cm+_7s0I54%uMDza+jQN+jOy#pB zwQEI{T}@p^a`Le`qY#q@B>}Qz%ac+}iSXXeG;VUG2F$2w?>sh$`pOnC*RiH;vXJET_wT?hOQnl4pTP^E=r21vv36OL*5O^IHxQlHaHPupoWu8JIM(D@W80v^t}dwm7R7$S3&ppy?txQuNK=kLuc9p z*3=8SEE}b{!c|OqxPghB&dteNiY!C(>`@Ec$unORxZ(d#3*arLX{27)oN4X`8y*A( zTa2f$5|*~D&~0s;Gh&d&ZO!Om_b9Q6$^yn6ea8Cxe^xFbcx3%1i7R1A(7ze#KtDT` zOxdc$_4y~3Nqns8Au4IzO+1&Z&7VzYeUU6t>yX;g0 zF0RUFHTb#qZmd`Zwjwlz&p2`p2;9?7G`3DV=JmAx0;0+Qr0J-#cS}wz_!6uNr=M1? z5^Tj4)gvBN%)q$B@iV52BAu9@rOqNZhtkAYX5$l%Dp?VjDoW+IY?mKvn814EmaC1! zJmUj^Y3k6ndw>0>1IXF0s5B~HJ_SzSg{UqQ*ajJDFd}sD9{EEZ*Ng27=&c|9wjJ6} z*C>#+UJlb;$gU=cm~g;bsVJgUbFyy7i(k*(L5Z}|`JDxq8iNQ9R*1>z74P@y#nak@ z@p5!DCKA)WP3@AQu{bVZ8S>bM;pJtrgvWKH(CPf2I^3hRih(6p_4!J9dB(Whq#w)q zJ*(_g8gNHxjQmFb z9H5F*tzQS|`8=uF<(w)57bGKqw#MQ_M%2$Jlx-+Mri^NNZo=^9?16j9Hi=OMZ!y3L zd-JsFlo^)bu~FSY)|zW0y2|;a2fiVACA`?>YIZ%yoypx2QyuzUU>^v&;bR3i&$$@|wxDbSn`H8N}Q-;PS+!DN)0Oh9vP4=Fu$@`IxYC$-?sD>OrQsfDT?jLen6oL-zs z8QriXWE%WQt9cK6!eVt+B;jmoq=)=igO+1%KmQth-ZPJ!*Zu8t_%mFZw^EA40h!Mj zVJZk+z;G-ZBSf+pnO{`YM>B*H#BOl$)bXf~xx59K!%~rq3|p;sI$|)yW?CnwR}ouP zWx_QW! zdlPX|-mKU2Pa?&nRJ32PnkG_~)X|xYeMo(fwF2N1pQH~+zBVZDFNB5GAPf_@_p5!Vh;twoOrT$w%FAAp{jNgK3UErHJDyNaHF2wjt)8Dg8Vss_NSFhEz&WXhcXL zwi1T2D;8wejnUby&QM=LVjj5Br^5dxkj}ZqO&KHK(kt~X;dF_Nk%=q zMF+)6eZG_zgLvJ;ePD@T=34=>OFIy|3Bs_v-4pp&!B3)5VX@NVXZ5>5vr~O`dzzgX z`xH1o=UFV0w8j)@pis~d6lBf~d+#NwBz3q^SaoaMZ9;GIhLy!dthmA6#aFbRD8m;& zE>ajWVDLNB|F3uQwT%Dpr6+N6~UmQHlYQWG}^; zS_N#1cHy^#g3BylvW`btfMqjM8<@gB;s@5r2%^O*?zb^B!)40uCfUV@Q%mF*G>9s} zxr%D`1{QQ;?w^zv=;}x32@?$5!G)vG_ea^Y0ct-q(cw{R6x<`+F^0-^k41Z2l$ z)C0RMM@d2zK&w?wws8MEJ+Ez>lQ|b1!E_*{YaYzp-}xOaUgg5sat&F1SFKRAF$Aq- zwgle6$P5`cN{MK20-cGaQ4>kyn8znuupa`OzX(z`N_+9$P8Wj~jL$HVs zt*Wa0PhF00Gs6ZbCKwn%MLd=dGC+d^nCcJ;OoD*0FD|49xu8*p9`@1ziwFrUc+`+z zEIOSy1_fq@1(=ELMn*QoO1@%&A~;EqQ7#2{+L3cGoQBel0riW8#SbUPe|Pl5c@;XD z!WSkD5+R$CQ;*q$DV9<%h6DKrKo2rpr|8?CjFdeo!fe$~ugY}##x{|4z0_*3avhK~ zm>YcqGs}l87sc3<6DbLc3P8gQJ2-+Rr)qQ{Civb#kDqNEW1dFUncaYv%SP#YYE*kz z0OPh%+RW$OxkK9fWQ-~a6Hde~1(pe~n3yqvjNdBQv6f5kqYj171D4TaVn$z24si|G zV7^_60q)6_k$K~X1TDa8Vh3tAaCnMBipimtseU-97dv}e6Ynwhmgw%DFZN=*nSePq zMemY9WmfN6GSw*=+5Tv~nWP~sA|y=uG0Rcz`>Dh;>TFP%4t9I`b==jckSJCg%_ra| z7j&<9_GDc$qNve8)~43CI`?xBSOBp#I(RirRsVN^l#G+if0-ZvJiziV@)8zRT1tOt z#Cmsrim53`Hj5`C3@as=qPv}8kZ9qTB&hYORs_n&h1-}^nmUqBy8b+laFGKi27BQV z7h8!e*)N4W4`bciTA~{xTQrtHjdOaNNeQt$eNA1bSooq^(%u|TYXP7~9`tIi-HdBM z{;q@cQ3>pg7|@Kz(_2=RVQwue-kQh-v|QFi)I~VNbe71GMxhE`VMeumQq$JWgSavd z4XH@l5NPT$`pon3Ik$aEwe(b6(?n7T@K7JtY&B)?emllVgk16K?Ax0GE8ieXXIa^G zO1;DroiWMAROm4{>H_I1EY*cvIQNLi@C}-#@&;KM;q`d7NFhkC9F|GV8*!_GF&(w@ zoqK^X3&F1fs?Y^m(S&kAo8$dOXuIef~?1WIixahz=eQ5ObF%l(*9n=!~mzh zck22_Y-r+4bH*X@L!V(8Nu56vUQl}to6Ca^fYQm3GxPJoU{kU_nu_X=8 z#%o(*O0G%)?+MGsXlTxT#L|zkccKSc<}o@0vX~c>b?IU0{B3su<46U_)lF&EvVn) z{shbM+KyuXf3H`HjVY;wJ-jr9IkLC4PS5z{tqE57IaR^9B{eYI#S7&yl8akfPUXanjZp6K(s6Jpd>0vWW>DjWV}LvZc-9b zXrvX~U?`v67u&AU?!+|2VDS+No)i-jbQD=TpCk04$AC7W*sBf3jc}ZxY%33dM z3rJ&#|Ho1TR@a|(K@0PZ{*9~K&-ab4AnSQ$PHYG6UEP@Bo#_L`eiN8ns!<>_RXZT{b)# zAoZ7{y4~StvG1_XhtHw|c3)M%W)&~OxGVEemM3Oo+h;bbI(7I@~ymd|2W;bT0vL&76y=CP%}L-1G_+h z9&byx+<>6270WoBFJ9`M0qB1Nkn=+lwUD1>KE1j3p=Av(MMED$v9CmT776qf&?@gs zCwbpkT#W<-$~><2K_S5s6T$N?GQu=YECVE0*)>U55g|b`xX;=6%tcZI%7LF* z{^ddd&4J>@jv;qXilC4b67*eKcRbA`Xr3BZJ_#;@dgyDuDykwU&li(qm=61zU0vZo z8zg8(+m-cbQ38ezQjfFYaXtbyA_r~C=S5AgdH||Iq^&(sU`E$?RLG?J*uU~zUu2)r z`L`Im1?z4IHhU{3S#zUTte493YZry0AxlcGc}5J5QS|2bADi4C_m;*C%sTH zG~f-h9+vvnl<^OBysf#8Ff{HnyR{BCWqACfmv#xfTXr46G}>=a5hdvp-z-}$%w+h` zQlfUo20y>HdhGp7w7$;W?-iiFO-WHc?$muWecRo3;Ix9iP{scThG*Cc_QvzbgEQ~k zr;BIgZXy15O*H;oBzR=Ij~sKG>o^!4VZfXdb^+~g9VBBds-~ufdA_t_rbd@pr~M=L z?XwFF4|Q`TzEa}-bB<1#wzd;CQ6|xO?0R>vKKi3Vpoyua%h;grPfrL!lY(ZpS(`StA}w9otfVkH%OX~WwEi(wE~S0*=Fp=` z2F8cH-Ndw`ROaOKL7X}?wZSLP1Im!l3U0ErlLH~?*%_c4EAQr_^ZRrj0|Q$V8Pnmq z^h=@|`)3v%w!e&uocLGbB@ijtwp9pCnfgi8dRh_7`+?eiYNvRZXWx2TuevQOGFoeh z)#aoSe(rm?eT0)o;9belW{4=Y33$niHF%P&h0Zm}mJ~@ZloP=|%4fBrIPc!-c$9^m zsH2xO{JWO9n8@A9C8Ywmv#lW%)91EUc8AZEnwsX;ntZ}csdQT^IH)eL^=(zCMXY(Kc)s@o`Z>Wj?gDS~BS zul+Iaj+uFMD(>6B>|&26lM4F!$)2Q}gX#j4Z6uosWS~D6l_EkuU7#vZmG08w-mhQO zSQseQ)f=APQkD*ib1jt>CYvvMAY~&n3qm9Z@}M+j$we-%UY{^fL$hFe z7wp@j+yPI4?A!Wk_>4w&hP2iH*WOouwbcdfhTv{Ric68=6n6@=P^7pNw-$Hz;7~zI zk>b#nLVyH!_m<)kT#E*G32;x}@4NrRT{kN~ot2#A%$~hx=9y<^bOWR%zpqc%Kn=Jl z*(le*GG?^F><;o4c^#8qjQiqWp|eIdac3IuJ;^h)^q22Hf+VOLSo<#ZOlF6#y&n;t z(3@}VpYR`CUgjQMF6|T!-}pkqCEdIC=&CG+dx9q)gS-~P}`t3?=tj)KINeaRD6eR-MD z@H`e>y-9Ld{N1+j*awkZIKrV-krwclt(3%fyU9^zUw(W45?3!T{AqabE0%`WM(gKj=6NA& z%&BSHyYBr?f}&+Mj?;Q(re0*nQSx@)cSxk<=pwIx*w3`{J{R=JJLAPIit-{FdwY8~ zbjT*}R{~7^VqiHtE1>AC6 zdue7$ITfA(fu$gGWk!YKb2DASQRA*%3{5o^!1b+V8Z!_8Ej$YG#UB3=24phy=f=RAKcw0yOt6z1?YhVWTT2bWWJ$#1kABdq9Pe0(mP5vnJfRO)A! zRd`8t%81GBs081Y6*4mGm=F3JH zT3)!&0C2doK~6p|MFq4I2Sm-Dr2bW<$Y24k6>jPDL0;S$GxE7eeg1Gg3n>T-BDEX& zu){AX(+ok@7ag@(TuZ=6Jj*w{DH*RW!-yO{Y5Omhns=ruz-p#jgn`YGHt|;4b8a2V z=W{3H3uad+oB<1XhSjA1mSX+Y?`Sgk%BKQibBl zV~q_NbjY`h1Xa{xsu*?8uj7*6Dlh78)P^bb??tHUSHH0oY-_5T`-Mc8l)|(YtaXJg zKO04St7M5kI5_R#7@g-GoiAS%pL~_yQ?<+0(qIeAR2-YtdP0c~!i5v##A41FPu|wE zMe*wE9B%tHV=2vHu+-8#Mst7?9qoLavV21P2;XyxWQR)^TvApRB0GDD5v2fjv7-1G zqX;g@kAX14G8rPa%`HIeL8o#m|3+tn$yhZFBQ<( zT`4rF*tt!-=80YjY7%jQ!qr`kT5~(QDfeMZ`FzW0m#^7MBO(6I-N!nvZ%=}@P+@58 z?)pi@lf-Y~Wi;TH`+ZfZ$!kfPG54T8+1U#17w?oGHOM&ZOYx}bagB>CnwgjgpIzE# zm}w0LI*~ymJR*O}J;Ujt(kDs&_3F=`$JBdvVkAv|lkQgZks(uulJQF8J>w^Hz+BNU zYVuW2lGQ==9BjgbI2f2+%oO9wa~KMpt@ULJ=yS$^aOszCb(qrA2W%&^8ymAFOWtsm zGZLsewew}A$d_FV6}IULQvmZO9O*I8X~1abIaEjZqNfEh-Tyf+1{U=(+~hCIKl3~y z8`#qGPvTc;3H}iw#IbO!{}e-Df#3bS$T*`>BECSj`SYJQXc;5T;vjE5-m-;RVo5HL z+FO0x&6u3a-HIPI`n5^Fem6no+co8JC{Vx5_SU3D_c|w?9|v&Twt4p|{j_;qzi~Uc zGj%QL=5XI$6Vk}N+qO$&_wD0}D7fQ<2oplD9RvUgqyz8Rx>jrRjKrU;oJ0BYb-=&A z1Z|>WKq74(_#1F5P3tf3QI!zHc6{|cr1PR&V31H#NF-|;O|MW zC99Wkb$T1XuD@mus{XC=P0fduI-a@Xk5b0$b~IBdKDWa3EuaWX0$)em-2d4O4>r$H z=cWWrm_9WB0=nqQz|4P!_IDlXPo)$P-EuN=xF^3qWSfB+-#v;qg z5>9UPR_u(tqPOtLc&+?eeD_^|-JXrr)J%sh&D|uvh1X0D+Lb)&z$Fg#hY>v0xBI>8 zt_(6V7Clt+DHH-NsOm=7u!6kjQDLAJpS>LTLSHQ*H^^@@1h6aKHTXR#yT|V+A&R%t z?V(Pk9pj&yT&1lFOS@$htGWwr4 &94tycL{b@vGmZ6CWB^*lXaaWW5c~v_sq*=k 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 GjQBsdzf!;e literal 0 HcmV?d00001 diff --git a/version.svg b/version.svg index 5e016d156..18ace1a5c 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: Version +Version: 6.3.3200Version6.3.3200 From f03c8d3556f57c37781fcfaef5448e6580be33e4 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 11 Sep 2024 22:28:16 +0100 Subject: [PATCH 103/142] website: og:description added for landing page and language tour --- gen/root/README.inc.md | 5 +++-- gen/root/tour.inc.md | 4 +++- gen/vuepress/public/og-murex-v3.png | Bin 221288 -> 212158 bytes 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index 4c5a36253..556fbb3f1 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -1,4 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }} +meta: + - property: "og:description" + content: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." home: true icon: home heroImage: murex-logo-shell.svg?v={{ env "COMMITHASHSHORT" }} @@ -20,8 +23,6 @@ actions: - text: " Install" icon: download link: install/ - - highlights: - header: A Modern shell for the rest of us description: Murex carries tons of unique features. Some highlights include... diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 6a15c4311..ce25da2ff 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }} {{ if env "DOCGEN_TARGET=ignore-prefix" }} ### {{ end }}icon: plane-departure - +meta: + - property: "og:description" + content: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." --- {{ end }}

Language Tour

diff --git a/gen/vuepress/public/og-murex-v3.png b/gen/vuepress/public/og-murex-v3.png index c9b9b7a8b044e803d95cbe00e064f17b49b6db81..ebd9dde95f2d28c336eebdae9f384d7a59a28f80 100644 GIT binary patch literal 212158 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 literal 221288 zcmeFYcTki~(=UAO5?yjea*!-JXAlG>gJj7$ExY6(VUa8n6c7-}B2jWqyMTZq2#5s9 zL6T&UoW9ljzMuDb>zw*dy;bM@_gt36?o3}jJ-_Mh>FJ)0)zMNVfY3ky03dkyKv@p} zu+SgD2wZIRpYFr4JoKLrf%?YYde(kSa8Hr)R~I}_xU6u2MrE~aB@JdlvzHS!k`a2~ER;geKVh@-3^rlhYIzP~N= zLdEwJ&dg#3HJ2hezwz+{VflEKw~*8dl_A~9iF>+LqcKY&6nU`Xpg)h_9-Ajm_^xO8zQsB;oT7j=gkXEK+fTJ5LmCmc`l zqS!sG%?uMZU5()d002ceD=FzbR8sn9KImDz34S5_pj&~i$MSJc<+B)iW%8%`9IeGM zw(swea7UQt8Q>(VBXb`ryWKqk?9Me)-yi6rJI-c;;4xd zF7|ikmUrkEDpS*48t#J(YMHabdz$;6#e2?54k)7oYH3L4cyJKug)QOoDRIu)+ zSTWx#Q+XD9XS+}4QYpdmPMSsq3$-MrP88(Re)vu2uKVE3x3`((&q3S#4OfEL-do_K zQfMgSwC@!rt_+5e>8ND|s5a-VQKsoB?)o$~Uq$BYHXO4ZAY8k}?m+^1?#9px;zaoT z9lih@&%3g@UG&)F9C%w?_JIHn$9=xW^<;K=HtT)+)suH4^F(RUp7r97r@Ya67wC-E zFJny&DO(tn&)N=VW6$Rgg`*V@0A%F-;nudU_TEf3_Kwc(vMjr;NERk%J6RSZQB46& zxRSk-^MgQ7`$vIV`nG|twvu)%@^TOve2b7%U^ z)7l2+<1Nd=g6?PfM?NTAQ}bW!-M#)s0gVU0zcrj+kWYXg3g!RzH@v*>`=XirEztk= z4KIDPneyw|d%=7>ZSC*-+PizR{yPiRhnhP7;_!P)j?Pf{pGl#?`)`BU+5U?T?&In9 zhsMs9-`>q0ie~DCmQV1%(R({P{1;gNO}5`Xf2Q;Af}n@{7yti8{m^ahJD9Droz$O?0uuHDb`rM2y!OK4lDs1J)?&OiHWEU-qP7yk!b0|< z5|Y-!|HkT}yO+1MyRH3iR%qsY&S*Z8!q&p}_7Z};b|SXcydsi#zNcE8LgGpZvQUTZ&r3_Rw81yw!#kfBD@YlwnDrjLL!2^Hnw(Rydn|~ zw)Vmz_QFCoHh)o2j4xpRmNA*X?YjRM0G~(VF87wRW`U zhr2ue>G-`aQs~*Bk+uGAdQu4I7_J(=t!(eW*EWdd({bu>EZcVg3*;#vA zD_eWpqel}E5|I*+loAxw7nG0^5tI^@;1Lj%68JZIn4Pmj!2gN*xAic|{I%u}oW0QF z2mERJ%cLIJd;In7udi;-e{6|~>5o-NS=;_K1utt~d%Hh!qIvz*W$R?^?r4v8AAjrX zKkd%{8(sLV2ttzLcD&-^!V>6Zv$x}w6cM-KMXQ0WxQMWXn6>a%R-*=VbqTeb9*U3P|$)uZZ#gJ!AggUgMuB%kcj%pve3o z_%}C$e($d~wEIGPL;ioc!@og83;h4``Fk<`Uk<^<^q)cgNBI5+uK&RGKSJPtMEoD^ z`VU|+)hd&@-i%O;7bYXjzV)xlqy;b#PaKg#yZycv#(SNW1xItQ-|Z8{+^;LIJFRmdw{J)@(f&BONhnAh12 z{`q8=VpJH9M){vdKkZH?BIfU>I7AS*!}9l2YKsrV{?qf58bjfqj(n+JAnBiu;)MUa z@((coLF_*Y^S536|JY06B)Bx#U#0DR?-gK>Gf;`Wb7CYWU z!F`FiKMrUb&zE=Uw~{5A635Wg@PDXfncj!xjR0PF5Jt(&d)z(Tyxc=RqV6+<0%9gI zGvd>n@GacoG3Khea*ro~u7TB)I8;H=B$OjRn&X`#rATJjACT9t&38`(z56hw^Z@xI zWyq}gO9G|)?C-#4&9_m9%asprZOwDQPZ5YDR6hiM_WB-i`fkx9)KCb^U>;Jrj`!5? z9>v%5&JI=OY3&%C3kLK=#*q6DDI!CGToD1W5^6y24laVWG5GlmZ^gN*GlfL3S#I@6 zP)Ex($vRNaGK40Urw8(qFIkx&}z*CqA zFtKTh%uogU)kP|)Q*d5iSzYm$*;8=y)3B{L&%+L4%%;XE)fz>@a4^HBD%ofGrh zuz+*;*~In9$PFl#pG@}_C|7Vg;?*n4Ut1gZy}Z;nOl~npTv6Rm4gFM!mo89cMx2fh z>aHXsA`2K zH!)7p0zi4L-Kn^*A3pyZ>FCXg${On!-_FTN;@;kD*x#xQdYLXHkEWQ*sFUtkY ziGK%j)nQ@FIaUK>p#@d{n1<(bPiGD>YF~*kfzf9H{*9kxn+Y31v3enA5qhQSe?8+h z{H89k7~($e>AzBl>?w@fUBp8kOs{WjVAxS#W>|OXx!~GAmFLnpsz~yX;EaqS-7Ev$ z#zvd-*m8S#?~AqK_Za$^OVKc_ALBTz5zf7{-h%$mMhk4+YVt@mW}f6B}fdd?E?Dat(cIdA78> z`0>Rf-P9a%L<)@_gcfjlfRjWs+(1LDr=Xz3KDXhB`v9%FISy1y#6`?JNl*d)gA(sc zx-{X7Ag2Ld&Ns-d?%Hl77UBvAGl4;{>jC2n9=o+$Fq;+I7Mw=vmAmM=d+j z$(%VoL;F_)It&zKPlhP;YQnO60RD^lZAlWLNV{lo5q0zk{GTig9 z08F)RB7g!=gVBL|Hv8LmA5|ObM|$_aUV#vJ8|mJC=YUU({5==*=T47*9!bZcM{lEV+TI;g;)7K53`Xb)m;$;W)z#v2X9+Op4%2)UoHsI6$d~wK`&(O&Y)-YTsCtG!z712=9`ie~u@~*| zbGn<+%{vHG?Zj(yo3%A~oQew;3QExsT|nK*jX(EUTb=3};ovNh{3V?H*(X|KW8W=gZpCCx@>%bCFIwi_%DSRf-hN5r!22;Lz*w&4I#a+Ti3sPk$!i>NU0eM z<(k~nW(wk;zzh_+HU`}T53dH4U$e602iCo&CX|+WH{58HS8E=^c|G^8cWGA?jte($ zH98eX<_bzs8^wr;Lon4UGa>Jqb*;3C(D6m7j75O&$FE;WEduv@p2+Q%Xon^&GLG;~ zPESYQ99v%V*a;D2%2g&kMh$Mlx{m6ya0Egk@WM~!7A{y`;|bsn3|poe<3}8#;{#n; z)6W#4AuB3?L0>nm5m_iq?D1v0275@FwyQEvx88PU#-k?x;N?9SFV0L;VF8w64FQ;U z5Pa5kp5yZ~9pjUDM645)05HQ$#czSwg;eA*GUcI#BJiKR*mWCdWVO+ysSlMN82y93MJ&!7*Lk3RCQ*Gv>V4p%hi z^UM{kdaaI$_P*EIB3G~{1!-NKPEhE z({%Xv#rqM01+{<>gt$M6#vc7H2CsQHvhR^ zVc&WBV4~S4jQ8t8G8H5~F-Bm%CEjCWdK*O!z6VlEFT&-`jf@)4cQL}$@?B7q_FCy^ z)V(IZmMjc4Iz3Yf^^%>%hmD8aho-wtXinAC1;2zgn>;2X*{%z+$!^tGQ*eDmup5Z_ zR@c=rcU~&`kpryFh3FLmS@nauW`^{EgM70xGa~bycgYxT+8qF zt#y8XM7T<&>$|@DeYC^}uaB6-fRqRDL!BM2iC=}VPb0KLevZ0v=5xRJWVbgefAL*2 zr&h!d>+|Qh-;Nd|NPF_^Mg%kCAYr8FhT#%DANJGWJuP&}&dXC-D; z67|j-wYZw^7M^TYX%q-i9$ds>TAS0yMgYFlr2ORZ<(rb*@t&G^>_D{Vu z{{$@_TW~3W^ylw+n}c~iCIa;TO}gEf)fvwfF(Z8wDUl#|nB@{T^5%g2ZW?o;WhI}DN;UBBKu zqXgfo7sGoayIf@*>og%4IpyHx<@IsJGgEG@Bm9Tp>^Vp#sLWeh4YLh7S=^h0)3MOCqbQ7ZtYyeDrPeF}9605)8Fq1(u9e zPmsnlpY8GZwa#}sSH;PMMH}Ikkg1n3F6y2Mt@;orH%yw$CGpXB4nNBv!$;4eWzyPn zK7L?aJ7~k5$nPX!BpcnYo}T7`JB8XrI%1h2W1Z?ZHE2%PO>p$UWo11VGRfF-$Nmtm zXr<6trxWxBI_=Mls2AbKfseKLAnVNuT&9wjT-j_U`UHpqfoiPc2# zr2xs=Mpwe4Gi2`{!-k6xmBSArn8anrY1d&b`Tf^KEk_VFSN^6>A zmu>rvRu7A7MDPta-}1&5i=BmBdh~y}J2y)a3Uz7d0Hf~NSTt(9yY!-=SxUSOjAv&^ zMm`ST_n7|91wU}|@Sl)>Td=qb{uA?NiVkhKCALm*;hcU*-tZ~AkG642K5)(8&dlxE zUl+kRgw-!%O26%sIf`9%7^UBnYlLuRE=nWFfCQLfggO_A5lRxQCGo=`&Oe5|%Nk{4 zMCBr&m|{|XN8^t9M9<3SGD<};o)JR zkHpEDWG~1npeG{N8cvNJtGCW6lk)YN2VfpNVG>D+na=mNPH{24V{cCT>eq%{Q`T|E z&CaY~&|YVNhK7cfk3E*FYZ?5F2u&u<$k(q=gD;MktNR$b!!U4|3l+rh>}W6zjYJM2 z?H)&MJBLK;HSqd0Eoe+u)K9-s)^C-OHz9Gn-rfPL?4~EKQHjbhKA3oz$SV2PuK*Be z7WinI(D#7%(~2mc*-^oXORY(msum?uP)fW~P?nw%ha*vH{b!64vi->&xxjJ74q$8h z1^!J;aVdI#bLj5w&J4Nv_@cn=PCob8*QsYwZWxf2SMGSQ)d`1@Bxn>Pz*SNZa1&&y zYG7vVW0(u{89F|M8mi)dMv0kr`V?hA>iiA5^75G9NT1MQ<6sXQrwTh?pDkPl1Z`%{ zf9MFl*z2*pA=S!~iuZ=ByWzZgbzere0eFj!W#5X06}&=3L{TDAx-ehFN^hFtRxFju zgFqC6^cyXF7XFKLbAg+Knu*LnQ_#lmumDR$RCKXKI~amIjmuGGPgZm-Lo5S$>S%K_ zc;_Rc{Fr;xSFgK)6~SA_Ml#~d0|B7+lYu$0=&&OY(*b6ZxksI0P!wuWFPm=t#!(QvWlf~8M#%t1yxx+0ho zk~j+$KG+dw$a{GRGhIC?#tq=Tz|Z4rD#(RR9YhhmC`N*gN<93$W7+UG7 zm{|vcnvZ>u3odrF{`>EJjbP`-rm^!u(mwZctE*2XCoZ;QaMDp1v8s=TA=E9jOgT6S z46kM;l=a8Z(Sg`wW8=wR7u(zPzqM|BZmjui5ZMYwI`uq;h9mv6TXUVVrKPEu0Jo}s zXyK|89_*o`gTo&3n*ZhyBQo?M+T)!T+#H7XO~a74eNJ1X?#K|q&4o=`)_QJU2apZ2 zaD|8%*?9Ua`17@@HGIAr_Vuo);?F}z;y2gxSGT@gEi_*c-aJbv3j)nw_D<|)Id%}B z@TGtLB!-(qr-sJh!KlLlxYWE{{xY9gz!dfuwN3OH!Bb8l|2&U;uakn&H6XrIn!A*) z0-Kk2zwa>aNSG+sNMz0WELZj8%TxrOjA7XO1K!TB!Rm+C&P zq9iD>|H;$n%|;CTc&sK_@+!gD;!?CD|B?wF3Qr5-se2yf_KM)Xevj$vX|b!2g_XSe z+jC{xYRE9sVc(CiI_|Rf*N;roOOXPY&sRa^Tk{lOjvJer5TO^a8~*b5@1fc_--z}G z8jkadyh<)7)F7mN_p`PwAKor6=QlNlnLy7?cw=Z7 zCT+VPA~VcWU1_v5#mjgYtCMu`I;NC98h{ma$<8f#={bv$>ZX3aleWvFrTopc_O7J-Y`FhM4;2W=xw)ho9^tEM zgADM4g@zwUA_@RiFqb`sT%TKVvJ*bDhEC~QKAJ9?D}q*uh%roO-+fYo@`{S3#GBK^ zsxp4Nw*Z@vpI%9T2 zmQ@|ADPCbONVgxjyaF_v1x|dU(YZ)&Ld0vy86xZ)sAX_@$p-<*roVorL+It$8>l`;p>xwBDgYvE&d}!h3K51H#uC~9*aSC zW#NlIVq|~m=lCm!jwVuFA6u*i-#PNr>v!{hcQP}JrzB6-Q@K}E$AT7Z7^U#R+i=T5 z5Hy^R!tf%}7Livlw!&?manyx3Wb5u8(id{A&fgJpxHgXi(5)vY>2>>rJ$;Y;ONL+~ zkq3OmRBlxp=0evQes7xP}7IFrRT?TiFdU0`rJWY>xQYT{ZC^+< zoj?;}Rf+)9Dwi?ITz_b>9#c-;F|+L0S)PrPd$%Ssen3;O3^9V8xxIlV@!xuNi7M~6 z7)gkDj*(~wq^p6nY+~GGBdip4f_OEH#0j6g+-0j+@ds5HUWLmUlH#Rj$yImM)Q0M) zuDvEkB|FkLF~GOS&!0^PnrubI{G_VXQ&v8?Kgo>V;>=v%ooi=WBYk5n3nz%WpK}8s z{TAs3^se$`yPp0=cK&izTtHS9?Gh6hJr@FL+!Zs4hYiEfhsh^29YrL{iv~8ht{Dq3 z@n~@7Ga78uyE5S=B_;G%S=nog&1)Svz~rdC)G?M(_fePcx4odlyqMA&rSSLD8J5!nfqU|2st za`nI1Zsa~_oe$lW#Z*KGL+fs7x@?7+#>PGRAnsPwGm}^;Nuu1Z``n%QSH*hco;0xb zUF#4*xph-guP!dEVg$~Q?t{;Di#Cx|;D=FGg<%h*NC3*2DHtr3^OSV|^F5P6&HcXA zivG7x4rLa;9!V&|Tu3DXtNf!~uznF0uh-YsYA#G#;}qC}Rw>7KN4s(89wY$l`P_Zz zs^GfZ9jX$YMVB%})~5CcubS_}FmsAbzMQLVV+mWB%KVd)_s{A_wzlZdOCNn4Wvswd zZc(d*xZ1OPOhCu9~VR_cz??0emxedPofC41G>3 zu*&!%{T6&}-SxE4O>f- zFX55=QO7JeFfn@#NdVLGa5`*!|$^8A;66 z;c#;^vuASd{jZ0=;ZcEOqi(<*HDz2JYkK$?`Vj{8Vc%T;xeHK6hpj=;R878uk<3J5 zXrKhF2hzaWmKWRALv)#R)L$C-e5!(0=YyIQky+;9kuQ9rBx4_gX)<%&4`Tc+gr@i7 zqMmN>%8+`&**KE;#W5?h8{(ZFe`(*dy(8DqsXnPb={ASVl8Q>D_ibydYvO?xfFsvB zV1_lab=vpTXs^E;xLp;4b?&T!zBN1>#K$6xt}2~1{&+7U%alq!;E75}am1G}-sG?%^H8Cvn-Atn5A%`ZFsB9tKmB z5%==2*PPTVz;Dd#>^(gEqJRqvkMx)LY@56Q`Qryba<|%TV5j5ke&oph>5|uaE~jY; z4d5xcurup#NiWMeGQvJAzg|$)Ddp0aSaqHlDRjAk1Ue*XRPzz1D{(srfyi3tm!tOE ztRmO#V{LTZKAOAO?eZ~~NI=)BYMgeYhREIp@>Y$7>ZY@8u`u~Ei+iRU14v+ep#vG22_2#HwJ^R_yodt{gRE88CO(NUmR5W~w#!|(x6FvFF6$fXKd9Mo za*TMNq+ucNV|L^it%0++w^4jflv!7TSiG znSr~vqhw^>x$MwAjDluCJp>j56)Ns|eJRuf6T}k3?M1Jf=Ar$cWC(2|;=BIMGH#!>X_M$*;u^tVKz_0}UIT zcfWT)dCc3Bor=C7F9PMf(V@1z6i-9)`u5JHAv*IcC3kaXslvX!@PP#9N(uC~YOSeY z5dzu(w2VQVniMZsF;j-orM1$%K}-SyUGMDO4`&S5P2%&Hw+@=?&7nxMIej?9`Kdg| z8jcMP5;vuhg$kYHH{*jUCp3*y&@_5hu6ufm?Iq+yb(WA-nyr zRa9GJx=BADx!joD&7Rj=wjcwcH!r$A%urK|GRgP`N(*luC~uL6E2oy_$uXo(glZRO z0!u|@IkP1^m{iuB)NhCT?)wj&*6gfR4m_}FQ)Nwa{+Jj58zH(qHJ0hWa<*#|;QVgu z#8PI>YW})!FAjNbFVZNY=yZ`#n85La1PHQLQ^XRvgZVb5?Bp%RN4PZxmsRM4nTM1s z7%yC}#P^n|vb!&5^v}K=c@Z8n2Gb$;&d_I8$!aJY{T|M&n6G<@P1j<6%P-{^BDsC$ z$~NvFc>aeRH!<3wtF;n78cV&1r)#bcZb@`(Fr9UjP`(&ZVoIXXyMsOufN|W zyyoXze9>)WSy5`MSt5a{-*BKUO`~>;7J#%$)t9swN)cukFeOd&yk2^Bw_IlrajnRh zm|Z&eSb}Rgi66h@rFGKo?)Ci<4~^Vpx(unnMqjXkd5| z^I-TBiHhNYw_&3kdT`l=UWH3+7uPb>foITomc&w3j-qn?iD@r;v8*ETLPn*0Jo4h$ z(vA8$BQqKB+colpdKSt1vgirTk^DVeqo=r4)F9x|tf)7!f)TZj zDCxg!2&G2c%(HV<2%wt*^e2v7(hQ6uw7S^XJo^i^p)6E`imDdyrzog?95BP zxP=fozQ4qvOI@tFVrjfcUjdYpDIp3V3Z;@Oh67^&c2t?)J;4lWo{VxpgYvV!5``5z z?|A*@Hw|cn$R=39gbv`-hchR=`d~v9d2d9o*-1;kO;c;a7ckTZHT85iHcMXnJ7ei9 zW>^~Uw~i}j%zoetl>-f|;bpXRBq%NG=)WUQ2(1%FoG*OK>nj=oEzUr=f9 z_H^o?9eG9RP*lXQjtoAmzlq2T^B^k@K&-u%omlPcaSBgzFZWm(+RSKl)5>cg@s9W~9oPp)r8F}p8$2gy%V?c5#SDcS>j0;uqFkt5acuGPA6gnB=5?J9sC(l2)2dUZe zn$cmRSbbe0T^pAo38J(uf@$#7 zvB+gW6BK(gxeKp9WylV-JvQ8nlU`9I_UjObfTDMv=ic-xxlgNW+j@Mu-^n{CHbiyO z4sE%EX-E8^?t-0zLqJ3X6Oee)&t-ZwUE7TaXEMPmF5p%$(8r=SLP3ovtR&>Kt7O}D zLvNmpO&|(GTM3j%_)bCeSM>KgEl2J#(Oz!r4^}Jv(zPv6c$7co;+8K}1|%yX3~XM? za#Zg{SyF%&&K0aYOl*0Lt~et3`0B!wR!4@3Z!~$zQXk)vko@K&sLM4r&6M$UVrDF$q>##fCZe#+M}fD=`JdSX;kNujshs~BgG5dN_K)#q^BFE zTRvCnoU;h)xo>zwq8n@l7%N>bu6Pk$2?xPQU~LC?Ar((IH#slkzzP?8!OC7(*lK-a zzV=EAVQI*Vy)65o%s%bw#a-RKXN~U{USom9rW*2zhY4|_xCueuKe3e(4qYu=0EiA* zQgiyRgc##u!xOmAN`XO_hW(!nJxW&9gGz|*H}<~1lo*XLBgY~}-xaS5oIb^zhE&5T ztuv0L-N>>AJj$D~cT4T#6SSd0j%EfuW`UdTeB#FY;wGKz28wKxDm+{hT>=aFdt4+c zBJ8F6uXrT1?fg{RNbuBSHIvyDZp|_fE{v@|LzTQ-w&yV@*8^v0T%PsQRCY;+xH~QM z587enpz^LZ$yz&g>FMLRa3lf-G_*YreJ^{}9Me!UK|zVXgXr#`@+_s+ZBNHy?#U&_ z?pH(4Ow_&7;746JoaEjj-x?M&qFtk>qQY|Zx(wIX^R4|AZRTXfcWpv;zBIT^U;esi z@?BwpRA}L2Xz6pknr^VeEhfz(D4ZBH_(+`O#K-%H!L2f~!{98&`1LTN&yN{K@!gtQtdJ&>C zwW1UT){$A8Ag{wQDnrTpWrgfuat^uUQfAD4J7rxRveL-rpU=1fvLgTeH(sgI6VlVm z*k)WAn>)iHB$3E$BK+s4q5>2kJ0_tiSBabw`q zU4+3ScTQyzVoE!ky@o&l;ZB-Uf4+zMuj2{BN zy56(1>mxJdHz(?!$1eO_37*dxG7JPx5JUD~G#%_rRKGe|Xr-y( zKxYB5v{jX!nosEezyvMeurPR*JySw8H#b8&%8op?vnnZ|nI(F6XT_@Br-LYrz}zX8 zaGlNq<>Nt*06dC`$#bm{D@6NJeE_(ATapUze-#Akj%wgW}xQP9jb)= zw)a{7yo384uPw{JWDYX{bI2cy{hEyEWbCfRFF|R`C(H})!S9f2FR}!<3!s6E z9Pj4;5bfo;fsQk!;Y4ecy&hMW>LU%2iVKE~1Q4ALi$>0mErh}(+xKt` zmm{eLo}u~@B_0%_jjwAg^h!aMIW%{P`9>{+0yfyiB$Z7Br#+yUKiU5>4KoUuW`_KF z7A03;7iMX0jurYT=~$8B$d7PlZ9dz01`BABy034)7KrMy@$va)Kf;ZQ-Md2qv{+CK zfYNcjf-DOPSg(UT(^f$&LP zRIEc3$7Y&eYxRWbbx!Mnn5G_+P&ikth#p{>8%)T|PxznYM{hJQS(>Tiy>cSBd)N7S zLRs-55xvML+ntk0J=6j`=wNH(<@&};V~Y{$W?IHX93tH32|bksvRU9P`lC^3$mE3G zaY2j=6$XlCq_)UUHDu>tE0dbG1u`V86s#GUg;;}}GH491{=UhxyU`@f0Dv^sT5J90 z6Wpf14kUW`o%YH$@^aQfJH8GRk33~t3_=8ru#^(+wjEN+3`L^Ln%WZkG6=P_ftxh{ z$zgt-t}h^CGpuy{o(9is)v?gy!_d>kvOO0&-$3(&UD=$b&-Bl6HvHXI9LHRuH#?>Z zG;*2PhNoz7NXEqQ{n1rt10Rr;886i-DqGopW#CPg>D#WXJzhqt`*8^J`DMFW4<>3p zOubmbAV(Xg^RJ#6Prkc{y&6Xs24Oe`K3cF9DRio^5t_%eByKMj@K!H>-T1M^$cfM3 z^e5Mxaa3ek$oKvao@I7MUNJsL?-yR}j zxq^7*cRALs)yFP_C%QY>CzdybMxsg3SbFU3y`aDN?gtCSi#zmkaF^BYJ``zVGV_@5 z?vj6x$4M~i!khxz0Qt7N9>1_EbK@7HaD zrlYb(`-JOyKR)d*N%NW@PY0g4O_F=iV{XcH=^P z|D-BK(O9{Q@t)T=j6(W@Z-_4RqPk%$7&&%q%qZb3BHEk7&pY3Wfi#yQ#S1Hczh1+t ztVKsL;^T*oU_7OYpB;LsudyJayx;ViAQr~Jg`#I%)pq63dDDJHq|;GLv{=nI&oBZ(HF1ZrG% zwcw(}{(NhcZoQ=qA&O}j7oFQu>r+fSGm@WlnLjqz%krD+Lf5XyE=2X$yV?y8$uBc77)@QbHb{wMts~WWT3n_I+^}-_EWBBB zCWtJq8q7gfrsMF?*9DvMIncUex-z*Ka?9{A#k}Do8 zBFZvlc^KE?#276f%9FR?(D&`?b+!RDO&rGL56IU9Oq$w!_KK2t$YmCh%?17v9VS}EJuQr=!E6utBKqT2|4vpaS}n` zEp*Qdxfh96`Vebs)(J~d3h@epsUXx5w8tF4v@nY#i$qMdbzhVWg*f*$41Ok9`tp7v zA9{ENpH9gj699sS_>7k_p+~`9UIV|^!$>YIadk%8>#LxbKlfu0bwn9PUuxJQazDOg z1K=>i!W$NwZiY{Jy$SSsb26Rwm)vUh&LpR%!G1^@6iWwS}f>=z-3* z?m@kPh(KS<#;^;Nd+c?050*}wQ;&ONw70ScKy9ck`l0)kS3p*=>1-C0&a)+Ml$k|A zf$VjVi;BE{&*%1gTQymGPW6XJiE!oyCMm{)U#>T01Mu%XV&~UTr1obBB0+_wlhw4Wt#>I7oc8>i_du zGgfNTm!7rYwn>A_*4?%Eq>JycY#j72COEp}!`h!LA2zfPwsq>@O?W0xQP9V5QFiuvSxba%G}~JY4GpflCLU4yvdGG?1eI?b zy7iLYjut-S+T&=B<;CFs%j1+?pZwdMDb@#d51pTU$l|T8ke!;|hQrXBzi|QS^n1y= zZ29I*8Q(O*NiaeIRPk7Da?%uQ=2)hNfaP4aS!Q_bMY=r9fHiIOgaS3gqd#3m#?YQ& zorsqu!$AsrdM8{VJ^Jga=65*54-IVMkv0UFhlkrk?mbajLoEifNP5TgE^q1$h=70- zlIc!>C0)b)s~fXQ@!=i~x*UeSv1Z7Wl~6W@@qYP=G$m9-G-HG_3>(5%Rr9XkaAs>> zXhPP2t|g_cD{%NqEQmv)vp!3aYwsf$Q(7Ey-juC7RJ`R~RO*O&8O`!2q$?!&M(&m> zC9<~|pr#fZ#pHVb;vwkb3H_-Y+-o@TUgt4kSP;nA{QfU?)IO`0f!QO*W6=jCAMSDb z5}qtgBbMoi;f98UfQ%|FI=|N@E^ayFbo-^YfB!Z@ zP+SRc5bLhQkvU-|lrZV4DM7sCT;rXxhxUTBLd=4cXhN5pcS94Um-4#gK?>6oSfd$t zV@)-St(74Bud|u)-3l_O3xe6UT;rR^@o=p}I;uLM2LU5Ce3@H^YSDQP-9EphQr+V0 zGBNuxXFA!p^HQAo*_H@1&_9HFXA1THcF9qT2kEGMp%(ij8$()C87Z^l&k_{utAQdS zAcsIUQl5kLY6E>_78hHj>CJx)H8_3zaKWF3(;_V@M4%u?g!^7lxUvd4)Y(#CO1^t? zFp=@{i=@Z^zCVo~_}&9t>s1D_&Cu|xUAL8@8kiG1Pabs9jA-4R!WVr+?&-ghf z$Agoxp}P4?`f)Nkmz^HWk~Ap{Cb%7zb7gm#s=RFsRO@?=qJn02n%T5N-z=ZcN(LD7==jE%0k?M^Ln(o*}HLsu!`vP@aJduF){8JpZ9Nj$)4?dl8(kU;O5AAn(G2*M>$#if(P zomp>W#e1t@nHckQ_^Yc+{Sj?{eHtQ)k|rUA%}BF$5dzj}i0P^=;C^NiUUhx?oMCkh z55)Ooq5tKwhqz^UjFW9SP%apqNZ0Kcx|8O+gQdIzKk02;Xnn`JIJJnZfH639$kuYk z>`tRMZ|QqaPJS&c%U`U}&oqe6Y~M^fP0KLCDRipD6Gzb5K7wd;g%Lyl*&&G3Ad@Ql z1_b1`KFY6DRY~OwsS06EV$xmF(`POuC0l|G-_i)-9VljJ??wMk!+a+KXUhrK=|P@b zI`h&(kp|O`2eqUQkH*oLQDYTiofM0h%6|}gi!{0#%aZNFUQlP(d5BuERjw5x)ukM$ zU*Fw$o93FFVjI;XCZ1shGM;C!)+z2*aLj z1@wJmDf=mj6(E6?IWh)Aaz=WcqHAkfLnW7s2VEc^8Tpx8G^%Ln2Ql9!P0UhTT#$=> zSDt|*V5ZM6v(`<*JK}17`e3UzR|9KYB{ht88@bQrMMS?-86LcvcrbG+8BdVUZDHFb zp7!=ztkpM*$Kb;gRckBO;UqEW{OpT+Piirkv9MJ|!15KR+Z&{C^W0F*sz6Bc)UL^eFk#N0KJn?J#9E~DzTWO27D zSmC|*_tGU7R~{A{EGy0PUuz)@7+2yRj&@F}Asv~FA7=9=JoY}U0oGAz4}dVt%MS!E zl7Jv4Rt=LZGN+(l%Q+v`7l3y=AyvZD4S^VBN-(RN*rD`($dG#`5LCh(boix~colmZ zZ>u%ZnF*oNKezWxzlpA@Bwt~v=h?0viNW}6>oWE2+r5k3s(X{pu}0Ur8A+@H;%WaM zOuqQd z7I=Gw5|R_iIE{YdSeC-nIE_=)2OTmE9i z#KbdeYq6sK_kVwV$Q#U*BM;vZkT0LC?>E5I(TyWn$w4dQwl3>X#~!P;V{ew#8ZykRj^w2do&l%4kGyBDkbo!vRa8J4c844`QD5pe^vbV-g;G~k zao#g9(6tFr5B{GPAW<>%lD!%i6~z6vyjv3S9`d^y#fsEA;5LW#hGo8X1<_mRUG#{W zo~~{m>_JCFMsje9#T&3i!n75Vg@Ea60I~&_tpyhm?Bn6#VFHsE33xnkV3Lc3m6g%U z13f(DJv;#kIiM5`9lhDnpJku8h@?j*pNnd+rN631)l2?COj^}7{MjaF<~OC4G06@X z!AuX@=z9U-Xc9a1!3)AD#ylU|Tgbt-EJbAckKI=WZ6GHcpL70AYhH?K50Di1z}5q!eytmgB}@pbCzo3#O18|&4xlt z+f#q`R&8XJfN!P0AGG0rVTg`}VP@rp-_erO!KVl^<886tYSE2rWB5Y%Gta^LyeIj^h5`W|$JxKH3 zJz!Vs28Xvw9iEC}8Uy-)VOW4MgNIV^<)l*VhqIqbcYog=*ofRLE*f3|X)QLC%pnrho<#t(QU^F+;U zsMTfQA-Zr5l<%h2QY&^smO_>B_^nOBhrDw1NQY5lo?PEeZ5l)VlX(s@v-ie!bo{Fe zW@cv2$ju!Z9Yx;ozc-YZ`#W*O{m{Z5h~j^LE@NJd0P%(UhP~Y66d5p1Pf`iV zG+}t%*PtHunK_4pF;sxIEei{iNAtMKKsrZNqQ)xK%GF(6P0jW*^kO>{Yij3w{iloJ zeNU^0g#|p!krpfFJZjYt^!71FO1U#zumVIcXApRXwy(hg6M>DN@NZZk+4_&HVy#+a8wjZb#=9aZ%}ph51aPWxkicc{^4myhl!%P zHms2Zih(Pfa+lppg%WOC9v);164(V0QZyKF;lH@kJ75mrC;3Rxe%+ChmpJAc;2aNY z-wT0+RB^Up^MAR>d+7Lx9VFV4Eh_yED-{WhM!>c;L@;G)XUF6>_FUB87*IT@rO&<{ ziiY#B)sG+oJ#7+j{RiLkU~dew7(~vt$rV)@{yoN^aAXC+baRkznNHGx!)2QKcJyi% z8e+GAU9fb)UlaSL#mx0QFOb)$-{HSKC77@QT7$EnYaKZZ3=e(o zo00qNDbQmF+5;y4i*E0$Q}4V6JSBbY(SxhvMWcai=kBP@SN2yTv42Sk1s$IxkfV-> z$j+$^Gk<;-D(mMaowE=k1tpg4ka*2}CyOV$aG(vm`~4fY=ZV0$Z(`y!-~}0v z!QiJC#$uiEh?@8&w6D>a1{v-7i9ySh|L*OAN4!a`ajRo)0z;Hw^5(g?9VH4-W^o@LsQFw*`Ft zOLK&T{?_j+zqoiG7azX`gR1&&?X?@~>o3(8Up0Qnw z$S^_hetJV3A%_}L?f`=0>E+`OV153*Ex<^Tl1^E!#QTjr=VjM<>v(nge5RFk`@E)i zpkX8sX;i++(M#S<E!~5u7eMc|@Ed6) zmSR`X=lKC&o`)S&g9FGstdp4Nn_YK{0?1ft1WkNV$AsmZKYU zNha_8XJTP8kX@W~Dyqxv@n?~j8)FHCW2(TiVSVSGsJ>v}b3)KVUE-uwgEv-vy~9Cg zqq&OcW^-f;vCC2umJayf4N@Y#Y`&*fi*w6`@ev!HwW%$miQ20Q@0 zH7@2^I{jBhqSt)^E6f@f!oA~TCL_NinXccsd&+}i4Pxy&EVDai`?@$d}eEhD-<1hofoZK1IF--ED{{*A|Nr1XfKQS^C`>Ld|@W2$qM@eBh8kgz`(0 zE}(6={^YRT2#N3GD*x8jpzAIJFYnt~jOsZ}NH_>dnsf-AmzL6E2~3sJEPl1(D-p96 zTb9f^h<4{{e%_?${h{e;&L@)a4&MLJUzGm$Mab0&qdAseGf=#0JTy}B={hw z8D)g-avoBfyEw_oq5MtbZ8mBg3^X}1i%2&vgg%Xe`;&^_lR17>gixe@$a?SQrWyFS zmtOC6=Dq|osfD5M;lKe{g;{f`1J9rm7r``#FMBvTFS|?=M|Ok%nx=>UXupx~Pvu5x zWfjs*&iqD>#m9}fMlCdJc)#B;VZ-Lh*xeW_F|a_4wo5KZynI?PG;4>;Rf~IYmAMYj zjNr)hanWV9wWj^$Zk4M40hkOr`jFN7M6RA+^_oTF8*aVm&_B-pM)C^n{felRHX$d6 zBsDDtq$0|I7g`}gl*5&kMX&$C5fmTEQ39pbv-VI0)~eb@*>_2=3=hYVxGoxshasz- zOYH5X8xOzT2lagGg`OVFY;44zW5%y{gHpj@t7%foLsax>&8_IZ>l7Lk$pk@qL}0Q! zb(AK-hWN{T@3a0K#yn1`21>85+wEZP*<<_PN$1>Q8L;Wp+T&99Ppo2^NV|WT(k}3l z`|6urU_RXXQtCAUiKBV)1WpE7vxQio`@w|F#fB6^{N0}l$4Dv*n&a$)qgF~U5bC;7 z(Zy=&cXtr9-IUc0ac;ZpI~n32pOV6})6mBH&wBsG_$dC@Wx5JyBSf_iYCR)|;~zL3 z-@miIS)xe_(%c{Rd=v@Lz57OF-$Lx%Yk18P;Yqab5Z^Np(Ee|%Dp9o@Qds|%82#OG zih*jIoQ}^4q;%h9Nz7R+Gceo)n0$HJg1a~OR-3jrQ|{R=ikVqnj_RR#|I z`-ODWO1x;m8)3VX70-dsK9qZUAUq2{(RJVIsP77OY?J(TWSSfwA8)o3aohg>$i1q-#fFe8?wST z*7RUOL!-eA%`DT;>2&i*!-Qej?H4`9TT{Xpki7MuRML)_aT?T2!4|Ow`btCZ`5czO ztop`%|C-WhvTLNgKgjW^(CyvcPGm_RHb|Ld`c`9onsE3vQT$*alnG_ZHeKpY0Jy#b zIkK|2O_1I9>YCVuJrM!^`GzB0ccEbL4-2hj`A)8htBG6@2D*&gUp-$>7uMBXlzdFG zOJc96VAXV;zzbPRLSeC%f26`Z-Au5~4?sLI)(wi%0mh7@tWgW z-zlSDG2{Dj2$GR3g}-#biaHtr%b<;FMc7ihzX4YptXXcYzG685)^dftwuIXP(Hh4@ zwHO$L&wpnl6|12oUDeGtmIam~njA8GD_w>~LZ3(7<8}=B= zl`=U%we;4FUCwg1_uy%Hq=};aE)Rgf19AWWbjk2}RdFQt?sjr&mOuOMdu=qi!f=_L z`|?53N)UV50^W@+lP?n_q%mnMBUN<{VC)vVRXz*iG@4w;=$6Tx#Fb=qt6ujx`A-ve zRxY^$@qgfy@yp=>$^b|vS}ATn<>0@)@!7S(ddtXye>}3~ljP;lMRWX#e*#UVjHI7E zl5*n85Rt>NAGWd1D||y<{eS?&di%*N>#GwviriPI(=_>i>-zbc@93YTYddU#_^PQj zhcATtt#P`Lep1QI>EGfKdTP6k!iG^y0TjfsZc4Or=#-Obx{IC!*v_S?JW~zkktjFZEie` z9ZyX9*~`k6$xT$f&gMS^f(L$(yaq>`3yk{O3K&s zpMhbi%-UuLQ)HTH^ciz6(@}<2zzH9eV^=H96h-_&M~C{IUUdeulLc0tmSa~^K{t4q zRp=wkkxV~1Gb2H1)KFmbob2=AQR*yds{`Yr6^#To6RCj7hXw95 zKkoLsRV!GH_&ZEeCuQRhZC=3NAT{}B%`FiC3xgsi|MX6nJC|B^ud~H|c2*F}(9rPk zxWJw-1qt)E5?R8qbxDeTZ>sK!cV+{F=U|c+x#Gv}hXnCg!gJ`*m~9aIJ5-0|CselH zXVemnl5`;++Osv&;S9L%Tx~(aH{rrTv;dR$3OOrV3IttVQk;rm+`1IbK^Gq!UVh#5 z;$WUWyh9ED#MFnD;YD4dxn9A-4iBmL*Ym*l`yb`UeFnMRy(g8wFlojW|rp~fb-?}Q#Va8=5GP0quRPnlH|CgH& z_XS!^eb?YAuL#BP{c}Zx8v)vVWo#y4@@AT5T<~|MIWQ09NUbQy-WdJrbOkU#W9Rn- z*ZO=Ke-Y$t5Vhhlba%E|?@E(encuq>sdckF-f0{HMyCi-FQk%-%1ngVd@9tTUgxhI zuCxB5qxAt#74hp9B=GCe_}e@4#rOb{^cotxvN%Csu5Bm;jihaBb@P=i1(ZcBkd-aK zWh=TF2H6e_F94N@gfHNm(L|blTXp`4w+THzV~CB<>nHJiuIuL*^mghdOAzlt1=O2} z$tiJXN~FLAIEP!I15G9Tydb|~w>H0T@&%t5f(wYz}_o&2x zyj3@@zJXoCOI5?WzmYf_82VA+=R$0*X1Q=s#hu@OeSzHXGC0dHy+{z2(1c~ zP%j?40koK`M9VHxyanyuQaj8~trgs=|EHqTs#=VcdrIK59}Xj=2Nrl;&_=krKm(8w z9N9pH*vJLcH}tf$o!#iaIy8?;3`0z(a@bhJ-vV0f^?h*t+cwH^B%`7MAYh7T_QYQ@ zdA$lr6!}6*40T2z9WJfOB;0#!jwo7H1^AEP@;txy0GDBnm9@zI#E;*l%GWK9;pMoV z-1raXXod6$ekpv{uG35PxGBLgg!=4ti&rTy=K7xnRVK&9^SPO@Xr~~8SeIlJh?;)Y zn54KcNH4B`TfxE@XP8}T@%CGB8cS?*-i&}Dk-wYYv^Svc;CJJe%Vt=?Z26_T#&xz- zr89YQNctMUP$^m)H5T>|7W;-gnR|RNEM#HLV?M4TWz5wol32WKtryMrc%;KsB*1Di z#%Eu5t~F<~Z&qg-I}ANo{ZN=GX_CvMS(EV+hS2AM@IB}U*;U}LzYlf}o%3MsrS#zG(qzHHBxiSh=4PIy05B&tM z#?PnL;xdGYmm(1z>*V_$ZVWOKpNBf)IVm}`W}g`0T|Crf7wf6YmkabT<%EdAweBvH z+(ZY7mF4Bu{ery6pJP1*7aj)Uo-1Bh7%40c3y~#KG`5+Ip_pFhD?o&;B0NTxtb>nX zsJV{Hb-egXT<$Dqyf)pLw%9Y4@>xAkXIZ>Hm%&JOfdP2|cebDcL5}j|c^$NyLIVV3 zrYT^E%W$@Ca;p7Q+OC!YZ4v;ikmF%CT(}h+?2GQ)`B$UaJ6FHyo_UXddn>O6Tk`!i zdp$a2h68{=*`oOY7ibS~*`{-r)<5v&wb!@2k-0hZ4aT>cZYM8p-X-Q zwSr2R>B2WSo|7}%)BZ`{TTOg(*+Cl z&D>vidfF#VA0(^hSVlcquIZMPuXp4NhCKBtanJKRGccYBIOX8 zaa}^3qa`WWoitHLg3?A0CFf4CULR^>iECZIjvie5xbDaTAdNDlrt*59Q==uZu{ns3 zTiB9k0qrnp{pS?$XQi$(a~1bKalpfdw{uK}FdL+N*c{w27{I6XxBTnsmhkxl5s;NJ zf;-J8QIZN5{kl^?NVsDAr`P#ldhboXfS<=!$~kadEYBr>GSq1=;wgs zdcOjU-&VBkF(DK<01sM(GDVQra_HXJm9s1(?Scptz2`FgEnLNq+^ND^r*TFu04^p2 zye}a(V_e8#PiHtCOyw_1LVOb(#deU=Z-+#j=s7GQ@$y2@+wR@pizPHnk%z>iZ1PNn zr_Qt-!GHArL~^zfDIB}~w$<5ma|6x<-RHVg41aQGv@Fy8u!Iy_UFLC6ITXx!sV2Tw zZz>x2H1BVnDxZGFg|ixjOc6WPSmvj(>u_L46B9tDsws4z7K zxJIt{tK7GPe(}21B5$o{f0q{8&CDs{0|CD1z`uq|euN+FPY#hmtNGrH*8P-)MU(1O zrMnt`_ev@Shg2!5s_S+L3MPg}FPayTh+vu1j8a6?>IW#p_Bg!o*-u^dPON~f9BvU1 zz>}zc#yvjqoPIvAoZSr^yJRv|`Bxeg)jmJyyoA*00|_feBblxkJ28Vh1Il5qHffMJJLwfGG4{_SkO z-4oQCzC3A)Ss5U1X^qs|M`$pqz0$MbDYfrFHwRSs*TIE-A6+mf&UQ0ahu+Cj7Fby! zpr(RlN;6BjGOe+>GYShgvRD)p{&4OSUlIuc_??acWL#&fKkJ?j*cfrgzoa@B%^6EH zy?JB@V2%En9U=a;s=$yGITP#xrsH66!HOl7lJ_ITRK7&P{65 zO6OoTN*V;{d1Ws!1=`WTXt=nxm+cSM67F@l^RH+vuks8Ea-piDHvRmi-kHk8+C4iv zyjlUD1s;yqVZ8%WLIJH+5YO`#aAcuHrKQT~QiPNt{l1BsJRk+!IV>9=?(PeJN#t0} z@!KyyB=7@90fp_f&Rzb+?Bq}P5zL$W`wzMPpof0M8X10^22;^)ZKY%@62k66bzLhZ z=&d_E~1+RHvY*{ zteG!u`U5t*9?P=Q`tvDY`8m;`M51}8zx&_kIN`$yGJX10%+}z2vs3im#Mca3 zc*hs-5V1nJ2hSq0*Gh1hH^5Psy@PS^NKE=;3%c1$*0u=?3<~eB&Y;ljfi*_m)+-C@ zokIXI#DZzIsS4@sD*p}XWT6HQz{Bs#qWd?v&#s&}PTk!xGQzT1)-4~xY4#h3gC>ku z|F7~Sp}aYZI-ldpH#>tbmEd41w2jia-$6Jszf67k`4WL9l_fbF%0y z#ksTjIZtkABfKoN-4bw$N~}OQ%9W>C;>SY3fc=T1;iH2;wT{$>0~=>piJ!o#(M`4lW%|do`*mAhJ4&^YXIO8&M_zNj2 zyxk4Ci0kDrty!JZCZG8Wm1Hnn=i7moOA2!*yX3ekN_fb@J59x-TW_DG^5)=jk2>u*~-#Dv@O)})CviO5WRQ3;Bt;eWn-uFWI(EnuD)Mffci z7_-0HH{-e~ z#1K;r`laSQ*1RPYmHIq|j+wFtZWrLkah zwUxQZKjhSH&lY!&7H%P3J{EKLLk>)M>FS%oMU<7oP^1R$i;WV^^6y(r#T|G>S}c=G z(EaP;#P8p8I&%;^hck@epD5*!@s!Mp-Lywg{8&b3ni9~t$}oMF1w3r5RFJ$b%G`E_ zWn}>ct}nkS-ZLX8PVKm=w$j8JBsuXDx6xl{s&=)-Xj6kb2miLLZxAfuj=O zCP$q5PxkC?szJSv`}#=~tV3%uYLE1R?*Rq+KUU`5vEkrK^li|wzOfFgb4o-mcw?Gx z2?djl0T(Bsal3eVK75d5dk`-D%u>$cBu#yzmc|0QbX+esQ9e!b{-ub?by@ml-P^U& z;ktO3`b5uU`nYs<^gCpUr*HIS8i*o%3pIu@bQ{tUW$Q{Q&@tn@zoCTpC+=(*rJHl!T?)V!$hWq_ykPgT7B{%^;5J*TstIDc)I)1C(h_h5A$ zyab_(uWK~ji+5fejAGr&WMLI@E`Gb=l*j#of>>x{-gkrg^_F+BUyXO6+VKS%7(H9q zGkQZa2k@BuNG;UcNH-ou4#OWNvi@W9?k+x9%?esSV4@`wcD>ut5$KBThqKUMA$i+iMVq6}zluuwm#syK4X)ED3bg*8=e0#BN9y2Il2T_ip z2FR&`WwybrG&J1ywDaB-2~WkCdc*ysR=St$xaiC1q2C8Vq@)s?@*E(I26cfP^AP0sZ6 zYVL4tLPo)?byzn`?^TKFEwAfcSs?3BcqY7X4F%Ktp5yz^d;>FQ8NsLd5Oms|YvgYM zr;7<&_KQJCsgz+L4iPRAAOwdW+Js4tHe&U zg8Wd<+MgM1`8;Pp%_}q@V0Z2y>}AA?D?9RHYqQiiB!EPG@*yzO4S}=FL@M6M$Kp5N zlG<#55veBq1kudqW`gtA9a&_m#Bo;xmv|&o+Ay9SM;2tlGjZ5R%eWMp&KLqd-<(+I z5)k-C;`H#uxJXJyP7mhGo+~i6(LJQL_@bvkJq7SsKU6`v^r-p2cfu(IthF&rBasM^ zm?CoPVA;5*rI5+;H@^iKPO=fL%*y~OrvGe5w*_+LeNwT1B{bV?{rQP4 zl~ExY-zLJX;+9F;Kur;~3hCSb)(aVt8_JI9$^3yCgK6r9e;gi5-Tj>Kv&NEu%#`JJ zOu4;51!X$+;zwT(58TqmtVY#8zXlH(=t9@Ld45TbVCa1yNxCa;j9Ofpljb(&=WCGP zv0Kc;G0_m9=+!{6y3xapLBP=9)Z#fLXizJ8Ma4TlDOmt&5fY{$8{W%gT+C~QlmdIA z3|ff95#eUqs(LlPk;l{ivooo$>Yy!s!MCIwNLNxJdNk;))=Eu3JJ z;pW&`A)gmd|B6hldMS0|kqWc+ZCi+_65fj1Wwcl6Z?DYP3y(7}> z&+B)7LAflclly!#wVw@_)4k7i#o5Vd|1$!YR@5#R4oK zc`JGfDRZeNJ}SVLRpf0e^nSYC=FVPFSv&LnR$(F6(-R%$jl!;+wQNvD^$CmM&by!e zDTJ9}NP~N1V~Zu6{^Cj#)3mhvj@-vNFnQX$e(qCZuOR^sk^1 zZri6=#dkC`&IaN%3kcb*SEdX_ZlJ*fpS{Xj*)1(}Tsyo<&dx9mrssq7o-p=+qw&iC zB5ubF49oFmEQ{oopzd-L}xvoG8Z8r$dV%_#EdGwOq5+&b-`vnB(H znYgt@9l@SxK3S*5>YK z1@_NLMGYL=2WcgECn4bg4xt}K?j)Nu`#VcqrU@elgL#Ic?K|wfhqA-n#A$h z0t`}bOHI_1tbJufc#mKSsPKNuSh~ylVz1CPa9mlAPliS=)MctfSV$Pv zFT26Q|6Z6?w**`*Qj6^Ap;{t&itaBf zrmr;yzU*JbA1zLO5hsA(0&H*Atd!bIyHdw0XMrA4s8KM-`_FgC?G8zi!$QUBRS*&0 zsZXLX`LidWnpj|!oOxxX+G5sbR;ZmDrVtqsYiGb^nMuF1-AG3r{aFnWa#JU8%5(|1 zU0m<7#rY4(0079&NUhnge|-|vsu)DiV8Idg@Zh$b0GNwBl*XH8NV$InlhnQuBO)PL zPYPTdp3dxO*_SB|^3cY8O61fceOs)p68Q?K3=X9Q2u|a0q)?_E&Kma0faCzL9Y6*O+4p)RsB9ioM5LQMZisx zCR5IfUV@$bnv0lG*5~Fj%auYcb)^3uvMqQV_nCy}-F? zSW%`nN_JRerr*E)OV{as`o#p$?|KOxKy9);N&UrPO{#X)!AS-=f*L3?u3d#*m|kp% znxG4KcgV@=QB{HvR=RnSV;S=rS=1`Ag~}BFD6`UY@6$Kcwx7>l?@yI?NCKs%s5JRV zkm{>sepM#c)Rh}l=xELM!C9B&AE%)l9P7Y~Xvb{U>f(@zP2~=_?sMhmG>!;tWs&wD zGG>J`z5D5{^%;BSr3fnd5jmK|xt%-`iz4&0f3QppK3swQPRNk!HLGQxxKx&lY|D6& z+FUv9cY$#K$PzRoXkP~3j~PEOdCUpWFQ>4u0khY8@`JkYWH$iX_ClDdNN4s(=1H20 z5;w+RcjDgW-PE7$#?3d2vlV*g!}UA!l<{Ev)-svSqTUL0o$oOXf+)Ou7ISGJB`tOY zRq7~OI}#0fk-Md00C+xK19TKUufKpA;9RY}l_P~5Y@O#TbOeFv8qDqEu6<0@C8q{4 zjg~FUND1H3k*wruG0C?hr%MVA6)6|LXW-!nF6X?YZ@{^|f8jvmv!BYM3A54>s1`3| z(J$}81S3M@F@NbOc--`r(x3A)1>bv799uIBksCA4#h- z5#Y?3&?WGJOhiIU=&Ug*V-FdcdeeU;+?9=!5ff8(S?v4&sEaIVzs%6(T4iib0ugxl zxp)?EP`gYA5Jm1Dc5qsID}!au*zE_BmfvTl{QRQw35mn8E+&yyg**3TpLO$z9uYCV z{~Fw8oGQyUzU8U|VAeuzCXG+jdzGcyw-a9YZMJeC{bI)aB?k*IdQi%{ZSIO_)54%l zIxmKC$~ZVF&ZVoO>T-Ux)6E7Dd0ncz+D)#q$;%#T@JNb`Mg)d(V1i_aLuC2qd8d=A znUDqU#J(v0HzW+dzCf)Bbhi9;8Z8*tSLJT9KxkW87hGIV>PZ{5f<9bg6DY2*XJgeT zn(NVLFRo0)VUBYM^eaK~S!qNNa3A_z37vIqFa+Vc z-oux5wUq$LyOuhx9{baB%*={HF#hNC&S(A^5)(Q{MwdYoLQT{h7ApnXPf(xzWoybX z38A6-XC8J%0~&&XnR-BQnw8#4p6?T5irRwFm3KgZD><~sl2n1$orR$^nE?)_If)HR ziPZ@j`$J|1qq%Q8aKVb<#Ny@Sfj>l{ANW`WtgI()tl~OMvRGd}3w4C?WGSI{2-#JE zYPySMCgZg}H}ocVvH>`PUcXuxcuX`e+j{UK7N8M+4q5IycDr30ZtR$2%&t)470q(| zAj)Qtcq>3=Lzr%8NS64WP=k|Rt)v_UtyXCSK-+p@O2}$6L*%g};+^L>(F2FWZ`CJ) zb;L8!Vf`r-lUyK-V#D`2VrTG=qq;ou*xs=PP{nZaQ z#?pcta$&q3OoCWoRg2J1975RIBB07x6}qYtngY&CKbVp+tR)|K6i`Z__@L>zT-G5p zcT=TRZHg`kf_n_fg>u=-MoJ}rGv4r~Sf~xa1h}l2VWI8&S)gisN&{A0lMR&dNECP| z9gcv(hz4}ra(;Cef%kkjrz^ZCcffL1UDPST5_qrEw095MduFo97N;{PpYii(y%k}2 zbep$)=N4~X4kt9X66FTa2WjRU)vpcY&eBW&Q!P3aTs|A*LK190cQ}4HU!N%RtCLYX z`inK9f#1+)8<_sf%8}$K2oxG1Op_bWA-($-FRC(fK|xDiAC;6&uk05J+JDFb4^t`E ze@`6%`8V%d!i&=ZI0=m`qu2k@X7>k2VI=p48fUZ4y77)6oCp9&h0~LvqyV6>sI2xiqsfP zbZhBECzQAR%EA>)si}j<`SyEhx(+!fd)1bA0+sIbpL!|V{mtk-u{qla#nKS=pgj`o zWb9xEhh`RtA|b!Kz@H?~F>pER-%>M62rmp4k#o7`cSZnsc>4+*cu;%FF=E-_3tdNTX5j4sAst_g^okw@Qia7V-xC1A`^tllJql zm4z*T9fo~Eu2O)o#UPnB^e5i5T_j<3K(Z=50`IUXwtw3g=gry9fKl;eAu zrjCqA1suw>hg>GobaFdHNT?-HT)IWNY@OD&Rkc?C&C|ti7E^k41!jAd&GfoWIRCM4 z)$hh2^*=ggRYp4LT5v8YUi+ZK86~8~aEY9XV3mmoE|WGE-LMfvzvv-dSQ_kvy5}kS z>SAp9HMHJZ0x<73UvQ~#E`q{*C*iLbW!X+c zg;F%h#4$Yt;$TAJB<|LGYIV^#n2DyW%*w-~xwy0iq2tM~WZw4o!Knmh*(my?z{Id# zN}5t-ec+ClNJkdt%#`4O6x+z(g4Egi7)1zKGSUtvOX?qA&3R+QYTV0(wihvC5}Uc& zI%|^=U>vHedY zH%kxJF0hr4S}=+pO9rLHcW$tf1P7B^nMH76WhJ@u*YS~t{VRRDWO+n6mtBa`pG zRslSV7)lgDt$itJhnD&VGJp#T5koDZ4#fk{Qs7*&!^!}yY=m6BD=b^br7v6nijF1h zrG%XDo8o#_~Jjb}P76 z>FHOtY@n>Hhi^-PloSC^jw`^06wc*uYe_&sQz(R)E;x@9(nh4@(#o3@+MM0MjrK*R zuBPQwXf?P?%=<``)^*snwkI=?ski~Ats`mJ9&&t_s3{)Rv{{B&V8De)FVRCet0UfR z5aGcW>U+I!{@V4Z)8)gN#%36umbS1XR@W<@Kql;EHWHsJ@YRO`lY9jhywqO;kQipc z)~_AJ(o^M|c)5L{*obMG7DT%~@cxT&@SxLDCRxy(H&eMHBMBj0u~(N%C*&N4c-Xf8 z^-|@!AJy7_cm1~CkT@uRqbVl#k{%RMx9P%cn@Rpb5p!m-U{V}a#-C%)_jmdLjq4qS za4?D*YLs&jRR3YZ`V|vq`RISNcCX%~<;?L0vz0+oLIdME22zZA=ZJocfxs|LIB#Cy zF@KZWgl++{8d8QX}VNdXk7xb1Qb%T*sG*V=xFdDC!bx%oawv z?W;KCz>u!=)g|FTBX?Rs+x^+n&)Y>_yH%RQ41e-4qmp(u&n<&s zG|F877H)6~=_TMBE`*k-ngQjhl-7k;cN|t<_y215`VkTsxKP1%@O^K0QW0t@fnbWA*PpwMQ`1Ffk$6JGEwz-^p&aj7h_?vcLJTBGXXOT-TVx%nB^aLB=61B8OAP}6%S zJfJR|)O$zPujugo*zkC3p7#mGn*=dTOq(L)Te{kEU@8fSYCvxEkxHJtMI%v8@87Qm zzJIbggI+^${Njeo{BnZ&Q2+b-kjLGIB4KVV^G=(ct#~rvqKW*1RD z6dEM0txdotGCi^qMw_J*W96Y_YFFKbhj9G0d z+=~dNq&`iZzwUxmhCX8d7=4f*U6iFrib|F&L?$KETI$d)5*u+@k&N$f7g4qngh@vi znUO0NNr#9i@kA2BY(+U3Fdy>z^*8)@F)udb3xkgca$w>2k4XbIPDc^Del*+fc=IJB z0y?KqsP5OpanQAmZoi1QTz-y4zf}%e?GH?eE*{+@rtAo@h^5CH#&!XLM5nM(AvoZz z*l&Rva2e4|H62F7Yi@BCoJ!PDE5qA8Vy9~zaOJtJ=m%^EhlZ^0+zPsb<)ZfCu-4K& zemAo)?HsgllsvAA)`)yAOo^6|Xm=3!ux*BJGs?N!VzlIv2ao_{@TbcFwt~f?xYHRe z<{Vm$F;_1drqMxfH)3FS%H%?>FQviX%Z52a;^%KZh3}du_uU74-MwV3}9><&<|1 z2HtjCEkV6!?W>)2Zhag3agz&Zh{c-z!k03lO-moFl)FzSGy*>dTF@9Hc@V5Iw z9B5sNOo@p=$7>GlWSUuks55<{W}pR%O~!rTv(wYpzr6GA!bvxJDsu%uw-O;+$Q%L{ zGvbu$)qp}uh!FDO>sVRTOU9&&#hiq>=*&X@>|B3R6^(feR^VmAWgph-yM^9M5V_AK z@aCSP#?5h5t3S3ft?Y<|rnYszaNxz~sj}Q<@3Z#ygr%6*IfgnWqbsEqTBr$Xp$W32 zf_WbpJU5E=Zb#2HwCiXIdUu*C;38j86K<-?KN2ba{4qs|M(4i&2_=6gZOfVqy=O$7 zsmirr3zGQK>*x61P2-n$X$XmP7iRw3vv^@g2LeIO<<+xnu-gzGUpY&#U~&y8anj9# z=coJG$^p!aGPTh?=D!IQGx&Nn1OOlKqmqggZMlv=TnpMBxna7f1^YhH({`SXVj#TxX80t{~kUz#!uXru>%$3dM@If4ww+I5IR2Mvs}_NK(v}vH^z`!OC#a4!Myb6P;A8Lw?{JD7K7IB%@E|j)iS^dI>NolB!MQ;N~7LnEO z)T|}~!QuH7-kIB3ggz4w$vNSTrD24F^&FzuNb;|MAZX@vQPsMXKQpV3HCtiS?&bEt z;qsqkk2#(?W+$$rM*s*8c?w`rOp5W7spy)`LCcZJ$<}N%;rs5uWqq^(cvZgww@RZ- z6MWUP8BFq<4mA63#=Xo6c_ukfBJ;2k;_xz z(hs1_7XdsVT|B~B%-N=lqgE|OT#8O!?xY=&aQd{@CUTVKo9J;3*(v{YKsg@;!2H}& zp*KEnR8dW;32>?Ycc;To1PgulgvX66TsXw63?$LQ>9@jY!A91m^rJsQwcn9(0Yq)S1kg3`HvT_gBw zF6&L$=4(eFBy63?&h3ZPB5!NXt`}pe4ERb7oT>b!dxeq$adW6n8fU(!SRxOA4UgsQ zM1@k9DXw^eHiduyLXhFpu%N9^B)Zo5FQRtJ<-7`9ogrmowG4y|iq95ya^fN2N ziHe+GPt7Uh2qTsr{+9iicE`{>Zuvc6LuHi4hIe$8X;YD(C&mhs4xOJEj|4%>gJjv# zX|P?S5Iz==&I+SF15s~1VbkW*dYKCQ-#m&ppM_f9MT2X$uD#<;IDo?jvB{+D$H%N5 zg0HIJ{9oJ1=(ID_J01xfFS&AieSg|eQC!WQ1`gFwM`ndR(63_=11nmd;v&4T8SHBb z=BSh`^;&$5^?z}twsUtc%ym2J%$7yZa+ngaO2-L3IU~%c z-ZU7I`#AJqycT=};u(3zed1t;HQ8H_BCHAc&z0Q*3O!Ghe=%vJikaIuRgGkCUZGS6 ze%)J^{68&#%@gl^Kc(6*(f4MVumX}O9WbhaFwj5bqidE;J8)TGW?>G@-@Uh^b3NE* z4^YJfxKX9jpKzI+b25mc`29bct}-ghuI*0H-QC^N-Q6H9Al)rU*U-`p(k&w0AT@M{ zgoJb>9n$g5v%dBI=FhCfIp^NjzIKF4O6+hj(~Z7x*=K$>`k9*sWK14VmDkX~#2^ix`~sSyK%t$#Tj|+OG7~`!@z5Sw|k(4#0w6mR$|)31h~R z1+&r6X6+-I|J|&_*%`h;rW?dj3|U4 zqWCVP=ef*z+H)?T-tts)ROdBiR z5jq7>A;t{iob|i~1#E&T2aZ$%oYr*Z=}V8<>8Y}$iMZj4)LdxgGwaHrF#UMVVKhj{ zAJbsWgaK6t6hd_alk1B=92E44-8~aci+3<|N7V{icNJ=xQZsVC%}Cg4p&iZNsGU7L zBh~brRo>SYyxCgu*c%6QCmskW!{JwC9qGjs*HhRn3<>;cb?wJIyMJxU=~7*^dR3r& z#QM*l0Dx9@zz4m=0c>w!>-8gm{AR)Mp~)p0ZIU*!=;A}V2NVkV@-Y_>Je)A1$;B`@LT?d*e)n zRkux=*TzoTHOdOR6x#6we8<%rV(5VY)AG?3K`}{flnJ2X%6tSsv@A*efoPoUYsRkX zTyP+#VvWY=q<#4CCaD6K-Gv6LERW0bmZxV$_D%9^IkmXVJWK~Djk%d3g^aLeuZD+t z<2^d!o01csn1`V*FDnK!1by`ry}1D2@4}AZ!?hsMT`zIc^uguqerC#41@#3T9T)2f zgJ&eLhoxHuW%yN2yF?CeOwKTDV#w7*K*seQeRmnR+wK=xea3?H#gKUBJ2bc?_aF+= zcyzYy0@zy(1LJ!?PD=l5q1-oq{|hP6(NioNQS%;6p}!vver7{Jl&`bDw&}c?9Va3_ zlc_M4tv3$A0p%YQmC(XNWdb>3Yo_EUvgTqUBjsU|p^~yPcyjVQJ7?#JTJM`d3+%UB z*Eie-`B1SM>@Q!bvXsj!bZ`MN^bxt1{Bys5$INL+;Fhx+MZ(%qONxrH(b3Vr>#)Fb zS9)PF3Re%R>QH&|PQi@&JyANV-UhE$_t5 z1z3A{H(?GI_SMwkFd95c zEBByaS<0+%J|kt{FNYi6%H4|c{GmVVw_dPTLW>7`@!vgUAd0Z0->XG9c0##Ghx5@* zIs`LYmoMi!cYWqaHxx|-Jl6-asF-{3+3plDy3eup1(%nfcRN{uGCp75%_Z|E8~6Z? z)|Z&)O|d+rsHjb8a5^&qr@>u*P;NECA7 zesjdoXMo$ZafeP6_f{O%m5|M3Ycc@`X~Z}PPN~0icniIexoUa1fdH=<5XgdZNIFL# zdxnb7_SSh3L6h;>!V!8!C?4dBsI)ZoJvDy#?211{Y&#*h+#X#-08m5xacxD_EKAG$Qv3h8F&B3*nr4NkL<*;g~0*iOzlm1Glkp+;CCnuqK|hCkR0c>z9n;|92Bu*c@N< z_Qe`Fr3b*`{Dz5_jy2LAh*eZN&;au(H2ns`DcbdXB0*r5DtMj zKjx9&uO7Stvs4iVaW0^L0a`dYiQTCc(Ml)211IM1-EBUKBjZ(#trK5+cq6(s6_D^5 zHW;s&K3nXymGk}PAtP@H6k6soG)2Ti`69a(C6Bjav>d)U#0Y!K1@Bg`0h;Y^GL_&s zJRLZf2MYR93fep;@Mj)(I5E{aos>oFo+INwSAfILn{AV*M6?(^nZ#R3b~2 z;GBXHYroOPBY#s%(>9{SGq8bJ7Oh3=gW7m+!!P}~p%&XSp%BxzM{HQLU?5T~fser* zPP99+l2R8IoZ@{q2vce(FdvjDf1NrMp`(Mrh7TOj27-ve7T1fOl*b4GgF+`p-IS3V4wR;wT(!ScD2ih-%nmH{G&VIHU*1xn; zY6?=|?vcxoa?@JS3|Qciq1sN*Hv>CyU+7ZqKPKLFp9dN=*&(~M?|p+sjWFgdF-0g) zzTm&!C)O^+IzpNq7Z*;hb3K2%cfP?8gL7+;h`Uf;4OZx9eJy5w)>d(jLppkAtdHJ{ zngbuS8_&UjQ}$gVbU>I43OR-*46(c2AO&W;N<}<>|AA~|B^;W_WhG>?J9G$`D$wp1 z6KO0nk!FgEW5FAjG%b*HBvmltsYL;}yR1G#q?L+|ZPHYAAzDhs2D2+BXl*CO^Kmzy z#uy>^ROqEYxd3Ji&UXga`<~m^1#i4RJ48x)4z6(mUr@qmaUR~UoRkMxgj>&{q5sp# zUSA#9@YtkWCSY!@j0V{q01Kxfu%3 z7}afZwNVA9t1C_DK*qa+RLt!iX$g{m-_qd_VpwZrIrI}6<}t+5SsuARY|SW(U5<#FOv8a{Lq*JyX9laOCMy0R5E#V~n?y z0Y8~b;l4IIX{tyh-zL^CFHcV zaWe`6G5%w?=WbW_V*0j%kSicR(PWHRMXV!1!yjdC_7y@5WDp=Ip&u{+p*NWr6h*^u zM0G@8k}479n=7E*FKKO)WB*po1JoFf?40VXQxp(&Cx@b#!8UQS8~BWCt4)|EOSIT0 zX;@n3%UY36*>cE16{>sewYQpmtU$ICn~`tqSjBWo5xkRBOgZX2I-ifM=rzAry8p;m z2WA=v0AIJ?iHGQnh3P=2#6YC{QA>;ERj}kW<@~Sx12e)N9>PKd>}FpVPpNav1+OO> z-S)F=i+Xw}F(qyQFxT34_}-KyA6^8Uy3tQ0%Eui{^Q}HPzzE$=?=YB*IORgjp%sre zBb;ui2n()9=~l{;}vnV4e1_G+m-y8>?NWl8R=(0uod>y6_Yp6F1K&-%zaM zvD3%qfPf*ySdq-kSbEXBXOFg%hHNni;%F+@{yAXC9g77f1V?-=KCY0+%*@Z{ zKlpomxjg*}OXmGUO<(ueO3m+5f${1qF2f?{;Wu`mScdluqf()VCR`9-UR$DD%2*;u zBhJ!$y7c!<%y=kJJ1H7dO`=iOG?uwmJwFO!wTEvKb2lCgY91cSZ{q1Bl~I132`V_h zaM8_gZkqBfgaDy2zje{j>dJY)3-Bem2-Bp(GBG2K6JQoI>*+{Qvuw1$*MlEdUfjTjEbAmJDW$Y>Sjlyl43artfAR5s0mIC?$40;*wxsfi z#B|_}GiGjJ$ z1z@!9G~80~K(>qzMcA;8j^3CrnJBlR(n}bQLKHE77Y%1^>`v1l#fl*@?B954OZg;N zgAVF!`vm59S%rWRF<><}pd;hwp&_!L9m1cE$_O{F#@|UfI%+r7uC(i$Eo1}IA=G== zhnY$|Y2(U`)!*aZrEim5G@#+?Ur)_RW_n6kVYdlk*vgiPpQtEd-umd3fa(M5DIT1DsuLjemd69mwd6*5lQ3 zTDBt4JBpv0_vkXo?|$m===*M84u4v<&MYd6F6u%S^dZ913JobTF4E%FNMZgmtkm-d zmjiWX3aHKgfdfzX^SK8GufY2Pt|@5K6xHH>M1Kj6G7GN&ObfBl!k^`P*R-@0*OJHqogsj_nTN#X*?i2(D#8^eZBO(wFAY$X;mx_4Zn z#TIp;%<1Xs5$_$c<5Ud|jV@p}3QR&uN*&%utAVhzLdyvEhLl@;r%`_BKc=7kGF&Xw z?>)9}iHJCn9h^IMWm!un3E{c{F2jZ!jTrr+Y*x`C zl4fSb7r(mNE>0^nMmvb~@XAk!$9X&MmVg-iOj5UK`-#82yBt;nh3+o|V<+yE?tND5 zD-4DLCEBaKHu+SF>aXK>ObW83>Pq3Ujund@8)JcB6+h+Tg7$vDq z>-@W26G=vW#XdW|mX}l_J-a+tX)J;50?M&7!kR3px~1A zn{VzeZmGQ?p#kH&mz82saEYXhSpV!GnTIfuRs|kM_pX+4z-XBz&IgM;_z*Q?bh|Zg zS&J8jkib9?iX=-JFK%*Cw|e6jqI!~9W=v*E#V0g-_OpVRTru(xFZPq^rfcV2gsC5l zn$>D(p3Ee5(-J)d55L^{!a{Xo3<}C(xWMo2?6X(N?7s5YaFCPf9sV`@UOB!^OZmbC zFxvD?w@ z=&S*zT0(BF1v3*Ekv*?By=j!eVJgoUjvz#P}t-lbjc(sYTT#p$oN+%W~v1P9h=# z?tA(PIxlNIKM}rSw+0=^laVvYF@q0u2n0m8L&teU6eRx5r^0e~RNe*By7at=5Pc%m zrXRzPcm)c%j1RL!HRI|h zCItgGp{=FWNNKE}72k7hnn*%SusD&5G*yJ$5I`5)%>CO|1955}BohttZ}W@ztZr|t zxs8JncWNkC6O`L^8W*RVyKz@tp_kZ0ZEl@fP)p3UFlFC5FD0`-B3osDi>SMi{Kz_p zIP*s73`}8il>lRp$&Slvqwa@nCx0U&){J~FLp1>$OG_WwB96)g$4Ji9WMyng89-ri zN*8waURV+YZX;)n$3|bIzb24(8551>ThuVo%x{bv^5TNKGr~q3fK{Q@5?d|Imi}*+ zgapzH^b7bbX};BY1b!ZJ*x=Sg<`j(e0!+rEJz*+AQuXx5TCL4Plf`u$c{l|}3W-7_ zm(j?vlqa*bVjyY6q~}4o%e&mOq8r2IZ-3`DbIr{ZxBc(*G*J#IMs18Q5&?8zq7URk zjtyH}<0&CWBHyr3B2Go5@Ti~))Z^Dp#WQoENPbMo$SxR5I_&=Bi)*degSAcUMdUES8r1vF1q;gIo1l^MhRIVM{~hIOd?WGq%wChnv+FY$yC zF6d#860a72e-TyFo9C^KuUdh|n=AWmAJpg+dgQdW;_34wvJT6(5-emY2Hou3HkKf&?l9&c(lMr*; zQ<>HwVxiqUrN$4&67JN#?YnM0i7Q)gcAM(gZ734>oUK}q>!9CfdVN(18UTe`V~A|F z2?>6gkZ_oIWwn#vP&6?YtmWh_rYZSWQDtAj8w>3+&SP%XnH%aj5#W|EyIySN_ni zbt!^>KhBZv1!;*WLqlO=-h@PR?@Fq_JDA9H?e>`15wg9b+*r3Q_(JL(@a`;r;JVs# zG1mJ$o>W9Vw{iM4=t+R-T0GBK9?$KGCanN@J|W%Y*9Z}I9Ba+mJifkhbU-)6uj@92 z^r^bF%eOe#)Bu2RocXR&H~L}u2pOJO`Sl-j8t32r(nave&FA2Z^adzuc{`8O@5Sk( zr~_mb)YZ7^g>M3A1D-zSXjQgJ36;|Mnjd#^PL=uE4n=nQxy@b?q}GljWT~eQP(jf_ zi63a`N`aOE((Qm;FVH>97Zv5`@XCxUAT?|ke?mN?93C!ncpE?QaUAK~=Q=0(9p2^> zv>@0Qat6^TSvSLb*4{sD;h)iWYOsSwQhAUmMpCg%gR9;f{6H`;wnoU>sl&_e7ovLv zhj_#S^M$u8Hr=5e4S+rb)Jo7Fla5qHp^~e~Hu=L8$l&)%DYD<9TWOsT zg3(m88p)6U5#$H$mx4Y|lDIW#A;0G2yIT4E>3St2b;A|K1VSfP&0&uj9{>`3{~J(U zV{wvvX};TJDxQ%55+#QZcTmc3O!NU6=0=h>yz%xc5!IzA7Hjd24xvvTW<=swhMZDq zs;&bJ4F7RSSZ-Cjc7TH~BYLDtmZi%5%{`JRm)8hL0gyz|TcoqjV~(`gaASG1<{{O( zSING+Xemj|3wHiyOgJn9k`X$%P@q(h%AZA`z9Tnivv28y$sJGuCnE(&Gqvu3pLYZz zP`K?Jlfxv-&$T_zD)$?&cc%S)eI(q>wDgF0mg=e-Wb2fi$M62`CJ-(RXSa!VNfU{aegX*m7WxWXrm8Vb_z-v1P9vDmJ31i)YbItQ%Bis=xs=szkMyTBrLJo#}Iwe68_1$Od{&#n$?$(sCG zlLSvighB~CBDd4p?}k9abyPbR7Vyb}FXmE7bJC?QFEA_M2k+~#u}3V->*|`8`6}{U ztse>1>SE3jKMgilw?`qtVn&QEBc_92>G`}CJuim@y6q1Gjc;@g_}aE`81uI^X#_ zUhbN;yMhgHBURI&c3hIkABM!{tSYumnV7yIO>Q8f*s0MOulg>21V9uL{S7L{HTC}bb_Uh4S?rrG zQISeAJEXmXYeeQ{k_(mJC&CpaP^cm^#MB7~XNo`0uxy~kczx{cU}*^_QG zoDlLS-Tj8}phRE`W#A%a?_Egx0w7TgH{6kb(gH1zi1w)G(c=@FIDre@sZLmM5#0)i zt=R?*EP1m<6|zhm?U4HZmrd+jcei>eoy{b?4J@2w!4IN58fuB!xnsH-BJnU!ICDBm z&PA=jItFOs2LPsX#lw2d0K=ayt}?N^UkiV#BSH?i%ueAUd$=IV3uh=wlXuG_&d`qA zJn3g+-+W#)Nx)!d-8fzc7Seizf8aT8qG7*(g}yprm_;5I*Y!ZR=96s{+IUjSGA-o+Z}phw!} zoXJ$b3`m)7(6CzV|7ZX&{*>nRbi!QOE5<(h51}NkYqBPWyh;d))@2o%q;~kIStEe##SMGF)8``=x(XYCUw6EmcaC1$@ zeV~m6cworE7G=+)0_28Kpe5`M>g5xg%ukd<#Yw999>kozq5y$^@u+~PdIsz~DH?xr zHn1fGk%?2mlB8NU*WU#qhxKmK^W2h}JP8|QMD#*((zC7xP1R%xpJgR!>^uMc_y?%i z{aj^MyfYspI|^4+GO^h4<1&B0eFg{W6yX*WJ>1y@N|T>J#hd_6*CR@(7ofTga;dJ- zqZDBsHQwExSd4N}@=S8HZ$*-B3S#(yH@gu7Gk8!v&>q25>6%o9 z&T&^C|CCxA8fyKR)s4V6PiB7CZ0CvxND6`dQK#YkU^fcnvteI7z`ov!8(VoHatDsc z$>Lp~YD_9egc(&5Jrs}sQkYl}<@GYtP{MpE_0x?g9f1Gx!220_=hx44G{IDw`M&{h z0R_vnqXYa0OtA;k4-eqBn^~2u2OQI2GpvLtDf@n9oKWeD=>{gNhY$Sqs(%>ZALXDu zUl@y##IP3#(}sza(qbdK){eRVEaBiKk6s}NDuHL=&CKjt*xZK6TemeNUi2?SDZBDl zo8vr3z;0kXE+o4AfGcEU@3l%dyD4d^KqTawwARvda7Zn``n=GvX=$jRl@Gh4>1j3p zgx>Es%C?=00}3(ko74y@xG_SvW)^&v3^%uoo;MB5`?f7%(r8)G+fimPcF%)RPkcn# zLEnS8kX#X}6ji<9UfS}Zzgijc!^y=tzo89`cvF`9B&9kea@L9Kz477&IKh0(@_#z~ z7bWG!{@@)6l_*;3b(gu&fCcef)nbg8dsUHHpeu;4pig5mhkOGm>Fd$!{pf80)%v{1 zDwY{&)7QlvI4><4|G-;0z*;KfRa}pr=cQ!jh; ztR{=ZZX@U6Q~K^GnT8AsLGM8Yz+NfbHbJnL+)eB#8S#_rtqFv9#I*3!o%rVz- z6mC5;979&`cRDCZXS;Y9O3jlDd#54OiEpaDW({ZND zgwKrDcZ^ANa}5e5tRpllT$&4!`}@3eY+x{;Dj6t4g#4TIBk4P~tPuRz{>_3{()XtC zlVlrv%~Bu(t8tQ*=xo(Wt9PeB7r*MTfc3tojW^1RKRqu`_d~4|atvxR;yX_tUP1=0 z{&FVK!!^FjXHC8UXA+cy=fZE`?}@sv^EMKVT)NN!QCk6LtYEkhp@U^ao)lS!WY9C5 zv3?|^;FM{(7To_#`tMaczi2<3lUgVzB$zC`Z`jV4Zz-cWVu#aGBGWu4HUNWb$1!K& z_;RITZf}yGeVY7+9wF?sbbE}v8dD2pNrizqZP%g2gvPwjYC8r9ZR4;IyO?SH^mnkF z!5fF3L+aBj2Dq+bu;3Pe7Dxrx%dmq^%@&P2O)-3x<*MrDlu0Aut#bHKo;p};xkE}g zPSzwEnbzA_hn(U3HI|K#f!02OwWh7b;2t#HjkUR_Z`k&9*4kqQfR4ZGA%mqYYblG~ zv?aE#b7!Sn^Ww8zqzkBp!!J3ER|rys`V`e>X-<5$ILBje|NFU|5~i$zs64oUdjGc;fQ>>t?0JEeln=D-FBNEF|T zNSQ4i50Zy-DejYu{_?*2RPq5`X|H}bgsO9&Q;$~mJ*MP>13Zg0-{uY$oTM2ooF*`% z8UaN}sqN$^n>8<|Y^Wk9twP;ygI;RgmzmT0*23GT#wgWi>w#mJuamfZgOt_)LxRL^ zz3RT}m6)T^1Nqk0dNd*cH!&E1@fh%2?VJzeDt6*scbj$<3NC(~ftJ(WJBK4fw|2Hl zKNNw)r4dr;<7JI_5NYkdHNAILg{ppVyGLJgDby;h@2MhAhr2y-YzCL6f?8Lv7(_2- zQV&1V$3(2vSC*_B=9rt?PUmg;($pHn0G~_|x>ItV@ci%*lHXN4H#DOW(b_|Ie#|8c z5&{9XtY7Zmh_N)~p8<g7EeMO- zJpN{l^Q~z$PX^P+#0~%HT^gvekZR|N5cn3};HBBH!9+y}|5j?n8nd?mh#d$1h@V^( zlIHYDo4m5oy&e(9N68Ra^MG!j#C2j#R^_bAR3zFr znOKU2o%GwkD~WY)QylDDu5VY3xF@p4c!|$QBkn%fgRDVVmwnu;a=HQ}*q4!Z^Nv2- zMH=dLO3JXd*mx?eIPx4UNHtoGZ*Q&YPxxK}!zm}Igp|CxG%w9!H0-$lW|uw>p6_4K zH((-&g?+LueJ%%awI$A4S3fZVGD0}2;Bfu(z9X6yeihHcdkO$58;a0ttM<{Oi7tF) z1#o61pR_kb|d`qs0WS z89k>QN7u(WI&y1AIo#Z-kw}lMLWh4uEmB@QY#W@=mgm^G)WMS}MCN~xt`<^k93MhD z0wYstYME7p5cU_&_mZP^USto|+mBqyg{iLi4c3S7@Z(NDLlvt^@`E$Va(uwAa?7I8 z;pUy_kNx+Va-#KOS0l6zXPi#^)iveeV|63FY5bVzA3BB%*6 z&0DSx$X`i03mM?tPMa5*qFV;c>N<3Mf^*QIgM)Gi-^k2b6b-6L37VW)_e~`c0P_b$ z764_HNaW#1JPI|W#e=II4gala93}3cQfw^FT#Yo!%`p=2i56#U&X>B*vGs%un3)~A zGwmbD>sX>i^Ssm%MAVp0_xgJN>LT%pXr8n;X^|Q@Vuien4r=_tCzNI;s{QR_GI}`u zMXJPuOXoH|S@`vmHbwW9=es7pn9$&aGJsgRPxW5cb8WaIs$k6}x2JR^KxpC_^%N9$ zP!L4+LO;v;yxP^W_k|S!u(N`2FL3C8KfxG8DaF~o&lh~5ut~=P2t~RlTn3_e zzh|bYPr|ym+?06X!cv{Wta3Y~Sc+~S$>Fuc9YQjCcNKoMQ_qeMC>~Po<0N8dcTG5P zP-16{*63>6Ua6a^g%j*K+}Z4mXk7~w2)grr{iBoEs>8B1####kh(5QK8}z68vaQ!jsR$LGYrx=MJB0xpfCe+ z#V9vn0Ik9gvqnbJcB#Ona?C0ul6%&)0^w^;7FpvbJUG?z_T)nrU;h$hoiUgRcd!mO zC8x_pfiKoG+ERf}GZcN6m=Ue%r=$^3KhwmI8DQp{j;K0DGN8q6HobHA=LpF2gR6zy zW>jzttm$vR>@}~g4%9B1RD?sLw%jWQW=O)mt0;Y2R7Z3($E?$`c6DDOXH-L#O&P$( zj}&2MVZfyE1ix3gtmxxq(NUy70!VbC1%2q~FCEk3cW3|?I+2g$XZ7u9Um=|F89@E$ z055;si^`h7bdV(EyuFtKgwF`3ni=W&rlllJts!%Lpgy$u69a?1YV#(``o>QL5kTMa z4p_5Dy7l07SP0dcL<&F?SD!cBs5~ek449$qG)SRY(86uk@LBKeOIz5$X8!ae=R_(+vf1R6wbZY zQrw|S#C_mZj6*~pyA>fG5qsbkjZc*Z8iX;CJ5WGh|1dECmTO%JE9d+5eX-oDvvti& zL_iKby4(bf)BekbCsJNMvZq-vUSTzk*Nd5O0;)h^{}!(7D%*|U^IM*u*Qvr}8oc87 z_y(Y+<4BP_IbeSug3EY+S>XXR@v7j{MUOuI+Q@zJA*Bod!f*nYgwI~G3KYd*d9)&EG@0&lm~p2H4*b2kM)%(`s_7&ADS38eLt!8{90*-#rs_OM zHPkOn&Any$vJC0WDEy+4fdGmh?ao+@fnDZr3l=_NjMV9bg-Qq*^t~xbYN;Rx!Q9?Y z^$BWnG1cFsx>QN*S^-J2t;6dPL&q+Hm)^PFnKtP5fS+^LJAtyh1+l0qC~1&nprs?R zoABUOz$EYS=MWwDvz!0 zTPTZyb|q#r^E;dB z0bM4$U~(Z!9%6BhM*NKXR}c8dY-jZ-7f*)1py( zbHNhr_4EnFK8FdHmfB9FMs^#hw>z*xrw@txONJOY|00vAoFC)NA6(I12k{qePLVDK zu3^JPAjDX2^S{Og)1b>(Z6QM#jV0z9fID5H;Wu-Xl^UpKgMPFRG{a2yQiz;f)*;KW z!*MgyGS*f?A$&N+c+ypCRQO>DZnO@Oqdzq<0HHi=Z3qdf2>PZZ2KG#&uh9{Eh_Dw0 z0Qdw~&z#s(+3=Cd)k%Gw%Ne6)1>W&v5m^J2k#&>_rgHBjH*FM>kcb^uYHE^fO_hS7 zcW3fEl4Wf7uIA^7J*3Dz?Yk)@NjL^3s5BJ~Y-$sw_dHmkFKAC-s#F{MiV`a?^?6=X ze_Lem2r{`c!JrUdiSomf51I(uZ3vsV&i2KBop{+eb;9-2Ik^OGFmUijmv z1CoV2l|MW;fK*M0;zb~}c&4XvEn~zQNg8gZf}q)tT{J@^8Hg%1Qi>d(k)_{)8-Cdr zje9>6C5{)$;;75xJ*7L4@2WmegQK}4QGLh|756M}b)9Lji`B zz)>cyb2S+UHaavL!nE&-ZORTDKo#IbhBVDHM3CIzN-TES%AJXPc{cw~Xk-@-ZLMhq zR!w(67%(0J8E4&py5{NhXl$~W+It|DuAPpPrJjHOO)tnE?G$+tDbNXfz7Y!U2Pmn( zUbq;x4&TKbvWp}as)><_1<&6l9{kPAuV@dzfC&Jni!|B#?&!PSHvk%H7G}1zqP|DyRqYtzNCvI=bs;23+`p;2Ibp;^1tZa|URpNl_~n$r z`kr=4v$+p!Tv34vZhi%2DHm|SjFpVUy&f1p9;U*5bw6qg?tEPU32X$go^{=+T!;n# z9rEu-uZ?j2L*#>lNq#3YbWT_6k?}C%mi#@(`sL%~{j&Fr(qz%2 z`81Df6UHPdz|A>6XZZVoj)7zaT-Epe>-qL0Sa_fMZ%41DDtFR@EHGWFq-n^c;{qUS zepk5eJ-=DK8Aqv0W?4jwTv8#{VJO^{Z{ZKC(1o7^CvnJdOUEKLSgX$rDa=a=U}8XQ zC4y{;qDP)0C+QrGbVvW|M`0^fgZ|^989`Iof0$`s$wDymoR*}Fr`?9=k_GK^=+CjendtYCnhi@9P~{`?*jwn?#T@)fQ=W^5omC3}C&JrO*eK@3GOQZq z897^iZ$B7mbl%BluH?%(<VUbiajFr_4pXioGGJO>_guO zHnCYctLGqcRs!1o_gLU;&5kS(_N}Rz32hAw=Mo`N0YyKr_B+-z!}ws6m%pSJ(3g$; zpY`j$i$*{<_fOu?SmWZ+ZH)Ied6f1z?0*!U!+_{Gpk+U)jvD zSQ9s*X1;1QsU_sXW&r4(u8W(NHl4QePf6|30sla!$`05ffiG9*XHj)f0_4cs^qPmL0Z8;{i+lC^(2>N{>S z6qK_&6aW5gHL}g%X}VHzzELEDc-ejT#^&@#s+DjP)s%emCRFPk^GssDI33&Iz6ah> zZ!^8|>GgqZUksV0ZlR1cTh0L+Gd)2DDAzRO`|q-4oiD0Fp%CMIPHo^m3mQd`K*qsk z?uK1`c*k1up|>|hpSe+h>y$OpavbPsmTQDi9}O_njQ$_1d|mK@_QP>J)o8-XG%Dah zml}#-F6wqeV~{fuIcuuYhYd~Lcpx!swuS9fR*#d}yWGd?KbY@!$x4%c5*eC~oQp|+ z)-NBxE(b_12hM>3x9vhWo07P#aGK&n@q?I>A6vSLU-$FNd z{-TzB_$*w(0|zK)LN)+H!a|C?OKC?3^J>D+dB*Jx#~UDF9-#86Pj}62a4=Rs3~{s+ zO@=u`A4Dc5Ds}_E7~gP0x3X4EI;CY!G@sVH9`1PfX(|o5e3}_hH&j@O(LGasuNv*P z4cBNPOim1{eF}f$!b-2}Z`NxqKY!y+(?hZNrqMV!?6Fzj#F|%34V^|2yJh0tTa>aC zuJHccoy=0opqda52-PYIU2a;5OM~0ku?a-NN>Ge#e{cKHda4K~J{~4Q9vz?_m;RUl zeghy-C;%mkf{sp(<}7>X)rUv?T2l&b=kO2^Z+_x%xAGtqID51~@^fJGM@3q*Edjjj zNmtn^nV(oY?Yll5s}oBpaePBtBZ&3!=ihl;^q%$zg{NPUr4X>a3dHkkl)#?&cDusL zG(U8C{su5kBCPKD`PwgZE-NchAwd=#u=0ly5AKB>TEjGhOgXr(Gv?uEPL-;v;F$=K z5i!UHrr(}}2VnUn$JCp?)O$}jRn`Uxt-s_K zgkphC)gjYC6^UgmLy%x1&|4n_bMkf$P4Zu@GxNCw{44Ud=C{FgfC{S=(F_j!n)W4Z-u2Z+GfVpM3ngj# zG_R>$3r8@}g#225;4cRVs|}ediyJa)s7n)=bX%SI`6E<~VL|BK*2AifqYV!p;BaLk z>7TBPW*7T=7CEV&!%Q?{6}%e#p<2dbEeCb@Z=B>`L!_cVD|24R2cV;n^pjyTAceox z$g;pU{h1JU@}@(1xP)%By@7MTR#$Fh9{xjCTKJ$d3@28WvhQ)~6%}|o1Ttd|{mwf5 zesp?`P1MSGuaQiPj()m+QV$Z~bw2f=(+4Lkr)|FusQpv_%*M+qRKXN;Mn)`M2~4zI}>iiTSAiaOZqEM5;!NU<+j1 zN;FaVQ=$JcSS;vyI5;#>n;ly4qDwiM@S!m-G`PkxRFvo>_C^AuQH?xDOvM@g_1`0o z?KIDy>1*F9EVB-@Np2W?$RZAr@xW=3ISzO;iP`fd)6sQR>6-C7rl>1D5UoXQBdDQ3KzkBd1EG5TZ68wD<@}0K5_f z1h7oKET12kv11Tz7G!+0#$#izpZ)+FW6ly*BuE5(v%#> zxJ~l#7X8}2lC~z5knh3TT8*aQPrs!J@6NF&{bQg7!_L=@W0v3ZeeMw2sDbVWvlV{o zyxrJe*CE}*$M9w0WDQ6oR&?2F>!MY^={Q7Sd!}_woj06_A8;{rwk~j;N1i4(2mL_S zaGjV%wiTAbMZ{U9b{853xx8X5XzF3hKfc&{s$Cn$yzp^`8?|)kPrXzo8(!!lG0!ym z(~4(DjtVRw9JOwpx2iX91r@2c&|IZ!+E9ij&*E)VDU))9`Uzn}U`y#wbsk8jqdFkp z8}p~ws}rcXFd@;}EBSv~0MK;Njj>jE#E(AvV#Q54Nx)NJxYK*U*9s(zeXTZ=vZ`KQ znj#co~5&giS2x5+^YxCpe>14oS>Z&%AwiWDP8T;gaKtfqyst-*!*Gj zw`<#+wIp+He`>h2xvfBYj%zpm#v51y023%-TpYpHy|-qwLCv$wEKjhHscD(KItK*p&>63Is7rWKs9 z_1mmKWJ0EW_^S_8nb;#%NJlzsYyV9&JK3D~gm6Gu4|8Jgb!T*!y3MO8O>(xt-3?Nu z0u!$)=|@MZN!@(hySM&=-n$%JQX`jF#AMZ}8qyr~Z-xg-heV^b2`#N;doQ**A9<*e zGL)xK%bfbYe#RZ7GJ_pP!e?BE8W>u<3{7ko3URDyM}SRk@qU&Y!@lE_tst}WnsRl; z9m*dDkW`bIpByuKCK~y$zN3?^%sd22$-W_Rn8>GS!J>zK`d~jOTl9J;FDDAqz~@ZP zluzsANuWuw0b-F{_w$F0A-^r#sV6-yV1AE>=&R1=68ZP5~aH(r8{<|M7lvzI;5n#yFt38L+OU)+xz+E{kK1MW@mP;IqN7~fT2E`^Ah7c zRZMC?jC)hBtJa^Xr-yCfw=zOr*?3{ec2Jn$NpkbTzQ4$B7+|w25*ql;qd*WHU9SUz z8seE6B$&)lPsN>)cv35P(%4A4*s!E81OBpb9RG=^V}U zXX-kImV3ealu+~G8{h4Kd3-!M!&ZdBh`~<@dO+^!Ur|ii;7=5yJ%eTXiD|4RPsc*2 z488&4@OEG=oji99tdW>iNQ+=w&T z8)q)X3*cbf@}OG}tfb#+!n|u{+g-qKyV282ED^9IaUw*1afsAl!N(p0Cg)*eIdbv8%#BZ)&(D-x2@1SKzOKvya=bT%_bF0WwN6Mgar{TN`J)_k z-5)@ivn|wgUX%d@4CbKs?3gH%aAql*Tud{Ver7tPYOMSYGCaP{e|5y4M^M8`_Br5u6#Sp zWK3}BnCpcVOm_@YdA=txx|?l#Pw(JgEBQ6-yonkkK{Tm}W^M-MC~rY<>CF-a?{iEE zCt1t2XRNEr(xmggD@iF*K=CAskjK3I zo7c{F0J9=!S2WPTcH2RZ6FH5B%@j0hXyuR5BU4fc~QPbVdX(Z zEC*)u?4VrDT(-E^FDKiypY63(U*#tT*bF5GKlST8p6yn*1KyEBmzRf9@Fpe9zl8NB zJclL&%C#T{q3^bq!yiRyGPbXF!L|Mz3E#W|OQAto*xk(`z1^&7RFk6$#{aM69F z#RtiC8Yl%3Lm1-J_yGW?47#xuz3Gxrt#oM|WubzL%bdjA!SV1EkgX4#v6O3GD9B4H zvU`{I;jUjS%5&Y_pBD2vf_ivnjIEz-PbId)&C1IdAZ}Keh9T@h-dbvy9)ky)k&Df%}Ys%6~PI?`YZ5$b6=KGH!K2 zQ1w|uawzElx`s#HRZ_r_$aLjf)O;%{JQum=5axAxtm*`v-~gl=i9EgS7kyL>JzdJl z8%397QZxfu)q=+y&okY>NyvQe`Z{ID-vwK0zXtllEpb6|;nVU2ftK-ufm?C-x`TqXBZdTCc9&$l>C!xsC-6w1jAqS zqbL2A`^_gVNw4hd@rr&seM|wYBGD#i8lQc(F8UIZ=b9r#3H*|uIW1;*3lV1qgm0Il zihA{&L?tWjdBsvOcvDq34W0NTM2+$5Z%H{aHj9o75Pq!~O z?RR&BFSxN{4+mj6w-;p;4?i6-ehluXoHB3rnFL@EBet`?2CIV}eDB-VAaos*XIF%A zjrs$^n@k)K_*`P7NFroe`)l}pd+g0aBED`VM7R7>Op<_#LngXI;ab zzfT$bWZ%FrZzpNQ{R9bi{MqS{n`YC+nL{vSWh-wc=FsQzpEa6*Hp}v)no_Zf-Wzk8e6jxQ6=b|@bqt=5^{8wPWn@XfJu)X}cE%EgO#X0aVPSX#ngllvlK7J_0 z)W;6X>!OhTniH+!AJT%;xsEmP1~3G~-o3DKbltENOR&j=Cf09fSMP-lU`h_E|{Hp z`i!^DJG^_=gl4zebYFnS3K`_BLssGW98B(F<~P%P#jp2)E@()b!z=PPJ4GdUvZ*_@kj2tIjn4PKnJ)2z-HODsIIq8^N zVd<6w$HP|VAx3XxN(hm^A=Bg#*ab!`9RL3kW~`}%*ic_SV?L}!w98rlqf{u0O*6Rr zdYV(sV!4QQ4@W~7i9Xk!JtdJ6nUp25_gj9P zSeG7!=WUw!2Y*GV4uCL1eQOxfXb}RZa2Ynk`0Tf`_6Pw`wVse5?2-zQsJtCa+g=pH zA}#!IB!fW8ZX#j?NPk4y2&f$`p8#nPd_^`z52WHOruYxL6u#gEdRV9j5tvvnb`>apdaLBHUN?s!+kxRy5){fg$74t2cM z`SEdBU?E#PCAcT)qD{CsVB^RmLdoYvje&N|HPASn>mgNH5;yCCS<0V4e&A~I*WXmy?E-@6>J%vaD$86CKOd&@`P|~uWqq^0vM%6A&Htxu^>HyCUlTQ#5Tv80i&Y@ z4s1fz#nYf8Rcg(Lk|d^)}9qoJ|n-0C+idE>VweN0(=7W2P) zY~Ku;aY`EP6YnfeGEthb)-TUqX0yY7g#GG>9;?vo=DT`^VFFj$%hG=dug@(*c*9Kx zv{BJN-ll@ct*Eg@XALi&h|VwRt?LebK6{LJl~13=xkMj@e&kd2;?lrmBfBSi6uoSk zUS0Fic=J7&SHmr7yCnnU^4@yYbMNZ`lT2slqve(1ynhOe;>K!r!`_QAWdW2aOl?|7 zmdguys^z#b%1oynOF~<^QpR}#Lj^nUJsA?vFhw^Fa2}cNV0r7VgplJyzh-FQPj(n? z0)(?EkCvR*s%Pd~^G#&GhjP?bI8p(A*X|(Fx-;0h|5b>gaXHS%1P)Z*caRX@fQaH8 zA0YMpkUSpCcVik@Jpv_Wxsw;A{)_ZfKF64+ofb-g6@KYZtCl4i8Vi4@GUGa+Pb9kA z@?vm4l;SP^G)hOixb0m3=KRkRpqSVndkQTeT8}YV2@ji+!7!+zi(dzA48iA(0>A8Z z1P4VkIsZxO>y1_Pzk~zS#prA5_^6%;`e+$-s0h5DuLb@!4R>c4A8(GNE~Qm`C3%W` z{iYAIE7el$@`}KF)4(Lhu+?c-L-gV~197bwxmDLi8ci9v{p^UxDSo|AKw&_IxL2&s zFG_Dn$V&)h2gT%*!r1y`xd^y!o)N>jqEVaV#~V56yy+y}atO;S0{K=dMn_)TtpbZj9Qb_1Z^3O#(FiDNmNIt2Egz=JZ;h<`+VP`cTl8BUQM zGdyA8c~{FA{xn=vgH25+RGT}aVShrt6UB#~e8FWJud3XSzVb3s1pA)Q&Ml;9@I@~j z^G6}s-{g8g=+pWS;@yPvX!}M6kO}bbF;v>rF`1gPO3Cp4S3qVD-NKJk`#!ZWdobw| z1N$CYg*9R$;I~ew;Kk343{Z6?kqYWsu*|O)yBDkF)M6QZ1KV_E1&Ooa%!ai3{C1>M zJo`wZ(mH-IrWzz6Rn75bpO<9eaENxwZ6#+rO)^gQHPi}Eg!1NQ1=X;Qol0Ir_+;`y zvtrc5lXM+^69fc!Ke6IeP>ss4f{@T?=Pa^M>!MLYvz-Zl0k8S-#M-?c&^$ykf0yML zu%U{=uS`!wMcp}uhhz%Xn52Zbz+*aT*FJlq%3W1L)>}hT9l6x-iTt~R&(E}?li|m> zJhoIa?zQ9i6gM@A3>VgsOZhE4tT(AEj);nd{jv}){uSrxWRgBhZQEr1@1NH%TwNcS zK?=ixNoyS;#Lj2og&fHl*XhW$%jf#`C7u;kX5u@%4~(2oeuBCLZlAZ)d~TjE zpMg}5^MgQP)^PXTM;n_4eu1~3hvo(ihpy|6Ad!2)tLNH*M+6B#$FQ}{mEMjr3rS`3 z_@=)W6JUHfVjn-cKUE@l<6tPb;cC#N5p)rHe%Lwv?yA6^50xR#nxe%QoO_D(@(=D` z6!MY5KW~K>vFte%IE9m68=K^9?1%jRtDTFPTd+z#uTx61IH{%VRn-2V>_eJnb78O^K{<99D zWDAtCc310iRoXarMKH>Mc9G1qm%tJU$#RKnH1UIC&+Z`fxU#|2AcO{haEK$nYk%4Q zVAiD_L^E9#oxOqy|7%%QyaLYC{(=yx7`8ccZq3bU`5y##e*5nY{m@|fGcG8M%GDKs z^H7EZa-i+?NTrc}10G9Rn(y(re?HiVes~H+@W(Olv44VM2Plps4Plcx&lhaUeu9@5 z%1!K8RY|CYd0)YA|9rDAK2E>GZL2%t6n`F8jZWrlib!iFKV0SJ|BEwftT?2>_BzQX z+oJX~#~!FIdbM!o`xYSwF>+YYKM$OyGMP8FiY|UUO

i}%4Xf-hjz6{_qn574+F|t^S4ME$-8_LpAH?wHLQRluv9$JOGvVP{TW?Cp_)^tBd(v&l={hjJX4J(!nqS!?-9B#u2!*RX6m z=ppAtUG$}g6bb13Nbb0L?n^$E;J`Jc!-{Y0iTImvKVzbr7i&_EK*(wYzWJ;1?VNs! z8SH;E37+6k5Pb;g6Qo8x8*{_Aw?FQdkm_#ZLdv$40QE3?c6`p%vcU&Y6Riox*~fnJ;?4<&PZVaZ0L-lOK>;e@|e z{48S~!wzST+yZLw%wWpF1goF6XLpH%?Xk6%a|IazZh|-I9O0x7S5(sDoVydBSf;j+wUbMf=OhWqT;{ z5>m8Nqi+ZvSL2un!rZqW$7a4N74XY>szLOO*V-jFa*__3;Kpy%a&K_WCmL$Wr( zkTPwh^;VM=BU8M}a^X5U=(Ba0l_>!CE93C=%se1*mahfdDBK zc4eHNyL95oSra!osY>b9A#%!jA6NVLOD)%6g9{F9>C5vJGapYXwZot91zs;uswtoT z<-yY32xqfO0pUEb4NX`znDjjVYsE513Dq%qVQbr_+z2<1_zKh+K zv%J0C-Ts`D#LehUo*MW20WP9tM1p^JhWiLlkEV29osm#4yV#py8qw81)vt zJefQR!}mVF#K0a1N8P}~Cx=ez(zu^RPxua4f|Lh{IEp&Q zn{yiuL6RIt7s-XEpOVcaqrU&cZ(h>pQ#-HjBNT&%M{?bF!cBX51cP1HednuBa~yfA zZ-#nJ`U@cP+St1?D`(GHz<(R5t3p=| z$ExS!-@6Nwjkim3L!M_12=U3*wmQne4c)L8y$L(8NDQOJ&B!SPn9NsZtoL;*)Vl&` znee!(fi6uab-)I(DaH_5+S*(HMM9BeTI#{w*-pQtjrZf9=XXD0_-7@Bp`powRey1H zCRDdqFk~yCASWQpPMAp;>RDT$cc*9KyB1xQRz5v5N8$k5ve!knP3tpq1CvHPw#USNu)x`qe`? zVx%Ct(Y&!Wc;5;W)nKC#$MlV|vyrsPy+`tBt${dmGF_eiSjrI&10*}7HWX7Rna{Rs zjT^A3J+nQnRNRnFZfuvVBBH=Ft5B>d?t5#<&?#=4UogGaQDZ-N^@2pLyo{u2MoALhPQMN_CB*xZ*BuZ+Yyp@YqR z@4H7B^CXi`Y@wkDaWQiV(rd7N4XE`)tmFSl?AS&wMKgu3|MbBF&o^UxJltedW7I~; zF6L_y9jU?-B|`Kk$GSvKO)~ZiOD1L1c+Gu{J;q`KU(L-(?G(}1fEPqF%&C@uYbH=| zl}k$hdCH5;4`*-N({a@4;!wHM(2 zOA6*9L;B;_D-rqY_&a3;92%!^a%%HkjT9lKNbFLOHfK_$&7E>k+^Jo`nE1qZM9V^q zd=@q(WUH_8ca*shX?QJ2R~{SjZGEev_(EMm=`5uB@6#pq%lM(9Tv&QE>2>jC$l_C< z%#@iv6w2xv?}1yJC{9>$6P(fR*?+9>K)kG83HduepXz~zh*1Ojqt?_(tJP2z_AMH# zW?J(V3-DIr+#v^^cjp&&(DYyYTW&NhP88JEyhLrIfc@Xwb^%@h8oY20cabMw6hyAe zg>Z_d)2G-*PkHPbr@>$Y2!O)e4CFo8x)E(()%vDm$w>o-)8;%f7(5v8Q%ksDz{9(} zTrZFe)19(p+}*lo1$%=yw9u-D&?zC*7>bVc8}9OUO~k;6cYodRUGAK~Wrvl;9(i_Ux zLxdJSf*4) zB>O%ri;*_Ov}mH_G^e)}Htzc>k<75=LYtvBH6}_mAeuDe_$;Q-k$j^w4vmF@Vw@1s z)ASGnkfDnz#S^(*Ts;bni32Dk^c^*d4YI@FKxdll@fe@CaC}gU?d;OBE61q4rhR8IQVUVx zd=u3#>W{nuxQIs3wKPlC7e|04y;5d4Sm5sU*kvtD-VfSp1HB>EVK5Htw~VcDbX$bo z%-YvMF9del?lYIXKh-men*96L%=dvvC}0AGMuR>|K0)?TT{+)mAq5i56T^%f^^G`Zdz;nZ%sQm0_|hF8|ubAtUj#k42Vr1Q+w* zFNd@`hBP|%MWdl0U@o3n&O{ROGNmvQAp$f_L}yWM9Z8)b-^}kkCl?Ahx{{4?qk+lE zwq&Z||01n9bQV+3+prlvw;rDLby9D_42)g*eSc*m9&BA6(RvCurpP2{x|Aa}X$=CH zC?Nr9QBeZ{cfjrh(T&IDJ(f7sy72suIT<@=IJmF^G!WWpT}Cd9XS4a=6KKjV#)h*6 z+xZUK)h(<%{@?NYf26HSBH{_PJtPGR85j7x$GUGpf`=Y_08@A{0Wlj@FaRsD>g*EH z;MIvbG!j9VdmTY!JGFG{K@B1H@#oLAg%Pcd<{SS_VqP>F1V>3IG@~Do)UtOOX38sD z$f^R?j?WPk!j9a9qZ{a4*$<3s6r#X$;tepGbUo1~H8r-h3B8$Z7#C^m2mWH+hE?9M zR2m5IaU`~UgBtE5fXtWN9Mn3fST`JSRsIX9mO|tQrfv@@knw|}ba@3Z04+~H2qW-?oft~01{L>MUNQpQ31^njm)|>B+NXZ0zr1#xt(w*)npQV%(I1CajowJ zHK+&$&HE>{!{LLhG70gmx91-QF_my&|26&AA1e)aRd>3{m%qL!Ao+-^&r^x3k9 z2RJfa`Y3Q)#R`qXmK1*W$9l>{!oB+}v?z|~nQ3Z13-bNPVj_0LV|APfavZ#aF9|TO z9)=m~{;%f!mB43_5w6Ddf9C&=e=S0rL;N3FX=dvJWLD2!y;hd}pc+c^w2HDG-Hga! ze+%rmY6K5SmibI@0Vp}VH02H&#%UJTn*qOywSubQVu00yn+G{aa~sq9iPO`NWHlgV z^2*FHki_iHiibTm;oJ1$;f0$(`P{2@U4#urCbJqIcCSRig#aC+oAl7Pq=)_Gt4{@Q zS7Z9Fr`leDpcO^3jiZ{Dj;KL5C&C4@5X-|G2GLmZz2{29Fy|PRuPUwO3}qP~Yd!(G z`mG>aw`Jdafbxox!O&m@HVgj?l9H&O5x%Y)($4tUKMI3=+s4JvI4~3n(E>aw*(*-o zm|8F=PvT9y{+U0$+TE5&$43q+*}%d*S(Frz+44wHd)0shKnBLxcm3A(a|6V6U7UL^ z3_-6?B_0+n?&AGOgwo4#sRBoEc1wGq#NBkZ3_tZj_Ow0Lyq%NBnrPCwHRJ95aJfC6 z4nN3|4aDvnPhn_3`6?I5!4!l7PbzNbRtH zshy>Xs4pW8VpCKo{B$6C;5q2oudr~bLwD@@zU$UMF z4+%dIfGOI{K_n8dsmq8ujI{CSsgD@)D6f3Qo__lUk~LFoH3&A{4S0#VKLSH+pvLNe zos2FbI%(Vp023`t5(YCTz||PHwV4E040tz~u&N9BF7_CP7X6_jMeGgl{$aVOdhKEm z2leX;x#MJ7#@o1<5rLNtV(S)iZXTz$NE@){Di}XYW}0D&omg{wDYH-Rja>osC7@lBnpKVGwZm^ zH42I$GLl>gByDT?N#j#-I7>^&SkmXW6Pe<#1o~R^DTQAxq&O1%!pr$tzdS#g&YIy= zxg3}Apl)>4429m4))E@&uibf##si>EI{y@w16*Rc!)Byb3_?;;>4pn2Mr>RXUL`x* z3mkZ|9Z@&U(!?Ds+g3`q;Q=-`VZkfDfowgwj$Q((GN4|b%>(~ghX&`T^FbhBp|gjq zV?PdfD}AP3(@DwyvO@Hk;w^T!2dStRB_xBOQnJU&nS1Lyr=ZJuXI_wm|9FVc--6d$ zEl3M{o39oao3NP^S{nj!?C4jmp>s9)KfDP$)Sp``Wt=I7wMDSIU1U+=!gy~fU$636 z5RvNnpUVBtvmuT=v|~UsG$5AU{jr8E&2-OlSG?~v$g{a|@3xN!qY7}&+obLyBA%YD zKRtiWo!w6IW)(C>SrR}5>sUAkrf9su`*pYm3u=j>4gyib&;EC_PX{^qXGQyKcirlF zp7*r^S|LB(dQ^xHzWl9u(^l_%P`*G z^mB4{{$$*@i5S)X<2$^q$WNtcEeYb(Ya&g*n8O>$SVm*$ec(M2>9}Wh(7Z57gDipe zaHyJwELvZc&LsC*M1FzNThz`ivSU~mh5hN|5wRKjMZvN7 zV>I6haU~*lij%xPQ<^Oy?7%&n^>72HW)B^#P~5I32ei(MPJcjEz~5_Uhs|zzG5=@8 zl?7^-s7KoXx~JeT79QE=bMQTBw*tgmHhoL6zzKiLUa1DbM4PiRV4$-lt*)FP;bKqZ zmamqGqagXUWUm~tpA&=)K)9`ZtA51&0tPPrHiV2UicXzKmf}P2Loi~;v16vEW$64T zF3`c^-$QDvoBDF!F*wxCrNp_4NOqYQ*j9d~pQ24Bu||`NzPruaqXU?>H=NtcTY11_ zNyKZZUnQ^EGabljv3~cdnoTx?_7||F@(;RAr5cPRd06r8xm46VawA5uBaUoQW1sQS zK_~O5wGH)2GV5m!28!G)@Lrpn`O#}IXs75yGspUakYF2u&1K9G zMnmbIdJ=E90?;O1Zicdg@lI6;@6)YO>Te+h;FmrNH$vTmII=3Jy&GP+7 z;WHHn7LpQ!!v}j^{42CYFZP(4md$e`1(=8d^wa<`l#AVQ;*s?_I;W zP{1Ch_+2+n-kM#n2UM_Qc|b+6>oPr_?S{A1j*9{9D;mXjxOBuMW4;xkDYmAM5auGft`ab{m2d) zeCgLHVfaRqq>P7z3%7cL#F*?<086Fut?Q*JR1pM4lWvt*FLqm#USTSjmDB-lkG=+? z3)`;=d)MHn8KDdn=oYa9e;?u3@*2Es`OkCNz69N@^QrvG7bOUwpAc^5tk=0VUaP2Y zt9>1%aOfpJdaCt3pTEmwd|l4d+R`Am@0aawH#+t$ih!A}LvZ~x0D}<(xC4br zG4#+7vNQ$^dVcI=GxMOmI$fA!_nMl!;w{kMA8hx#HQVS2Sgf-pc+=k1lP%+s`n<0+ z{AmeA4W&2ia5i3hk7)UMjqCUF4rdOs$giFiqfrZS`ZH20#cST*PfYdigCCTha~CJY z6_FIE3|-P`#AMV8bHb#OCBhO0x%F>e$nJQ514#u%ag*;odXsN9*ta_04AeP-Jv!kg z^M2C@zTjq3GL6|;{6c)UZo4(X_gZC`fL71HJqUuARjO16#bt%rfy)6Wzl|LQ^3tEt zSBZ%q?yfch@C7&AF@A}O3Hh}~*q9&sx`5@v|uB}we`N(9yvi;YOSO;)D zcuxAvEO?@2Q_%V4Ja|)r}z01VU8<{?T?HnOP4%MOat%B z=cgP5@FM%;m5Qs)dgU@*M@mU3C_-@i1V)LG|M?6JxJ%LC(F1uW7NDkdRIkEv=s+XT3_p|tLO<$5r5VRYTy)WsAMMUG zfT1Hh&g=GedR=EUz47@;6!Mt9`QcPgR;HNpbk3ucqshtOf-e@~BwDKB;(ktYbm?iG zM&S0Yz9ur|MDy;=$u9zVOfo^7UdS)ZMW~xM%y%NHyQ^S-Hm!(k_O;H@^+BR9R;T0l zV=HKU6#P6BIpzUJWYGxfsnAq-ts&v>3^*TyqlY=9h)3@3mVUH2A z6cMrz$(qO)>fdwj6f@uLiQyZ{y90lzA&3P{@O)b0kr(rd*U&u$7M|m}8qAbhzqg@I zRwu}pT!2X$&4T6d4+wSgd7b#?wZFjIXI+gB&jBi)JGFmXkY{lsvx9Nht0Lh)F8Z&V zwt%*(26@I{S7elJ0uV2w@Nv*l85z&H#&Y-(bj|9Xl#0s^^3eOaVBglQQRIbcbSS;> zWj{k6^c`1^F2aWAGymEHd!bZW=yJO350>|p&X&AMBxywvvubZC zi?cj^2X8r3k*NYkx`Wl1osp`YzQWb(P)Y<#3qsv;H4}#zgjFKb`tbhxe&W_4w`;z= zo@Q}VM&9Qk9V&vBl0J0I1JHN-t$;jC0IojsETH5BDZUGid&x%|jC*p{b+vwnCeD0xg1se@mdnVY7nOkcy7nEuoy{i1R=uG z4DETbiSrZMn8%&ZxW)|%H8Gg__p;-*T_S#6oUo+qeo?;j<-zn!#I|g7TKl@zn#0I3 z=hLIP=Ncn3UhxrjMS(wS2-9hKp$zBC@t_d#C&7_;;(F6|CT-{)6WSimz+@vU`S6an z?%>Rzi%SRyEkX&wTP$2)!17eQ4OsTvuc2%D^-91}X{1X_Aheql@}P=&%|mSHnDLu+ z-d7ZIb(OaGE8cL#Wa-q@A%X7$=`Dkx&_c^b$2YPG!$gT*j^vbVDW%pKld-L*6)T;c zfV=AXmrJkxh7Xvcb%{hVN_u~WgsQE-(vxkyxw}QE3JJXePan4i${3HX$;5A)C$|R3 zH)0X4|9_GyAb+^Sh;JV3_8IA2OU+Y=ieTrgZ0G!S+O?LOG(~3z5HNl4?^`&SU(72s z0qb-R_&+X$AeGHV^bLj4|qrjE-plM&lH~mKhuq8;q1_#Bt;$9gd47s zC@C>|l?*Az>RJgrZEyNJn)9wU@Z?LYSZ`u%}3t1H=5O2AdJ!vr#_ zE>kj{o#fwxfrM&`oj}+58iDNJ86^oGWf|yl9w9v}-zX3n=H*Zag@v zE*6^V*%=aXuK4>%3soKwBS@E}WafTpo#{8xJY-p`z(_J7G~T!Ot8bQb(J8$i!q1;} zB+T&G{r=jo_ib8+mRbPC0QGvnNkER{w%tbJ)?!nN#S5*p|6mL#V}ZMo@X60BkXYjJ zUTiDOE(T$uXmZz6fiN9g5B~es)3jFv+bPW(zFU+qnft6&NynWI&MfluWzwdx>5{~$ z_6df;#Dk;g3;>;lalELA`YjFM!UUu{5S{vLpq$rN!Ffjt|G^rry2xuhkF8`QZR+Av z0766mvbag7q-xk{><)ejHCZ|9->T=Jlc{_ujh141HTd@BtoQCluroy8?ALLF6-rg# zcaEz3#8t@^Arj)>0<*7Yxl}4{w}3&Fx#yxSL6FNs_^`$;XB3w<=9LATmU(TrWRWg% z%T>x{CNp09eT#<}qna5@g-z32j})_yNLeEj?*l`;!qn;#@WF*KZFN_3zo2g|u zMVI*WGM9~IRm5rUqh|66@Qa;{d^acCIrAk=Qs@Qq@t<5GILOgZrypXZf6#|*U4L$$ zZcg$qr9%`n<;Ll_${U6?=2eTVvi;i|XLBI>=1@rRbhKf&gu{D$>!6D)6)rBViDM!B zLLM2mIml(A6b)B064TH&`fAcT|qnB7I3z7mGd(yj8=* zyxK-k`UdoDvO+&5Z1vQ#pZG3yPqPkYZHU#19TD$=@A=LS1@BGmepo+T|6|rCdBmX! zHxV>ZY(U9sbVA75RJ!;`CPYJzd}&}S9p@gR7eiG&(OTio6euqnshv?9&HqH&{>>=Y zIEB!YMQoPtJMKh+W_{!^Jqx2tQT9!#dl4gkyB?2;`zWGBFnK9&$>4HDaj7MtMpCPH z9Z-|>VNpM^Oo-fSR;&Gs(w2~$^pQ^~JgVu-Y-sBz%ia|g=ayy##M3fY?zwZ8 zlKepGNHSuU`uYaT1_}&Y@4$qgiBWeeu2i1nIf57c=c7s1Jey|>Y#qsyua8{YBv;t& z3>c;a`Za%(3w&S;NEB!ZqP-)QBPmD1!b|}@roR#aPNQJ&i2ieXU8fK{{!LPt5kHcX z2x$I3LN}yt5+TRmR%vBXVz7`@58JExik4KaDg1_QLH4zGZuRO{Y%oYf!3_wFM};wq zFcqc9J+j0f7}^YzV0;=M-;Fs6QmdgeB2sU~jp=Ia^mq#}eI^61s0*N)5=LbP8QtW7 z-XeYI$~6axIP;HxeKoW?VJlTgSD%>frZ%}I)n6x`fj80bSqC!phf8dw6sKCHeLx3lw{YW{*mySe*jdhqfAtDluNV1=0EJ<vEI+ zV)1)L!V6?)@M7RE*bi|kBx(b$R%inC<-gW0Uo1rW5rz>Rxrb}P+>2nkgG9J29cHm3 z|M_=b)jk5m&V=w>czP;BdiirM)Znz##@1-~5;#bCH@xNrrU4ht3b;{Z0m`(1gVxRz z=7{hOp3H!jhz|l83VoywD2R%*o#PcE7<9ky_Tqt<8o0DgLNF02?RhmM>rX46yPJuP zU^Y2{KtJO^ylW+Ftk#&XbK$z?0GZ=P+LcD^nC;}Rz=Cty{ee}6LFpD{7MIwwEL zwW&tigL(=lkyU_>9rO}1py`qb!RPtprh}OUvxQpDKV74fKlEScPM6T*AHEai|Jq%@ z693m=w#G4vH?539gZD)xam02tI`LiSY;M61ek19%POcsyDK1F?jI@3Id_@~_HdbpD z5Vo7q!4r1K!_KlcTB9?`3>uH^RH+x=5ot8$6)2oM=`8s*eu|<4K?QJ^TT*mj=-0$0 zo;r$iN3^>@f82+{jOH)0`K(yZ6B8+YIyA0MEn(m*7V6a9t?b zPnKlHUzbfN;xA8^-Z$ws)d7RpnO+SM{=);m>!7p;&y-SV7_gu(_$0yb0Y)&fvy@!X z0%)sQ>z8mEdM2+fpvYS3Zo{OtSJhvCoLfl8nq~y6;p5?na~s8UhE>`}5olo^rr~4* zxiqgXNF<#=fiZd;1m9Ca0&nJk=pOup3)~e}s+3IC*nadMmi}C67tE77V@@Mo-Tw#p!MZ+3w1jo16RY4q{0f&W^|02Dkek@&$ zKzY-1yTfC2$1KfO7r_Bz?dsGk_d*G!gq7_#B0mi*HjiEl1wNS4AFQ8b0Gfh0 zctqQ!f_#3?<62HZNXC!}T9NnbYMVR4YFK1GhxKYk$q#xuFRV!nOa=wU9*cHNk-YUK z47zO0>3aO!gqNQoU-OrNAXb98 zerHBB1b&nF0(HF~DqERkNJR5LnS@iMJ3wwXyr|*NF>kev$WNcvW4S!}V!b*p|B@UC zI*(@v1)g0(>^u++C??uor68e>iO;cLQ@e_vrhPaVYzX)=8iz(AM?woA8E}0kir2eT zC5*8$DS{ClCfhFM_N5UU=+j{3WCRwMBuC}e9y@A&#!O5 zQmrYXa~seDbO`TumZZs5TOok)2 zYx|}4;oD^)iF!V~aqi!m*;%(VNS&FZht`dom~gifLHXoS$T1l=rY5fsitCFNPB9U; z3l&ui0KNr5R|=L&%^|MyWAwZ9W4%(n)KRP!CBQICuY0h#MqyD_36Qm*_(Lg4RE+6R z0qp#H2%tCK1%-V6T+b?hunc9$|A0C`{m@sS0$UY8_|2G=pEA1+1w@+fQ(UIRqr4jm zgtqKtmkYxYfh!{v0p@)!ttt{&j#a{FJk?_0Jk%!c9C^l6F_1N64Bm>AY z5keGvhRO-Kvu~r}YIX4leP;OVZw-zgkL!d|B>q#IGki>!p@}8dgHd zoxC}Jk;WVc@_s2caaKr7Qs&E8r#Qv}d2oFyNtXq20hjVSwqdd z7L@|wK&6iySSh8y_+6`$zLFRZXTEyBi;AbUZV$v$PVP*P!WWwL>wqk?gEyIie~biT zsgWyA0Ifg$#VJJVP7da@;UZ}t(5&nZQ;euD9Epl8bW9<2$guJ$qF()&!AoEAh(hzf zwN~qGJaT8DCS6gN*xm%A;W)jMa5Y=&w=|V;f+U6aq*ZUOcZV#~zGJYm#9&R_$?_S`c9Xrm;6mb^|mFL;@flas=Z@4-=u>*{*wsm(Y=40A_9Ih>|bpXDPyb*aH z*<9IF#G`QDPv}3@|e@b63&* zVnF`=SAMs*m(%WBTnvG=D>KA1)mIxF^1Egip<&YhI?beO`=nwncvxXtV}9We5bdbO~%3#DuAx+Hwgt_XbI3Gj}ZaFA>T|?3=abo z4tF&5SlryLfQ#s+R9286@2wtsgy;xHOCC#D}sVKppPk)r`L8>9?TduKK?ABlH1GmHx-a3({wi7sdeQt-r6I=h|oe{yJ!^3sB zc^ulIJlA1Fr%f8{IL>o#jhT3QE^+I7bm?DiJgPa-#?RuH@90?QS)`?7$_A;VKv$Zs z#_qr7J4^oLd8zX-KeFp1f*SI7UrjWd!(W~wWkpjpJaQC8om`P{JeWIQjY>ZFkre-% zy^+fIz)O_}d}BOxS3n`HA~`+PLS8rc3+nkOJL{Oj1uf%t3-1AfGGczDFjC8X0T`DQ zU0k#bwN+}<`PTJ=jem10Z*F@C;c0+yqthcXvpi)AG>|6DHH0Ix@hwj-9)9zRG0f<} zD~jShsaDF{3YL=JSz{*E?-JB8g&%exr}t~e(PXIm(G2T524{?bmFa`am>$yZzqnQp zNR{09QbZ0w5s>IBZ1E>r&8TsCN#^|3=s7W+ieV^yIs7>c?Qg6;Ve3G1^uCD?F8sM0 zE`hLsCabj`BXwLiHC>Ag7JDQ=7CR{Ql9rNJef)SrSvC5j#k^8c7EHj(nO)?k&bz>A z8AC&9Aupo`rFr^|u$SJ63mWQ?j!5%YO&?d;K?EnF>h5E1M|~I54YPA98zu6+or~Kp+D>l zrA;+Yz?}?OQI_uA-JP^c|9USVxAMR8;zCl=Tj@~ghc3)bqo_jpFr&3tyzo+%8)?)F z`Z{s1-e-1(w9$zfa|RNZ4>UDwHRjKvEl5!P41Hr0UEo2huI2nh3mKJtsev52ydr+Y#Vg8_4+PJP;F5PN|Pg#qdK?yE{Z3=Un6RpaAej9To&L%w(gn3dDALqjP#Pq^1+}b|vXkpDmyp2Vl zExFzCFp>7=>|di|9m~<=%GGMi6ii9-l7`u(N6NgFr`JT}3cm_@BI)XYoEl{G4eMdG zj79=R%=$kyg`PA+twrCngrYoOF>`JySk5LGRZ7G6W5fQ z+VxqV%15LLOrHXmcuv@_5q?82MY%{0CWPA;nET zpAk2@QOBH3M^w$I58&&!=i(@C(!T+J-q_lX=J;Y#}ZRv5{7h@Ye3qjfl@gHToL9%=Gd6w#*3 z3o9oRXIbzSyPff-JbmY*oxT05Aoy)=ubj9$Pu&t_cI#L_MmxoBahMG$tq~B2G7ZMY zX#)b)XgMd{&;-Aai=;Ejj}q*5phBZxUxQm$_M>}35=-AJFXs1fW?;TW2AKTGXIlhH zbIN1shI{Utiwy}Yqt_~d4{=(+8%(u5QCmMqf@u9YQlx9JO?hUc8q9|dnB*DuG^dBT z8Fu6O-+{kl^;)uDVs}mdv2Y;6Xc)5x!k?UGib75EPfdu;vP}g|C3VWaJ2Y2V73mIr zQ9?saSluTr&v=z^Fvhw2uh3)GQ@%ts>6;*E+Adr%126ZmL(*j)dH-kJ7C8ost8mwO znvhfqV0?i1?+8+ap)AFB?PmIHjD9!(Al=s|=y`6cQ>{cV3aDAP?Y`KL(e-F!tx+eC zAN(vwALWXC+IBSLbGLb|v^1+c$&|#*DWa|^oGer*W?+O-Uzx1;|@9FuBeXb6+(~lgIAE!1U zDE;uxkDAI)_`7*klY1HRB0oqVIh^7x5BaHT)w%=m+s%njabsxx)h4CQrc-FZs0@NW zk@b82r)K!$%t5Viw~p}eWa-R!?Rv5i@NX^SQ7M=FZEZgY`w36P`?No+ssqo(r|%CZ zTX?JkrlTQ-wgdV77a2qq@)KRK2~{#HGj^P=Wj2w=Sb{X$((#9)>JV=TX8FQjpUt$} z{|iy~{%-I0!rWWGfKYEN`od$0NjSN<{viMMwL7^czB82PdeUMuqxBPPN{^ZRU#tc4KyAL#iLDV=ps>$Rb0$HrsNmHCW@DLV z*`E@FiA+9{#yF#d+t9yXuJj0j#)iW@bJ8P<(PJQPwA+p!LJ)v?zl^G>zvdf(w@8Cp z7$gg)W*E5+96Q5Up36iFSum}Mm6pndFIM5hj{n82zbeTYB_0ea==kgOSXi~Tf(7o3 z(sr3>eID-9!;OS|^ffBJ%90^4UZSU&INMbQ%Ha?gWvKR__GEuDED(g5`djz{e|}=o z=aoSq)^a6y*&0CTVn?Qn@J-{Ie#Rduc_dn1%O$>5Ca$0YT6Sqc)NF5)P%C(Yl$8~-JA_Iv3wvTy&_e2=Lb9E}{x=@9 z-MG}Gpito=%3OkjVdA0BLd1pUJ=t!98Ac#zEh9mD*4|*NWTR z97Woko@4d%nCUJp7N2#NiaF@|dUEx*kkxkY>$6))m~Bk{$0E=lsl&zK4-zX83gAOD z0K{RwvL|&aHvRX>*)Kw#vAp(AU8RPr2028r06MR8jS7k^pk||f-}jA2@zb_P=j@;t z1d0BSWpZW((P%46v>?5WlZIRrO9x0D(;sGhaphi}!sD%nrd#7rh(7aD`kVth>h@ow z)&3(J{2qVOAC5`(O|@Rn6vttTZ8ux@MiU1kp(4?iz9S^?ONj0y@h6`=t}lD@ zHfGAV>ozZ>AZa=!*c5O>K_GbMh<~{I7YTTT8C8If6cLBED`K0&E&KS@Hkp>noNL)T zgOGyNL2O|&SkIek)_FRx4B^MPpiqBtjw}2t`Ba}L=(QBFStww$f(AL*1nY|=neuWv zFUj|R?nylw(e20{M4I}WoipemGdf8uv8NH2#%_x~1H;o1aW4h^gi( zW!qPEi`S(T1jGf3oMz*$%F6CU zsLA-Me`k=ZvBkJzCu)dl2tQuS?t^fWEdNS~qZ(nE%&S#SQ&&)vMS*@9wMqIrn%p5} zaqKP6b(JF--Tk~?nwhds`D2p2Em~E0mv(do41EZ)xdv02Xtx9DAqJEI>1#m3WGLPP z1FVz=dXm({qgI?Bg~{7Llka?|A+)HfGH47J0!o%^o}Wg$zyHBd-|;*qlz}xzp#I?} z=n$*@$Tm6u$M0*F#vAtL%P z(Q)cM?aEkoi}w4uCZ~=%8*F3$!}rI&&O~uB6nb9N^SiUOvG0|D&|U-le51IOobnzz zWK{A2B!Vw!;OPXQz$VOo=4AS9$Zb6s9(et$ujQo4rE*zpq;bJ8Yd|i3;K#G*Tt>}mZBBc&_K}{g`D{o~%uN94h9+0ywXlM{+IxF^r+q3%& z-XpeTs|cqC|BYEf?7;Ss67%s%f4NFlH62i zztFR15gq8mQkbP_oZ}3?r*oFRat7Xkz@8&ns?2Tm+8eHsldsKBqtKMJFF|}^-uioS zDqQWzwT;?LF(3F_Yx%p)DH+i|7}KX%e@j-j1KD?yRx6hY^sVAAS%(novA4%h(Q|wU zGt)iD?Ib0aa@TxtJNjn<0Ql8GW_X0rQ+|zkx@=F{tt-(d5tESgEH3IIGP*%Az+_X| z$;T`sIbrnK6v@vPls$0gkaW%WLKO&Bv z6wo)*iO2iu8foS$ju1bS+g}Bb5Rr#^v6nkl|7QodpT=@_q#uIjW)Hqv6(f%4;f*#X zaix!~`YlPsv+WkH-{;`c2FfFf2QKe68Z)FO)IwziNHPDL()A$10*f*HL4Z2Ttn{Oh z^;e{DZaGCdl0gsJ-CT~zJH7_35^mjXSsY|#Iy!oW!<=j(*|#`M!HDM(gwm{p9~?_a?Hdsnb8&HTLRQA$s3+xsIc|m6 zKNP%|Xt^kgSNKq2$NiX|Ej%n#a*!*z?6kyJ6hFDBqH~#DgZ-kIHfLpVAxo5<&5&{P@j! zg#LOQIf=n?E0e5)rnJzQy$1)=m*fdwqc;8FB29dgj%$p&Uvkca=fBXJzMF4;V<7jU z8n=e0upn`qye<`ByaknXW?Ekg{JqjvxzlA5lcceA_Wc8$ncvC=M$!@c`ayfd!?o={ zFaHsQO`%6cG36O%V$RDZzihac!ii+j0O4ECfdpAtlhk>kOe7F_!9+qwTZd0~^e$zd zN|Ghs;b*&F$&{xSGnBTRF=`qC%z-!wjX)p;y;=Ef<{bZ_w7I_%$cDWrC;h9Uw7QVT z!!_DUqZ1cldaG{0I(YfWfPT4?u@G2AkU;B&8Tye+W5;>#L2Y2_cM(c12v3zh z(x(t}{24a+3HcHQ|Fw@&&wrQ`R4O#h`4%A9+{bJ){cb*no4ah`7#%-pAF*w@@)JBj zcJ^&D!kEb^Z_lR`rc$D$9l9S&IA}85jjRRXPZ;N&XKPDq;67T0cKtOT&~THP4G9=0 z%D1RKY#LDqD|uiN=gIsPIlQLDlWc`FSKj*o#|9#U#lz7DAY=ROelIyX2RY^Qw2FV0 zSownJ7GItp&tqNu11=KhONSWoz5w#%E!od88B;d@ip|^OMcw_o5vZNE^%vw9{!6cK zoxr4DL6IA{b&K$g%}^$^$qm2)qYAlyMqi=dY4nNd(Ln7jN|b3->`n?^8Uq38EZ)6M zc#{%BW@HMD1BqT##zrw!)B2X0Y{ty66(*4*!hNO5h})Xi!uI`suB5_>^#uMQfi(NR z9q?mCeYFeoArOi{2gyg@|8fmYNYBaXX%PQ#&-d!kC#mBEc>yN`_h8@kdJX__s-m0C z+-w6iw*aX|dNN$TN9kYf^xq+O{Y$B?T&~+#=zh_Bns<5T2bkU(qi(d9kO1J2B7>^N z5zIc8M+Rw!=fM(*XC`I4wSvd0$dik{SrwnW+!~C9sZ;gMv^Ss-r3M(!PuU`pnuHne z&Z%OTA23OYzDzULEaz$hn2f5qKN2IM)k;8^6_Noz>0(Xl#55k}+nAjw97XY-B#VI2 zpK6)u{3DxCvu|-G{e=qs4ar$K+>h`0cmTYxQ9MWUf%V7Xbpc?I@RFtPtdi0|!`?e86Z z8{*OiEP%1!@R6zB$A#+K_6K{9m?nk5>GtjGaL*;}3RJ*VFgXQ4k{fg(?%i7VFSn=} zF+ALjV+*Lt^$2d3>_xp(*^^oE(va98YYzBX;r{n@NCX2~oQWy8po|;qE0OjwuUo9d zyy!^h>?yMpdvaD*a0nk!dXO=ujc^KbP7Z0f05AuBaj}s$$AQSlzL6yEs4J8d#3qG$ z>di#8*c8*q+*`$=dX#HnMdbB;JX}W_oZRBpgxeFbjE8<9Pj%&~`l~5``YwYuW^G`sW$frVN z*>IAkTv>P8`$R-1P5V9AkSR(pMN5eQAsJDX=D2!kia5LIUxH$QORRl2GeYAM5f+!S zO;?+_h0{Am915aO=`f{sx_|den+TH=*F8J>byqj!ECJI0xFW>sb;_Dwqn$Tos<$sa z{*yC~k1UjoO_o%bM+LSWBPk(0z2O159 z2p(6Ep9nli0;Z>B1slR2v&P?eT=xd5M>RVs&60YWCa7=;C`|l`q_7ncH=6G=v2dT$iudMm{rKO%^+hwR0M!Q2-4kTa zSIlriWZ-;~6M*DRK|?d!^+6C%3K&EwsVt%7<@;BthudY8oaK(;nVLhTMoshrc`%OB zDCN1);*tO92TIf16}}vR^z=A~5H7JJMXC%`x0D z5N@<#YUI9PY2TR19!u82)IVL73v@XfPCH!@S&QEC2uav+lJIciaiJ`;p+kt+65aST z%FkxftCj07GR|Lh=Yl&m2^QO?V08N#Eq9_A4st#^l}G=_O6yqssQkU~D6DgV^$Nr7K^R zpv)HFdoLT>sn;9^Ez%^p>_zh~CMJ$#{vF&jg>1=9Ai8Cfx;V^ISv1G1KDqjqepzmahU z!1n~;;FhVin_wR5*Jp9VDT=-dfsLw=kU6|!m$%N|?^L67DQy{Rg>|9Q&+B|6`yvc~ zLC@=6Sxlo{ln>Rn&)e&Cb}plEi}1vP6qZQJfrS$bGLR!N*O<)Smfwx0 z{*;9jDYrldtnp!j!esFg>nI_9RL%7n+Iy za9HrFGP<9M59LfN`PaER%?9cPu~SC<_8uha#87dzl=U@wY3Sh{6bF=HNeYsFyC~SU zj`F5qmP$zF@f4TN-MLg>cA-|4YzS?dKZ*L{D1om=abM&_RdB+8(HH&@ls4>2R9oYe zr*9+QFG?E%JQ&7dDfw7{yg!)^n^zfRCb{j&J&H9&-(o#4PNR|7vHSa>94~`cBnJZ^ zm-t!|F^EGUG7SB1CBC%7s}Lfff48b;dmG3Y>==%!LXD`vvRF)X?^gF_E_Q)cuC zQ!u8p>85H9GesLm-krUNM70EC2b_o8WpzK3@d~SF%`jzVg%wU{vnp8zc#v8^%8;eI zb~9>eceVm6jEKX7DMUU209dg?37IJ6md?n;wSb~#wOh*3fooa^l>4~O?(5}`tb~Ym z{@Lxl;deHC#B^u0 zROXYt{+rrQH~u`LkmD6KkC9+$Bt%~EwZCKfBXtk=tUf4RjgOI(MpjdcZUaGoWq972 zS|1r!QKX@FSojY6k*#xbn(>Z&&b{H(u;CaIQa3D=juT ziQu7!`$_|a=o1vUmB-`-sVU0y#p%9ns;|749LbN41GdM)>8;A0d1ivetMZsDwqA=l9BnU_~E zGRwIOJ=`u&9k~l(U1*QFr1`I+s|f^W1&<_G$(CBbvQL1-3?9Dp@$>)W;o=ny#SS{? zyIYlb0y(Z2-%L2@tuJ%XrCiIghWq}ElSYlt3vxw9&^N}b4k29OU64NY-14s4sNrD> zgu5KhD5ou})0*WSV0WM%-bfJ@5}^=L)5zWXm9x?Wqmsf{c(WQ|rGehKT z`T(_Y=rkV=uK1c{S~Iof!NSuKH&GK4F6Hq)`v>0KTit@dLbnsn?~@@@Eg9(q6?>QW z0U=Gyct&5 z>0@p!H9(t{W8cQEn;HxA?zivd_Z6PS{Q!w?_|Az%Lj$w3yNQ8cb!Tm4^L4#0ubXpe zbeXFiNn8t}@owZ1PQcH1E1Wz$1&ONR)>?T}v`bK*(HS6XiY>$;3eVin4xgu7Kk~hN ziQZY%*FUXZfG~i2*TrnshldGq*!h4C`GSxzsZ}Hc)ISQgGovO!(fugWJu@JR$9n1X zo$3uP;oYP8)qb@FLcUE02*4tDkNa$#7;Q-3Q>F~^yFD@Z5HLHF)H5cqfi%;gUZ&{( z7~z#%uE;NAhw2dEfq8!4(=8u5D)EL;N0PdrdiiQHAfcl-pQ}w`zRDm1`)L@}v=T>g z*JfWpVGk!P5mrTX0|3;K6dk6a)G-w?*z*WtnXd2-kqaKz%AxuSO*5U=$4p5C=Izs;3HVsLqYjvA^c##Sk49dGhHy6W0?Y{_2u{ z>jK7jJvUk^kedjE-{pTG?i;#}OQc}-O+tV9jk5;ARE)~uo6Y4~B*%(Yr%PZ^Lq^Ko zzn^drNB5PX;4f8V>dC6@9I61y_D`KLvLU5+!iRQ?+Nbjk0rWIgpf|zL-qb37YNGUj zI*LKOQ6oHME(q}@>w6`usNwANqBGu&r|A>_*^Pa+&qaxz=)-}u31pHc)wgY(s5-cS z0}JpHzjaDF@}40eBtX&NT_TI!i%$>loLZAgfcv=6zPab6tqw=*P>AHXe^p6fO^v3A zIML1kM50Bz!fT@$319N|#iT6`&%@~_IR3~#pB5-l#x_pRu(L#)TR5ZPOYc>vzsoYu{8Wy0a-J_CuT z2rEZbBACUJqo2vugM?74FV?bF8Le~cpMuB%i_(Q)7kEunMk4A9N%kmuEBiB_bx069 zXfp8~Y+@ElF;^T_%ed1rB)p`QGihK$*!s7^c-9S!$2C$?OFy}${@wfbF(OWubX|u{+uc$-}&-_u20_pZnke?)H)>= zWibI_(qu}kRC}MRh9&`M8M{3PIz*#X{oHFBYlf}5J$BOwcnOjlGHA+2$(_M<$c4DW zWJ4N0Fm74fG6HIxK`If6t_EcFXahd3XvoRVZKHv)dyy%RtkdZ9myYZRk9DP!C?l+# zfZ?7H5hn!UT=RZ(qt0&G^=Q}M7YjW5&`4>S$bqK3->G3%2{nzjMslTGl^-8=*7$Bs z3MoszJt`RbWu5I6S43(72`&EbyAxLy}?TL1V8Bk3?NGTBBnt z#`XMY$jCCLu9smu+}wFx)9$y*O9Bp%yt}iExZ$MEvg+E8mTWSq<`5hBeFk1VppJcA z+kyP?N2kGYqI0>B-A3z9NA&4MJ-DK=wXvWrR<=Olm`rYa61m2&Te3)z^}F_$Y@_R^ zeNrf6XY`On;YVNqLpBHAJEu zQWoL~Hprq7Za5Pcepd(5L_%a(=3Gvk{i}GF7C&VZ@QAZqUEyz4{sY{~C#=>up^XkC z|MggAe4A`Deeb{YpX$&CUbn!KCeX-*-mFkcTFv~oyyJR^LTKzA9QLzd@Zyjy0{6dG zi<>BP#n3t9r>TBPT`MB^T_J%09LLKP+;G)d92HStI7O)dioKU2;SnY?igS6QX}f|W z>Ja@Jo?Hz8jgiCv#{a2N742%^t4yl5*@aO5yc7C-u|Q)EsZKK8bdTFA`42lK(bf?J zywCcVd>2)s*xiFR9i9671${;UDn;6B(kR)~XKvX7Z8`fDZgoxlpA|C7zS$q<-A^8U zJ15*MfAG}1i&Lwo0eR$kNg-0N`pvlvgPwyrlL+rng z6wvP3aDm06vF})Q3Ndmhm1N#%G;ioS>>V4s7sVgJMY6=GAlR&{n0E(->dG8tu!Gy{NOK?Htji+sADlsL)~=iOz?PnQ{IyaRo!#e16QR!km5_mxg@ zH4Gd1svb@YjX49*2&fIWz&YO^!4G$R`oL{25PV|2KDXc2#W0D9uugR^b&Uul7yq3< zK1XvpV~->}BxecXx}odvTb}gnIq6N~i%1z(gxomQ7pwQ`6+nsSBFy5(Z*%#gM%Zl| zkn1@VG@*isA86cg^nP+J)gcegm@T@8mjr_H)JmNPycP*}|6r=f^|RS&BhI_~Xl-N#_2c7) zNF1h8>xzif15`p-+ZEZ>$FSFKIxv$A_JCWZJ23iP%T{i&lkB`d85R=HchO%TSAmK# zc}+}0Gq|xAdj*f|yIjFGIZ1-P+CQeOI}b;=9YvO4Rz!L&cYK7h0>nd3 zn*{&cZAlDv9>FaCZtIkUcXw#CfsQ(kPX4Et@_5A?Fa{PX;?G=PC^o=iooWDXfq;CE z@yU}HM?FZ%q?3xQN8NmwE~sTBA`sV}xhC{o2wiz)(aA)|L7u)r2PCj&!{EkxugrM0 zh8@k9_rswzbB6KFNcynlYFEtr4zs0L4bvcw)mXQBg=c?%{N|i^y1!mu+~nlsE}9&w zPVO`jX#0CnXs0N)2n!)5ck9OxLTU%#Wg8nP?tMU;6@~b%;Zy-K#r|xH1KXpM!gz>9 zuSFt1nPitB9DaIqamC<7mOhT5rsH91t9SD%kkFK2BSU5tG#i?p>(oZDH6+tGD>GEM zf_+T2@1Lf4Ev3lJkg6C_p(T7QlSaPzBfs>J6^rlhZ z%390`YQ3C=2JDp^6A(dke0AgUSG)f_IkLT9?tO+?{MWG8RwFPsT=B1epm4VlNYQr$bYir!T;|d<5|2L&ZjH>Z5 z88jS}oSEaz&A5*f@I|pY|FPPu=jA zTI8!t;E0&n`q*YvQ%b90N8u4NBWaj?&T>VY1>dGXxv4yVX1`j)Q~h8aP`Mcm_uB&j zivXlvzP)s59a!D>2Hk5U+42v3%X?~I&58t+1JoamMGVU-{Q;-lMRlUqG|%5~>o(Xv zE(Ztx&Ex@7Ns;+v!gUa|!{q+6xp^Ie;J+iT#n;Nwo8DtHNbTGZ$#CEVXqcEcty)tT z_pEYjM~y@2ppr|jMa)Ew4b(;b;jvlh1S3kh6)Y)lF_^xoYD7`eavCKh^rodZiz+9j zR|~%iTe_6XXEeeM91qUn|Kl=>twf$X_k4paI;Odm)+;Z7Pq&B$bs%AAdb`5r#AeM>CHx7 zEw$hv(!1z%{UgMeV$>JCuP1WV7JoYrOjU#CHXe<_l&sE-TkaaG2R`T+H99^|t@I@f zbJ8Y3LO_s1+Jv!b8tu;ftNJ3Ft1YzfGP|?e|L&vGa?tq%o4t8P^fLn;r}(>=ZWA#( zi)98881dxBgzLB-q{PumFsCo@7rlDjiHqtbEFh@0)58g}gv z1M~mi8lNn2H~3;2LoMw4xdTqvDm$W!I@VSKETuvSScXnQ3O~S)k_asAwwOEl6$JkM!Wz zf<2o4*y1l_g4O-Tunrwq)g!PK6eYVkFGccrS^Itmv#0LYQa8O%$2}_-&L5WWX~X z{&C`2g1I06(?Ctr0)~FTWlz0^GLyndbZNx0G??IEIoXa{Y$GH0QMP*m^X^v*lt4M4 z3fb4sFSTQ%05{j5>UcG1I1~X}WsSJd;@{TJv@s!Gs<@0Er{QZW{IyQp2%Sexu3fa-3)#OLVZ zuyzz}k|i01z62!{85{w=NDI18TWquPSP^1Mx;d@TH~OJX7%Y?1{kuN9t4sW8U&iM8E@)cejB>fniY0H}3?1n)^lDUG(TYz< z$+R%{hF0^gr<;0nKUX$XeUCDpxAsy`#8h_>aP{9#HF(I5p&n}emn#ez!S75QC;D8u z1%ptBf4$`-Bt9g}=^TUoNz)bFhu}Lz+-F-&{jWn8>h>ifS<;zZqlQzp)Rk1rmX|g- z@b~BXrG%O+yfOMq!x6_aUS(QGCK_a|j0s2LKcVC^e=F9XICQf8@q%A#%~0y*~k^AP#8l)a@Ms$G~#cy1;|^N zx2|um6JWvP1?kCG>b0W}TOw&H9{YwtDKQ&(ofOBD+?|CBKF4}P7B6m?Ulq--?qek&usYg9c!sjj zOYhv{jAWjf&zUqtvAAKp2&tQ{g=P+J5$tZ!2Pnos8sLsSZ0`8O+_61Y?9zloE(kwMHhy)CQ}AD=9|8TdPLF6dV3tdDEx^wQ`w-wZqgfL{a= zzg1Cw+=Y)I`T^+~I+QDFcHlfaq_F45@_qcpZ(h_hUFf$w zL?4s+qPkbPc2R=0e;b6L%fNo2aYSnB{rItDFBiY=Gq?BeM&xvp-cLcg5ZTi@EMB$Llku<0j5zQ3I8I0yDgS9 z;UAHjUGXVKMZorWfswyIa>W#Zxp&BZZsX%D1pFVq0&S$c<#8VVoo+R?Rb}>>cT7Br z-rvf8!ya|?ps3IW{8ER1`eo8r&FP2s4J?gDAUOCz>|1(9JR7m^gxKw-ci?^yY^oqa zOQNDWLenpFIFTA~Pae2C2!jCv@6&=%as#h4Ld_zjG`1$-#o_y^3PUm&f>Hc+!wp!g z+<{&iuR5lOo4<$xFzoiI*iTw`x3p=lu5V3V^Vdp0 zx$lT{^VA~z7ClXPp+UQ!Uxe(cakAfxQl{_jCCYDrPQ^JLm8g(cXV+_~?hoWHQrl14 z$}c_d&ds1L#(`dntywB?jjA3>G%FFbCFSU6y&!hFnua$Qt4ds5_npGVfqbecROoEi zVu2Abwjs3pr=rfiF>cp?4ZZkkOv-9y^z@%};%59dyj((?DdRc02n(kNRtm(H0j7Qp zL-D^3D9Ihwdb3Q`6C#qOlmdcj!S;BiO5jIjV)?}LAVpw;qbB4%Q}HMn9Fh>7BXZ_D z^5NbIKk0F@h|i+LIGVyj*+-e~9VtTdwt!GXujbl|Mm1s7OSoy~X?y(_R73==bL}+L z*O?5vVVG+yRRgwd|3wDrb|c73bu)w$cCo_%I4^6@7>R=j5WYI@(PC#=OStHex~pS# zK8+AX-`{o@#`I|x*E{6h9NhgB=KkKS-f;yvDRj~Izt$__aJg2bnX5c+c(W!l|iw7Ln~4(;O}pS57s>L!$aQ6pz&g>zAPOs zNNBuT;tf`w+w~Ro4GV z#z$L~5${f6OdXHJFWPjFIaC~lkn!+h!Et3_;`~;(nK&84^d5F>{v|90S+kC=cV7aI z@^oAf|D#>RiSRCcAMhN2Nkf{ns#(I zh`mjJ&H*v&=~gau+;*|m3Yv+LL>N48a?oNlk?!Rh?O0dO-(c=}yenLSKDl6`F(TJ= zoFYvHKG+0;5k}}EAF?X2gCg~wXX@+zT&B$&-amND9QxA4Eiri7f81_Ov+%#H70&S$ zH)BCRlS4n&oH+acEI8>wDHkHcrOC26n(DjpH4I|02^i#zi!$0iF`cW zyITL0Am`Trgx%Q2Q}t{~K*I-b8X0y~IDd?X$m2=U|Ni37P5%oy5}#l4HVM0kmKIR> zhNJApeWJ0NM34YbUnk@Gr}-&@Dv%h!u+RR}?RDvJAcVlqI*~0BC4n}sl`w3Q(t4DG zl+@irf~VV?doxNyfQV(pe#Dv&ANS$mJ}E;eiuPlAdOBj0Y4LUL$j*=&HRNr7R4+zJ zVbTbC9*a`bH^!9VqN2yWW6HNR-4Qr4PvRECiF?ud?`M&a8}^>##?;HWmE@UBJslz4 zFJ#?e2!W25;=M`iyV6tG-tW$FRv2~6`GuN4p2TB)?t2_$^{+)=C9adG_U|i2=BLJ0 z9tIRLUD}^NA(6h6;tH`g%wAnX0LR(B&qMb%WYr>i>}zdh-iy`vj7r!)CjmEhj<%d2&v#n_eNy3Qtl za;Ecf-_n7J^Id}dxv@n}xw@vH$ZG?p-3xq%^8t<*O3LS}l5Z3HxM2_^FzNZIwHfy3 z_2UATjWFz>JL$Vlju&xC|8p8BG}bGu`{j|e>t8H!qb?Vj3P{K7*F+j zZUxp8PnV~4HA7DX+AJfyQ|4?}|9kb3nD<7#)xn5yTm+>*;Oz5+9{^A?PJ7pWM*C^a z3H>GP6o&ynqctQI05Y@OQ&Ot%iu`JJ>2|UMD!F-A4p+Z{4IcjqcD)6mo4O6u{y{9q z2gYT5*6|@1^F_AU*?}Ta`jxNmULWL=;pn2f2Fh;z(ZLtJaEuwsDc>n0GS3#yGIi4v zrf({%tqYA(=rvG7v_WN<6yO6f=IB1B@56|UwHIv@?mts8@*slHq;bfj7LeE3uFFQInTja=h=MfS}06~wBKQz5Ib5ojd z1<>c1$xE5DXP4#tLh2Ba$sbYbaR@oSn z!92|tKx=Li|EHZ?WI)F!@t(in5rHt&C!r8uP`Lo$n6!|OI$>=-^0`a4^U*Xgf_GCH zdAGwgw#W*d&a8R>Rs8&2$JsMgizWSJ6+jysPHGPbe96&`rH{D!@!8ww z&i3~&(~prB@Xw~75>h2)ff5M8dpu_PkvlZY5T^(6|_lR_u}uvUEGpS0`+mMY~u7l_+0W2uxCYa%8ma{PFOp4q=8vp+!9^3SVVsi^<@P7QhfB3MfY1M zYLgtvk9B~9w$M^lr%DwDn||5aGey}x`ni8}1V@O3SpXY-Ndps~nu=5^P*5PlDR^r>AHBS!PgFnX`WSvi=PuL_ybg*_PQEN$UeOc@SBE|P zOZNKR4an8VKVGCh1_FBPo_={gdW4W)JLt0!g+7?BuLd{1#r5nt>AhAkA7{*hR&!+4 zw|SLFl6fw<=JdlOm2n~EQV^d>KK_}dd_{-{pWKRwFJ6;K0B~+k+m^jsY2F*xyi3^V zT9Y(QXzF@)9poEa`{WO*ll?a8>FjLr_TD8GbxstUMl|Xq;>BCP>Zjxj79Hkk4ELk2 z-<#d~Hion0;XnGX+%a|l@BDl$lqeiM36}{taigE5Y_ypRvPqDme_}Zp=pm7Hd0N7oR#0|LElTsm=*w?o1{>c3N{D#{JlIJ7JUbm-s4Do%2 z-4@D}-_N4WFLkBEkn! zx57>y0FBEWTSl7?+QYZ^H#XHCfT!Qly}(FYVd{R2Y3aDKGLVmX^Z0X&&fLj&i#@^L zn0a{APs`I*Ha3X*mb%E`f)ko16h2zoBo+0UOxGj%lBdc*Du^f5QrFZiGP;$A>@S|Q z(T3y53=^uQrH#}-NI8@^A`gD8JJ~SO)W4 zTO1C5{p$sIOT7zJEK(eZ(`o6z0eHTA@1LPkQbFDp6Nzux>7Gv?)P5Y$-UQR!;=V)5 zHe`I>uRCPP61`kieX}WVG9@O+j^Kx;g)1Pl8@E~;mfMJ^e_m&!>~J5S8S+PZmqJw6bep|&=HbZd z+H7`rw(vD&P{4W^PI*N|eSLk~H^BnvV;}b;XlQ5%ak6>2I~3GEWTK3fl^{s^L`YK$ zq5ELNftfaaku^;a8;exC!tHg7%fqKK;t!9_{-FpORs-&p6KNHAXkAeKC22c0g3&L= zjReFC-&xBbkicMS>u>vzX663ClZW*qM3=nOwvf@1jD{_Gj ziWV1rhM&_jJq~-wMeiplKo)o7;^j)Z|K(Bo$#wplxW$N z-24GqJ>0m~nKy8D4KLu`dnIPuqeDi0feTM(#ZCD3TIX*3tH>-t4=Y0h!rGpc);o(n zcI22Wf2&}vt&T9D)Y+)EH6oa6S{82V@tx?T^8~SI;}ogutm+eg5xO9bi8e!RxWNVv zYQ}U^Lr?oeF%REEV1U?rG{8`@ zYx=AD`=b@>!-#3?JzoAaOf&zABPjNKO$>sJi}LYkbnR8t%e)La8346V`-9d36A0x2 zISRHsi3$BYx){9dM& zEV$8IGx-5jJlb(;@!oYL1>JvimFf1Heh^=jD+n?({Z8vKnKjsd9 za1e!fcZV|dj@PNF4BmthlE0}(`83faq92TvBQFX*JL=4*MGDML?krIBj#~9 zcEn@RGd*?4<3os$Wzq9xDI(>j9|r0^>moP67~_-CLsbLLtN`Z^k;(|g#36T-CG0qt zyJ%g%DZL0|QhtQA!&Zl4``GJ*_&X574`m!=(tS@1%KriMjh`+JE6SLj3F)H>w{_uL zMO)f0r|Yt#pCxHMi_<69V+uF_e6NzHa9!xy*VY?SU0mR)b8~WnAi9Z*hI?MtU%p8K zf$mHe5BRxJZs=Hc7yNF+Gb5L|zY)Aj`qvBi#q@I@~=NEHGTV zWXGW*zrzm;#v)8`t~9+5iEP@-ZMdF2Af@k*Hj9Hxzm!=Hz1(}gOcqAM5FFDxW$7m} z3<=3+4Yyuu@E7toa-PE0_64$qYPoI+NgLj6;Y|GyfIwN#! z&^?fxpu5`1uK11sn|f4X;&ehG8iA`eZqEpE3M~+u&BglWD2-I=;*MR;9KL z5}ueik&yb#M%}jGrzpVzddq@P+N5u+U*`SGt zXKmblu&pM}%t}Q0rOZ_?M8P#^0Fh$}EaHI`y=GAeMi<pKfoX%hHT1Zv7it!cm7$*WPl+jU{(5T4d zm`cgY$b>EX#OGU1GRc=BzH``3Yq3sDG@sszPDwIBcObCh}zrIZLv>rMENp+Q9h=^BI+B4gev;7!-%X1HaiB^yx(zhUb&iKNH| zKcJy9jR?`md2K#EF^lk~09FIEGtZ;He>~f6^5>{MMHHtqB4Dp3a>Y6NbR{cx+QBi( z+T8*~0a4Y85CTj0|4Ef>ty*U-lPmiw*#~Nr`TG{9ivqEuqXGb~hxifC-vsCXsu2BR zis8wi9Z}d^t(GHXQ=r|v&JQ}a??holr#fXrs&B*Wye8MS6Os?yIL70OQE>D~oPVyg z0>6159ob=odN$DTEV6*|BnfKQy8ct`DqVMQ;4JYpe{ zL-b()G_iLf;&Z9gc~#>%m`<;(XK8Aog)nBIX>~Jk-dbmnBL~4aXcv)JLnIWwp=4T! z-hrNvreBZ_4=Kc_*8ASO+Qi<2JD-l3PefAHFK$NS6| zsg54My`Da5CYt-EWp^A_P`72!f7_eKB%a?Dj4H?>yWnc@IivVno^4OWwB45jYV(ye zkt-8KZ#%OJzLke@iOF8bryi31!(CVN#K;|cWISB4COFkF5?}g^E2>DCP_I&Yu4G0A zDDJv~z!I#z6}0=Y?~(F^svjI(_BsH|qvy3-P+;Sq(af8Y#us|3`7$V@tTWEKLPwaQ z+I8wqSIkWggEfysAaq~`AlSfscqL{Le8AXwKBj8c<^{aCNc>`8Nz> zgKz%)Hx*EeSvPV&*o5xIFEN!<(0qr3j8%RnTGL-}|5BnZXbgH~AlGAhTIU@+(aD0F ziS&63ESSr}fG#$#MXL&te~J!G5$<&44pYVY;(bn|DECWPkg6nfxR zE@`SXg=t-nOyI@#=x`I6gU0!Va@>TS0E}EzTGf}w&DD~Ibk*ACui(a@VP@EKe#hNC z7+5QfdvuHGl!_oRg#dwyN|eL5lk2xF?mc_L5jPQT+Vd1h01bRAdwX!i!(v2yOfJa^ zfq#vMjVw;Evh=%uo2CVIL=A*on3T9g(K4BvHVhPajU|mJODLZc*w(@nB zKmf{6npmcP-(obG==|*7paR6u1`fdhwb7(>w;`g^^}FkDr$6hSCDqDiYa_InG6utL z*5huvZ>;kZ?k5s?sYArhqR^~*(NStfgbJ291a8^VMge;j1RQnV1Rb95u}YF7Qmm;Z zo<7R8Pt4Ydd!X@3H3~C#HC^COcMfbQX9E98(ay$v@sV`t!hYO{!&mJa-Fs|8f~FTzjdQOnmt9N%?Yc#noS{-I{enw?a`z~upM z83`Zp_EdCRgiDur%xnH(C5XS+o7$W|&=c|9#WXN5&|x8d#r2_~en6A1m{Cd6v?m-7 zvMu&~W@RyPG+vdm>x?voS~6j3s@XtTi*QO?UE)P8>Q2%5M49H2AOA`T?O|5zbVCxz zGz7vp?Y!MeyxkSe%edrudZ!nUOe3$Y z>Uq5MJKymNLH_psE4&0$FB@5Gnmxbvb_U0Q?wfU77gmGp4KWl}e`&xj9ebyzkoEA>Poo+Yvkvl}{E zV{NR#gEnN|p$8gYHJIca9huL~gAlo;C3QVC;HM`iyjcy}GjF>XC?MA0 zbO)`6cg8N3mtibHNs0;g!^CmDo-0clQ9Z03cB0`$I%&`OtQFJ@exvxQ(oRGuZ8 zrQm^yMgD22x9#nsZbA(1xpy6ia5k^UTeOcN;Zc#gl9uat;aHC44B*fAcOP`b zUq9}$+Z)rjPd-5e1qJQbcIN5;{2)bU(Mkr^nCCU>&~s**!Mj|=kD=E=6Vo629GsE8 zb$_D#WI_N4Tv?s3Sxw3zN563)rNDPbq~~GE=_is%=ybT5S7mr0M0_LWWIrr1MJIyu zG|@C8O%?9o{Tp!!U~7UNEd_J-auqi38T1E-Nd5+8Zb1{>viEihZhof*tOZD01nn>s zhMuE+lnx*s)Fo>%LFU`E5nV}FG~|k-@DPdm!>qLtOMxx#wB2ZCaEpMy-fxCRCsfqK zjlX`y&7HHE)K3KUtLb(eK*e8}qH~elB2@q#9ahPOi^AK5K$!envoGp{fZksyGm9&s z=0t59$H$D-PD2~>W=Vzr(w0k&`)&~-38&NHXfbj?M2HljMc`)8#N=d&NsURnKdIvW zUv%#|O@g+=f#bG^e+2u7<14Ngv#cn(W%_1z7<=pkO8?MbvEVA9zfvIGPdDQBYO>_O z8&Y~KM&(bfkG+=#_yrIM2{mH|s#@>?mRx9vtlIHajl9I8)qR*wsNdPf#Mq;(*`OU! z5G)BZ%`7V8M#6g!aW<_Iqx%tWad6hsrlTbc(tYAlsxeVy%9kayN0g`FDUxAgW19$> zSG}rY)tFZQn4c{YAWQoSABoxc931_KGQBR1gm-^|A92+}I*iTQdG!X71Rt62*-a+A z9?CDweR!BtP@q_%BU57`?-{@y{1D75CWKN(>GL`@vhn~)yBqq7g=yrk{s3G(3bRY5 zAnC&qnUYjSoS8{QI;dZubTUK-O8Tywr^+6#4xiarSQJ}V9I+$PsBCJc0Q|Yd2kAF?fq2(v`9f*wYi!uij|M?f*mvH{i_6Wk} zL1>QeNeZx)_j^tKLk-A}k;1t+H_5uRlHA9{)AL2A){DO@LV~eSUdUC7N&gTN_w6li z8T(#T?K?faxZ$3GS^LUro7GBPD(I z=Z5#h9(vMSPMo|#R4q5uV{VIs{dOU_8YnkChvscB<|mEz#wA8F_`@T1jU)boHwG*w1${D6=e>qA}X<$6&lGmScs+zaEbo8y&Zn6f4DC zw!8bk%>^qNp=Xvp1HHyz|^}mFLqJNa2>Lk-3nx~S2yDF#0xuoa*hGiP=$64*m1y#?N5H6rHE2feRrca^nI-^S!2V_PRAa9l!N}L3iO>_4oYx=7B{!ciWSHg)9t7 z*k}`6KK`OTBPH~v$!D*u{Id*)`x^VwxDVdzCGDFy2nbxso7fy`z$gOS(_Q;-&@xX0q42;rv-=+~_2nl;jiH2f&vVV@ie1 zh6*cZBgl2+AU{8i`>wr0NuvWMB|{|cLZc4ukWwXy{+yNo=)p1p7RBPqBLQV#6eT5; zAM3(SCp!IJD;_FnnQE(c++55?Mh+WetHVl6%o6JgbEif!KQT7zSyMmHEVI@(b9wK| zMK#T#d5Ds4?Dm76x;V;?4~{kSZ$ju(B7X|TSBl0|SiY;V6C!9=T8WA%e=U(99gdQtt6nP z=j$n{Wryr^U{2SOy)_jal8jQ730UT;RDZ27nd3#uMqp4Q;B{ zsq|qnC>x5i-CH6CAHsjd0AUXxx0NO&2_Nx>NV6pQ=X`izoD+(>d(u4 z|0wS2?~ns2VQl|J7+&?NmW88MWnz-uEGO#=Gdd6t^gHLiIR0Y(M|BHk6KQpNE3^2R zgZUg2K^y27f5N}xH&%yAvhG+qW__eI-hho?c~S4TC1%Lc&z~)X&g%@CQ&&Fq4UmGF z4v{AbF|ERA75fJTZ$jU*aB#4i<*0fEtI>Vf{Jh}SZ&uzXEobybj*t&`ex031kee3i z;4LJ(phEli9M;n*baT}>yk;jsu7u@B0m+9@8lfndlq+*fw_aU8ko31X+)LWp`?VZC z*zXlXeKWafB@JHMIJ%uUq`)}5j&C#Z{V|}!7sNp5^4ft|P4SBXqYye=N%d2ks%Bx- ztL;1&I#jb?yJ;Vh3d)-3u%6LuFR_nk7(dQ+2Qp8q0PyJ$aYWh{MxLy=B^F>I*Hs>~ zob@e2KK-JFL7RN!umXLgv?m&c)0c>U-|sBGA0)JXaSc$Kv0kKW)vR zBuw`%5=06tPb#RsaZ1LF&?kfKvWWmVE`*n}YEX8gGP`?=-T(j{QjN??vjWR@26WZe zGld2X$7<$!rQ!!)Kev%zgth-3K@=m5^2K8i#XMJK5{oXO5?-CuFq@!gB*(GAJ6r9j zsIBTJRn}a1XMQtYhS6IKvCP6bS=O^a?`tjLB}qoQD++EQg(oRh-Y$Cp@O)EAnTqGFte|jLbwGS~1c9m$<`9pj zx_xndE;Lv0IqLCpS}A%8`&x5CLCi1ic0FUGOWvhLS$9v+v<~cF3AK&!$?6wN$d|F! z^SH~759Ca%#T!w#V&dFu0Tesfqp+gY>q$b+0TMQ?mQG7;On6Ib7FTOKVX3ENro{UC zY_V`_YMGLZ-Sq4w2U`{^Tt8zp@K`Q+D%R zWsxGKY*zx$oF~B^D8$oX!vA6di)d3hJ;9feksZ)KL=h28hnvXScxOqcL?c3k7<4LC z=fA>TUVSpseMi8=g@mLtRK#svr&zq00KB8?zfW8pE@}AIfKJgQl+32o?%&)W{jo^5 zjb}$FCI!=LYr#o7s)x&-;eBog0%}}g#r*V-cX|5TlOh7#YTSDJmRJE`=Dvc ze}>9E7s7HP4LE8`EjT?*7h`i}IS+L-p%!|da!=fSk|iQ04++IyYoU3pjoUj^GN5tm zl=(OO6k`t07HY5DRQf#{R%S2dvJoBH{)vmQr6T35Ac1aAoDdzwPlKOO-D#cLzN`v8 zx>n1>Lt{k2S?@UaW_$wx78p_qx9<`~`ziDpiirc9n_FeknpW4)ipEX2dB=e8EyW~9 zWeBoiB`~7BJo#2I2&tia7kr~+C5pX=MOqjIYUJEqE>V=@@g_wlIb2-&69|omN-m(I zOG;{i^4{wny3!!a7#3FNUiZzGfnnc)z$_$Or|c95P}Jd!UQ78y7;~-5{Nek5E=6tFZNz>EO7?)to^Pe+e&1kg6TpwYKFQ1^Revd!fcGm zTb_$>NC|28!`&Ky5Ir9x|AhXNoTrC_%xvZcJC4Llo;DhxL)78GWq=$i#`K0SSrJ^A zfP8NBoHYM#YAgtvGTOHm+PvJgB2C8O%JJZad*o5{3^JnJwUYl%=G(BJ1QDKYudj0C zp%#eZHn=JL4s9|lww+>kwu6g7UF_C9-vfz(`F)7&mseR!1=IKu;^c@!yn6$lHnT7a0PMPd6@=BPhQJ)!gbfXs*=;XVv>PvQoNHSWwaL zVS2uQo1A_{SRq8S)UR=Ms7tQ%3aLx z(z(%(Z4$u{=#zWfRCj`$GvIyZtecI+wGgqZZ2j`PDH)!rAG;kijQwCik)Dn=vL@AY%1{Dba-{!AcGydoAvyHWX1}H(N zPgY^df(-6BNnKZVHKs|(iYnCNvv*H-M?tf*p)WcC-{nHwsdDlRD)%PMzs2nDw{^t$ zwUpO4eyy)(XeciF^MTLoHr`<$#SDy0J=co2t*6UA>IVPuZz)$Y!lU_w+l${ znoCa$)A_%H<67$IXxK`4Sh&MiN!7)Dp2;fbjwH;bOxH+;FSwB2n2Pt<(R|EVKv4uD zVG{_U)z3rz;y3edCHl1~W@x-(>4BLj5-|Iz;zfWtOOC?kkU+J5-$?*-U3Ejb7rZ0*fD$apVuf2?`-gE`h2WLXGXZa(n9ae|V|UH4H@VK(XO zb4O8qSg1D+FK$Rc%_gqQfK>Qx0NDu_HutE%mmV{tb*T&~xgW~jtmnKu%8yu7!fb;! zH114TgSD@hyw3Y#l`;?epG%%O4&*3l(Z9uYIb<@vuu^6)?a+LsI2q;bOCkoi5fU;f zsW8*azeV3hCM6xhv-XMhD(^$?L8>=)Kp_SD78-XMqvo|x25E575Bo%N-=~$*o|fVv ziX8Uq!2n?)Lc2!fwm+k=J%^y-kEWRj?T)~A?V#9Daw@csFU2dRXsQ4trU_bH;*9`~ zkV1LnMP!Pi-ziCQ-5JZ$tJOeo*h<}83P*j%)N`r>%>h-H7{Uk;-Zx7=?O8To>_7^+Qs8@dPZ)eICTMihn-)YUe!5Id!a zUS)@)Qx#KJkMJ>gY5m(C&NZj3jPDF89RzCt4Wzo39=|fN!VOtSr051ethoC*(m;$Y;=peBEBO7 z<3Ik6^$T%Zg0~7)i-U-?=FK4 z69fGrEh0uvlygmmjxL3#3x8g@cy@l;1`S?A^_np6kC8fJXle89E!_!VHhnLRROnRc z6)e4j90?A2?q-fUjRuZALoNkj?(DCnX1*Gl24s%AqEB~|{&Dw=|8>6czjOjcV{z|AkXM&b6SOn&KX&Z?(=;mMvU$k3 z>1T^ebfxTjx+pBSY=1?X{PG+N1fT;5MWAYd=azrUvf?F5Z6+0h585kqrPuCf_tQtI z8jvMOPBKBRkSX7q9|6fK<`j#+*o`!8shptNG2w%iWPn)NG=Mi9ErFcP9O)cS`I#R- z2b^ac;ZfwWo{5aWuHGME6OZ6K>-?DXtUhhcrMxu%tQYfsK;*jCyNJ{murVaobfLlL zZp)uHiQ5r^;0JML2j_dqe8{t?LmfgU{y@M2(B;?f_WUuJalWQmUfjR;7M_RgDgLml50bsYDfr9{K^S#%Li;|JHDqY={0jg?86U z0NEji75O-BcPT=lk8iaMNrepsB$&bd45FaP{Rjw2KDe$T>r_C^ipi;Ls=7x`mF zNt5Aej(Zf2@oX=P6S@-brkWwr;|dnUiBL@n^2J?PPQ+N^%MY52Fy1iHPJxix`LEa& z!wVP4?Cio;PAntpX+mlgK4|mVzgzvO8mS~Hod+H>Fj)` zbuvW=fw=-3R;|kHhUGnw`Ii_%e5No4tZ0Q9)HC%DS&k8Qlz6~CrD^w<&J=9tH4pf- zzq@N++|Y|9r}>>brFs(Z{%Xj&G9?JFLq)hyigm!+b>zmSU<@s4vAAE5HCc*}8fIq~ zEK64%{mNO#bPT1*r}u&usVs-7TjB>Q4+!Y@#>ZdHsuG;(`sVS+Ph<|~)avBEwKd_V zE>JsmpF<2qTrTnk+|C!zLyC%q)~%W!Ch(ob`&OrTS@&^rY_Ytzfv}M*k|iy4Rx7#z z&&nk`e_S^PqtlF8bSUn_HfbQ>&Bo~a`$o{RMxV4Eo)9`F3t71eyQn1-LfX1I0*3cB z4wTf6S5?n({1t%g!(_BUF3)p5U5F8S=L~%n&ETM25vujjw_N_4_b;6)DV45~(RNpm zzr4-56TBJ^;$RlyhElmIxj`=2_}+K3!6-SsJNHHAgcaox!;fEq9B#+W9r;5xzU(#E zfZ+lm%6;dMn(R0>8K&RO`@U^b9X4L}xA578us^{xcy{>#wyU0zQitE?aeWxlY<$pu zE&FCda!82+-POinA0ivlYaa4KNgn?F{2CgDQN)C*B6BOm-C&h0t-lUTl6F2aJL>+_D?^}QyYT6i z-+mr8mg_udZfvKZir91H2BX!@>688!3|$V1P2gU5SgAW*v@J*stuDMZAIaMXfGx-{ zKmq;nc+{*3CuVI8iFa)dY>jGeYMS-`h}=ppktJ!Bh(ow^!i%=r?NXaNtN1NnxrCF& zVkqn4)s#sAo?#}=UkqyC?}LTxf!_8D{&S(Z zUSyxKe?B2O;{_gVmA5ErvPB=u%%1Vq)@6o!SmtE4@r+wL_CJB---6ygQHFZAm+HP2 z383w5C(BhM7oyKc4t{_jG!Wf|UDCs;w&7SUV$$kWVpfgiVCFvv0}jkIxt4Ns2}?Hr z=|5BFX~Iu-g|>&n5QOkD%zykOXlLgG?l5m(z2wv4+LbR3!#GGlgX);G;vH^e*mKgQ z;Q@*cn~i7&7l-BHzK!V@ zFH*$q+mp7U-%(GfxMCNmtIl1bmBQ!fUJV|k!V7x?uEBc9I9=U`t2l@+qPhM16L|%# z@?m_9#^m?uyDat+c%nwg3JV&mAlSYBZ^8uZnb{pP&e1=g6YH>4pbVYW zOEi3x->t8uZ66UD*dhXy2S@X#%XR%@ptq$578|3NFkkE{MN-U*jGvgJbHyM;f(t@~ zV?^D!iB;&r*Zd#mg@jFp?B^mi>oxbKXs8HtOt*$S-Oa7-RE#V&KKao*TFk=%CHh-I zA5GIl{GdxslFhHM-K2yN(y(@a2ZrD~O2ng9*12;*h6}J~YAGGwBWY)b7GefX&)d(;Y~JhNe1r!0IGHyfO;9p(UG|c zI-lzDY^13`Gouw~uw&G$Losvm9n<{m<*i==_dz~xjqNLQNiC6@R{{q;eHmCDz4t3$ z@kpuO0IV9|jXRuVB-?gyB&#>FHa;3lMVVDw_GmNSNve+?rhJ|)E*zf9!amA)j}x8+1V8bR7bw)Y zxmQrCxBPG^eyzD@48xuJ0 zU86o#CXVln+E^!^HZb@WVolOlPiLNN1(R!pG4o4+t+C_t>T)CPIXBq8&~E;|P{uU7 z4`w4Bghgnsy=(h~Irk8av4nC5^_Ki}EM-`R&N`TOH5p`d}ECa{yZ`lef`**}WrZ>%;e z$V-t%1Mct92ujY*Wb~P$j$UYeQr01_!Lz!Kr}P2HFz7!Pxzv%RGvlW|7$mel?2wM8FpV zwZMOI>+XP;S^AYQ)F_Q_8Qkd8(_?wR*tPMKnyYzU8}+2Xi%1G>^5`68swq;DvVW6e z42G-9jhBMuBSWmdu zEmMYtGKb-#XqBD_JNgy*Oh%mJ^}o0(kw51=UXx>|#qd5K5M7Mi55&ZOPZ80ogc4ba z@z}bMh`!TkBeYBXuOb;%>>SjRL%#l3d(;LtvJ7Is=GnBowIc zXaiBMF2Z@=V$8;B6WC0lsgp{81bI(fh z8g*n!^_dM4aW>(QazGkz`mDUYk*x-E3Dm6{lA`9TQ`(EJn09|U5%^SQ*MrWglx6Mn zm5GNWhm=-h@@%*apNF^c;$c-<*2psMx4IBJ`cs!-xMv|Lo{{k!CY*2lcCuwu0a3}d zypd{fC0jGp$nR9lk}?@CxBqtw&Io?qSEiGj)cAMA6W_BvN_^~5R%HGu_v|WIIE9m; zml}N=`|zENLl=@WR7bU&u(ONJZX)jF|;l;iG)G9sf=zX zB-cqY+$NbBSBO-{y?*}=y;}>9bOInD%UIOMU??wlU@yC1V&TW4K-AgMG1O&B;1*-g zELlVr`MQDb31R#p-_hj3AaGdpn)`MiLb$2jgquz#r5kYrc6GWJ8v#?_wb*J{7y&>&2&$AeXeC zP6nS?aYvWZFLqwT5~RE3=5vO@Eo(O6Z#@o>5IJbYnkVsI_lB-+K%G*W6{X z*FLeQ!T!s{XYPmW{s?eK6KtSLnS*)lSK!WwCY0o?Yc*Opq#lQY)|-ML(7ku?Wbqj-POzr%&W;l)5g&N*Fm+Y$=pL$re!HHP@_B%n=Ij=FYKDU(Lv z+!_o^rkJO}g8XO^ipo6x*D==%P;`DxbPyR_o*n=#cCjcOqq_8{+AqGOeT8nPD*2WI ze|6GVr_Hh19$oisO_U7V8F8fyPQdXdFygNZID)gbX8J-eGrO%1U^@0wo9WJ&w7lZV zm%&ro`PtmrQa|fD*nKB;AGI_vlG8AQww)g0G#e?&L$PMUd)OCL!!})Lb9m=s7H4)L z7O~&_^4W(&6-p%c6Dji_AF8cW8n}09O~E=SOD}3X-+5ZRtSHwt21#UivF=;`%$(-_ zD8acoCZx8Oz0;3Pi}!@j*vco0M{1R=zBFhgnp4WaATpUwr|RoComX@u%6a1vZ^2}v zvYXJKC`CRpm-A%z|6OesNms@VDV?^tPxvewEc{Bcj#RUIA zK8>j|Bt3P7;be7%!Pw59p<&)E`$}991+~hv6VQhXq%vc<4wg7phA__ps#%e`1#(X$ zAfnUCqN*9I!};Auw=u%RAwY+P4HN6=`0 zlf0p2ocUR)!_pfYZAa$-EEIDGX^H5Rd{5M!NV%l^N=Ql=6a8!v*#df*+Ic+)fVx}q zU|)jg#EgSHtUZA;5netHcyD2PXj ziMOCV1zn#bwQggJW&u0btAKLL>pa%dM1Vu+h0H82vY>S7qJ@r6xpPjbGWG_&8>(*@ubw+KTi z3A)fA(T&zrGdFqfr$F*|huU|~lViZ}vELO=ph`~d7W=<}f2^}3MpVN0<4|4hdnL7G z0S`&;nLkY#qiH`;6l=4<)hEkPD(isHPF3n!hA;T+1pkz<@C|!?x&8XSBbN!3=Hy+! zb`f(6h;P<1C=lD{O&TRUoJO@V7g>IdsulnQ<+-xOM~dCtJYv2dSc^~#Irt^mGZ$LM zu+90%5M%23{k@81-^0HH+RJ@#MjJLq4XDahrUWwYda%ezgz8e`k<+7{7ycO+-W?YG z^yhn^H@cCrVNO2k!s2W79=HKL1+Qsc)12**{U{@{<9-5iK0=gYiN%!(FD)f&IVG@@mk)u8&!Y7vW^Wy5xRu9|=Q z%j=UC<+W93<9@uNHY zH6*mjxVC?Sh<QJO6xtrZK+IiTDTkzeAAvG2K(E2r71IdR7 z_iIf+U7>f8r7$ZlGkhsc#xm8kqKpr9EE=e-XqhT?)QE3IkkXqdn$PI^W1}uE`P17` zaq&9qQ%?+BJ7#EFu_WmD{>L=8+S^ECsQ#Gx^;MBSX3pn@5*(v`&cL#~o4omwcUj-q zP?MGpKk34XBieG;Dy(ogSD!pM(98(Y?qsPKc}^FR+yr5;@C}TJ$rv@VBIR{8s1v~X z>1kcHI_wZN5K2;(C}gBC=@sY)j#8P zur@Ax?LSNJi}G3UGi$ITgj=& z!pkqWkvn`Sb!L}U#T$S8-+?jT31PrLeZ~pJwYSUSX z+BnsW72l|$Cj&ztoxL9+&184-jo9DjGfz{y8SwSDrZ`(6&@X9d5guCp)r6#GEHgD` z4(hvGv_Leq9=s%ewz%1d+;zpb8=Bz{q}y?2mhfzamk+e}(DzTdAmP`R6n@1+(zjy$ ze>8n{R2xpPbx3fx;uI+k#ogVVQrt_SxVyVkiWjHFEx1E~;$GanI0Se2@_X-l=j6Yf z6ArtxJ9qBfy_52Zb?%b_lHtX&gR+=%y8s@K4{8!fV%UPQpjCa$6D0#rpS7;kvS4um zMC2Nt%993;63PBV739C83KZxDcfz~4MLFG)aoHcC{HMASrqPUUmJP9m^#93 zK>cz{DR}(HHk1#2kW0=DB-q1nx&d91lv{V3S3^VUg9Uy%Sp?O*ohRpS2pMD>kG@yl zm=UE%+?(E=5l!tAaj7kvh*^cGVktv#yzvz+7Z(D&EbJnawt@8r9AHnMyq&OxiA$_3 zBXxd1c`Ed#*T}0_*t^2IVXLzD%))`31D&2{Cz6wq=-Ky`G++(bNXx&zBiHDp{UE#NzmcIhJwQ}UR6RBUDD*2&3%e4#(IdRNc@!y4=#{OZS0+W$cso6|eJ z`^cM)$2p-R--ZMJV0<8j>ywgvdW~VuiduhvI*ka};NSV^=*`^qw03Up;PG|kT*&{D z_PPCS4-0BR;RQeF&{ZYkygkPz?#T8le_5CBraYXYyi#B|mGmEvEsUzGJWp|tUt$()T&k$JNdzEpomlc2r z0Br%0d%uglC#D%22SxCU!kGV)h$*;=-t-6_keG;fuw9yZ)y0j0F@h}YZf!$C3?hEX z_?fvP0^sMOzc?AKHRglZ4@$-*#u!!g&C%Bopovk8S_KnVgJf zYz&%}k-Nt;+p=Ic_lX2L!(9V=IU8OmjSu78fSK3^WRqUDEhdzt-yBu?Ss-hRptwZ9 z3|E+Li8mW7<4M+{PaW(BwBlWWyyPkp3?E;lA&Xd-d zu8?DwhQlSiE5#|6WycOmOB5Mv*T0TYJL= zgs-F^CMp3hzQvhlxpn?}*4_Jd+x^O>({;Q3jQ+O&cG3L-H#)!B5%BrL_?NIm{yOw% z?^o-%eAZEo(totSrZ#^kb<@rgz8qD{h+Wj%9Us;W?MRVPkU!>0>iB(bc;VPK;_8~2 zM5cB68BkZnioh$PF{LhH!pq4ZkAflO5j0r{-=Yc6!aNh|8M#KNTUxl~-EW!{;!mzU z@`2g6GMrvQx^38b%(V~>GAuBaTwZsA8b$B6AtElcSB~J$E#({XT@g1ywXx6CHl0IA zfd^^5FEk9K1`w8SA9|z|`}Fyne*!w*dJViK#8oTKnubPl z4ksY0!PnYe>D=P*!+^LWh&K8Ka{GBoS}1uh!l$6h5kbV=5HYvA){Ft~#lL*(1)PSx zxKcGmF#R%|p=5@?4j<84NoY76{R^L+duZ|c&)ALqB!YFJsuXLA%8$?;&eiO^m%|75 z5gU40^h*0SO2kWnkBUWtWo?VrytjK#PeJxIVczzm{TcMepMMNJSaGD%nf;C@#d>>}FC)!1&VxO90>W4sxb=#arjWbzw&_x!RIX0QbUq=EyRTvHL#cY0u5VoOc zv?YAz7X*0{8nKdNq6C`ZbtrsKj)*Xz?)$VXbJPa8t&T0@(Dq;|^{}}WtF3bb$Bfo!cp6cw z5*_I*uFp_!{!2SMCh~YsMZ=qN#*j(}{vg%%%g&Fh_4 zRrqB4EIYc$4sJfaF&yJaNHDtgFd?W-OfY;aHW7yVv#dx>`XtsoHlUaYBT>@|p5p3$ zJvrVM_byQ6S7=3U0wC>{q)TM1Yi`^sram!#J)*N~u)IQ{1Q*if5#Bs_6cLK1*76Cq z5COD1DNLuL%tC-!T+oXx1;eNLSaq?3P2J80F-{T^BX#Y@;^&`w+6SO#@_hX$dCUGj zLi$G@O1tp2pteAUCqA;5A16?69zV${egR{q@M0*Y7V8)PTd7BqZBMCVv?>#mYuYo% zDL!T6E=$LgU89vk$WA*!n-*sxUf28IJbQAR&D}4AUYEOkb<|zvJ&d!o1Ko(}hMJb~ z<+~R+?~zB`TV6fNMKWUYt)4e}Vw#>L^A1~|6$|s&fIoxGaFs(FnAKBD){M1ZpN0qH z=X^TCfQX+M{`|t{FZfip+Pdp8i}mZ;7xiVsmWUjaSsde{oa@twZ-9o?C7DY(SsrIy z>wNm`-5pc6cfEb2;$At19m>HmT5gSFyXA3{OU{6Kn{%Lo`q;nF*Ca&_M8uHG^~R4P zSLpM$-bC_yZOZOUFRj1RpH2#E&sSFPgxR7QZWxw()|{#Dhkvtz*fy3i=y$cxVz>Ow zOT`u`IEg8Bkomq^sTpFCJ4%CJnuP}T|J@Lug2tXxM2As&SG z5qD3I9dnD%33POg^vgw8%rJa(I=MCaaPn!(N0 z-QSb$;tHjQbGFo-5CF5J4lBL4Jq_Yh>RVSRH|s|o6G!Nio#;Jjj!{@%fcpKRTzL1R zMnMhCI}O@cY>mW&Qhay=x(NvU?okUBb%Ner;}%ZWIC*`p+Cv;svh^p_8g5kmL~ySi zkX^Vftl>P4mM3H*Tsq=CD8`psow?Q3Yq>8B??3;%_wnt0dY8o>)&bf|z#Okt=?g;X zD!GZfZ#aeQ!-I(Y!%Y}VVfk_0{434z@#W(qZoe2{Q7t_-@PcToSxx2{Pa1&lQ1=5P zJn+TwRcW>REvGWhQ5>BGMJ0F<#``+Bt}U!1#$)EQT&q0u$v0pb;lgG=2nj2Lz~~4w zH0L}g(ZTqr2#gr>O6Jnul=3`qXIe2qjqqV34bx757&i3JF?8k6?l;oO(C%dN9=5v7 zB{=(S&l{zaqg-m1yH9pQH+}7Nd)RMm zV`T<<3S1d48s|OgS@QX~bw%X)n$EGV5hiA@(4U6$c@lY>{rmz0jUOgTuFx&)XTJFa zDtllH3JujHtgKzFqA_KZrYnwwDxg@{@jIEfVuD+D=5xPmVaKU6ep6yMkOh9U2*!29#@}V!W`u7=!-cQrcr_ElEYSA=(3EvPm!Di3wQ*vnPlX@99j}GAP zpbkZPIQ7mFni@OZ$4_hB73_kNmaeC=(mXR$n2Ud(FeO9Qv=d=w?Cbl~$y;@k9%STR zT0SZ!iLWQ-8s`>8d4q-VC_&Q8wYokV!zfRxTYrDGS3GWGVgNq>!CNc4U0@;z4Lsll z{*1Rr66*$U`DAh7_U{oOnN(owQf+>U2`+8XBP3WVC$A_k57K-yGZcI?6g|`KznsT^ zvax$RV%l7w-%dkm(XK{IA7CzU4XCm=Y*p>%r#g1kH!)f4N{>nxYN^*-^O3;*FA}&j zqjl+CW4oW4?=ScQKQK#&F?p|!{6e6Yt_MlgzljL84Twyup`oNHfLS1y(vT<_u=2cl zK8o}hgk1ONUFmtYja)iK%tdC(o3RdZC2hzoo=UZgqV|)X9CZuLyV%lWei9<&^^T@J zNNYI9@}kpb(1_td*H<0{so1F{VwRbI)drqx?ld79uDo)Vp^l@otb>0yeJp3}b)^v+ zkTtjOTWZfqq5;wBUOl%7u6td$qQ4rOK`#aNmjUC!_I!bc378RvnvsV6)7U@9yzoe7 zXwW0p@62}UtmlVbedfAW4mgBG9N-f5N*Tj> zGLWI|T0kepACi82X&VgIK5kP#*Kk}jzVWp5_YXftYqK9*Yi}D@`(}4_))`9ZXm@%| z0FMI*KUOY{MozQbHhDP>OnAHAcs9t;u}nk@foep%3quZa-r%A!PhsvWzBtLI-jg3= z8}F^)(qy{$t%(Y{f?`aGsO~6Ik%Im7_N$J>+9!4dd!sGkqSZt9l4q8If7SB{4B_(C zXFD(TReVFHX5R7V^EMrK2e8wm*`2p82Wv^?e^Z0UcyetWRV}LB5@!(=vdGSE!-y^o zA|O!w!gX?o*AWxkwfQiRV9*@5z&;B45hF9OtIO`hiobP7Z5I*zO8Kou9iTeV^6!g? zuo(r#{2*90b>4rsy1jdT`MgHSvH9}O_N%FXY>nY7^aBZ;Y(%KQ+);7p3|E)-R*iHE zI{%C~F;rX(wxvGQPLGTI9tSNs*)(oGogXGALl=xv%MF^&J&^{rMX|oPST7>*3*#@p zHIw6?Zf?j?@ma{pu|JJ}=^gd%bhjm1M$k2XgI;pF(=ktS==ddKpCBH;UWZ&vPTG;Z zM-r>2hJ?1GM*rb6UjJ+*q6yk3nHsN2)JEu$B0QU_A6GRruX>d^!MSMQPpo!ChG(x=N)e?F`upjW zh{keGEr(B5&SzQmY!&ipbNiE$&0Ti?|f0i?h-eKf2BHc)(CT>M&>9BGPKO+4hta?h| z_t*0Yo2NjmhfWr9!bQ|p)4sf!IpPlbEVQbM`y0=U;O_u0pAe<5w`IzdBQBF(UpMEvCyDsCT2V=1zZcV>GA_)q%aoaz^2J(G>+M;qG@!rs#IbbT+y zM$bDYG5jKUIO_M89Ir3kZ+Wj)dKk@0?DBVY-5J>SwtZvQBCD-W_!nNNCG_+|`)pq< zQF;f7Krri*iF0=T+h(HNM*|u`L^G1#N`CR;v-QGTlXY&ccTp(PA0_|by;0+!1~~eh z-#r1-NW7Cbm}~S~w+LHb9W?ld3HdYZ@XWy7w~_rT$U?r4jjbW9{`Rp=9z_G@VdLaT zO*`RYO!ursHlW=?jBIa|{!DasQS({1v?}|ywoj7?1G22$L)^pX79P1~aTv@QvKAX` zc~)fJn2L0gfowbtMr?J#6~petQlLg#kms%8E?O`HZX(_fl-}FwGpm0s`uMF0p%q8s z;hRGJm)@pdqF8HYnDCOnw6BX9>eTE+A^dKer58BEbqA(Jll z%f<9$xmM$BkGHrAcZ(HN@9K|{AS<@sbHoq1Wwr2Ey7LoJKK2(Nz>tQ`GkulbeeyC- zuQbs!(aFb$jSXTDgoJx?E#LZ}%2DqXxQ9TC%tn~*<&!Pxx@*~(A*Mi5ahR8Ez+**V z^m*XDnv;)Dg4-i@rZQ%xGC@Kgm>lAK4L{&<0|?LTsZJ1ZdcnoY@tq7H{N`xb?~;lK z@6W+!rfUzb#B88#E9h9ll8AMMYL54+e0LXcEF+}sxqf`rD-QV<{s{W%6JnZC87?MM z;1ryHw~_wu^$DM5Qxe$&9GWoP>4vbWd$Gxf@E z4R%pW46(Fvo^!r-xw$j)2QW&t7xVI6*L9e!KFIc!m?SS{^iXJ z7_@HuH$gXXEp)RUhQ!Ym?Ninr5LkRiv&MLQdh3yGL466n>_ z(hP9l0Bay9-4m=o)SE!>MDZSOIAPwty(AIk5D(ZMcUC=FvtUAp)?wt7G@kbMe2u@j zf}ptuc^*4uyL*M(c^R>cyu084H}(^e)5c+p${1jGRiOy8b1BIG3C3bxAD2cn{>aZS zY%bhl@mTFFasLAw4r-AjC3%<^j64*?S89g+W7y-*&MEAb6I6%gs2#(jmIfXuBiGKU zm@K5Ew5?7M);4HyPl0+;l#e4{tJ=iVa5aQ}bH{~Y6r-&On%|<7zy%Y$ zg>Y`_cV34rH_%`ESj_Kt*zw9gR}BndZ&lF)&Q3VK(zoo1RLMr5vs78%eXa$ZoVlv# zB)x-cYeW9V=I?3QSH=`O@I3f`S^xkpT+Zok`}M>`u=MujrfYs8_zXqYHj9;RFfQV@ zpjs6{>KkG14q&h(?$g4YBMfyfFT0sYMx5>N@frEwt`Xo$_7;7&=vyuusPs)NN;GsU zae#SWq7uDV*Ik>X9zGL=jb2;y9gIY77xFPTX}G!j_DR~F=a&?!60=}Xfx77lc|H{t z*Vq`%)_umyMb8Q?lG^)><^biUL6m*s+tHxoXsT#VrJK=aKPf3f zjaac6U}mSs*NBiG1z`dGrh@dNV@Le=;cxUu0Y6_Zx0#Xp|MQAjT$>NrX%l8jiv zgdF?pZPNiM^AYBM0K8l@---ttYupt#ibsonL@?`$7a%rs@nrH6fq| z1i%;cu-$97v<{tq}Aq8%m!Dj3%Qt6gIi(k9y>m>ORl_z6SL$Aw9DP-(|a4*)`@ zg0|3ttgPb9gP#Lp-4{X&@P6^}iFKl}<5I<8GFEzTF=PqFqh)UGSh!?^Tga3pZ?Q;M z=zp4dQ98lBe{Yl2{Qg5IM5rdk!*!wm4?`b&gK29XCL%4~4*U$$`I1h#9YdyC%f6G(}X$RE#0AqhUL1Dw#U)I(_)yhtU-&QBJoJ zDw!udpfdp$|Ex zhmr`nge0v!0^Q&a*A*S&K~${dL>_UBYdB9$ScpP9+qnu!Xmj@>L?Ly$o zA~Mv01Dmv%ei5sOp|Z`LGY7GFQ4dvmmv2>r3hHWULvLx$0uwA) zK951fo?E>Rc|=6qhBKQfnBK_Wt6QG6AH#OdtGjsN>fzzW(7jmZ;27lL`SABLLT2BP zwPlIK_LuDqBYFbqz(B(B#+&7QCz6&)>rjg5*DtIgwdc>-(Zflm2ooxRzyPxy_NwNs zb=D7aMg4z2*EJDGwG=DdANt}Ae-HKhs=S3Ic6_ad2yTHF_K%Bj5Je7wrbg4zK{r{= zEJ$@t7WOd_p#kIluVy%j=b0*Z!USQ7b!?+d_e6zKo4w4bK;~`A(9AM?EFh&5IwJyq zOg>qJ1)%ts@2fyH>#=z{1f3mUcLlKJQmWv_;3th829-E`iF8*GMW)p3;#WgeSL{)5 zOIc7a3NyKv%=-ra0@t^l7XYSs#1X{`dt;lG<vf%)povQ|tsQp}SH zXJD~9HjV3go!^)I@q_bfHQf>Z#V%&S+n}<|K^_1;y=hum1hyUX9}UQ%)T|#YoRPa| zr+@aPKJd&Koqw%NlA!cIK%x2OpsPGnE%fs6K=vWsajZxh_23+-sp+~q{WBT*b(s=v zLUap(wc&iH4O<=5x7D2v<)Y=R2l3!Fyk2XZ@zXD?Qop}kls3+hren97$>HeUTBC)C4m=yj3Ggqwi&ymVLH4v7-8dHv zw#H1M-!*dT{Jc zjP$VlwNKfg2~%Xjm&-3DOn7gK3&SN?D$j#r1TP-&N~3WJa$)if?xO`t)t&aDUsIw3 zgD|PQT{iyY1=MbF_B9bZ5)dbzGZX8h_417zU{j^SuYauF=)OJ)xkwCTGO#le`bQ`D6Cq2e84 zGy`H1rGgw72?`%sllI4GFIRmT1OV>&ky|$)ZuEmMCLnh0Ljfd(Zq%-w8tt-{4eBkS z($tAM{WuIH%Op}ESbd6H8Ph}nWYSx5GRx%sN=Mp`ubS`^M#QTYUvbIuD)BtwdAJ|_ zNYa`tx;e^;-+24dgBq=Rdf{T0pH{)Nq`_Kj?;w3LxMXoX>6`RaW+{&|!Y1i!V-qIpT=}#=Zne z!nqq+TW;)gxxlF=kSq!{_`?-`@9rv{o|h#e31PDd(Dj_&I4(RU@Wlxq4N6R`VFe}h z2R#Uwx{Elqz{;GYf}>6>_lFw#4(Xt3I@|;dki7ekJmYLpxQLZ%4*sSfxjPh!`9^jD z4j*q5EhZ-bL5xp#o$^|BzX#Dn2Z5DR;tt+zV!w?vb(j!W^TP3&D>Yf}U!z}RE9#It zEam5``a;a!`e44;xbyewqko#shccEIj9#R)a>5Q3KuQ$X9KIfim3EwTa#a$%(`Q%W09>cC=LL+^*GG^t4jclN8|7!wIXslTmu{M_WI|+I{>P5o0Mss0@Uz_ijB~@5V4&{<{tVGD~&K zfi-L~eQzq;xfBkLD9Q2;yK8I5GqS2XHTJ&-S#{g&dsG8hSki^?RFbh1aX9sARv&-| zWmMJ}*C2||*H<_8gfq$3r5nmHFnribznsm@3Lrsb=TXqrogMY?8q+m)W^KK16O;mO z60?)peBobI)4dw`;^Ix|e^OWyZ5$NsH55LutS2Do#znXpd84)uJW(yHJFjgW%^>N1 zby1Ex0%zKNHaW`cc89i8GzvZN9-Pv#_)SetPLe96sk$ezTHTBo9CyA_?xK>O>8Rwf zt>D43m{0jkbd8j-su#P-)7>!U{eGEY?#0`y|CVg}?*`Db>F8GaFo#i5f zE!FaMH(WRb%0beFN%_N~TuxRI(63YsYhD-g0~^m@s7P9UeksS1@CW>&{}mY-mpQzg zeA~oe<`?Hrxcb->+m-85%aMr;4^fV=y=@^mnKA#lW8FOc8XVh$h^y(V8D@EYo|ogz z7frHy_vnLs_+fKXoNeQ8d8l+YJ2&>TQBHtP=fY1jKu%8BuMd;0Ei>5wWB|;qxBs15 ziZbYzRD8E5%Px=w-}a98nJ6xip~HB#_oN4oohQP!{by9rgI@1dI(mAra$4wDXzYUwwO(ZE<4({o7AK+`eO37{D-q8Oi@Uw(19 zYdz8+tqUdT1n}tNRP}eaCS02O;I1Vw-#31q=~wQ1Eq-Cm05QnvM_C=*kB7;N1T(7U z0NphY4qdD6r`N9F?l-(&>QlWh?X-ky6pR^ZhV=+r2E|+oUXK~zj*-O;i@?g(h9gs} zjs9Ql{~CQ?Pw4J*&?Y-BQ}2EF$sj zGEOgZ_7AlVr07bnY^YY&qCiVRrXoSW<;br`i;}UV=AV+&-I(Izw#&L0B_$P`7kCqG zb=*FG`-I-hpGLePR#@D}AAuC4#YTC^aB6P9(todhG9${FCL z)>K02cgz6F$fCQxgNc~hNQ&I-pGxv#i6}HOayUnpA;`TYlJJnkGND;)I5;(A_|O#0 zO9mA5YBYvyqAQO{= z_n(_U&(FOBj)C9?JceDnvAv_f&LpZ$QXQ1k7;sIDNBy&;vZ$J8jD#(1~ zJ#dN#Mic7^Omx`=WHZP>hLM{sK7TCrT~up?9@raw>u3fj$Xf2fTjn+mkF7nN!RH<9 zm|xejuE%kAE;|1`!ri*z;YM#Fj_h+hma>9SBec6ExeToXKpmnchU-g zV`w(Kw@`bSX{E@$s!4h231iZLz^Z%-cgtjLasaT~@$2xzer(Xx1m`X2UxIda@~2;VlFslhce@U0n^0*5aeJ=pnw$#?y3@g} zMKVA{Fm$~KEAd_7w7BVzZ~O)l%>6%70(Z9pfwZi;LMiyk7X%00em=6ajm7=9k6g2H z^aHA#aB+N0ohw?0jTIhsAT-bjbCIV1Bb7V{Ya4o6)pW(dh`W=Ln=Y?_08lLxs&I#r z*XxMu2|pw+kMN@J16q!Pq*^)w0B%#*^#OdWisRwgDZLx|4<7ROZfSA)`0ZXgU4u8q z3;+U!RaJdQbJAVY-{|l`$3g^dE`7r@CxN@FhsBjsXFzNm9~$rb4aXPknhLIiNxh+C z_DE|qSU$9ej$XrP>z@&ms|&=#FerBBU|LF{(~N0NHG&q6OY$FN_an=mB-mIvIBT%E z-8w#_QC4GMso{U+sBbItHRJ7jCf{7xU#2?ce?%PIc((STVoPu3D*G<_nO|Uf@N59_ z7gw~cKm~%teT)?;YDOl_^&Kw323K8X{^M@?0_LNK;c6BaPU5hD)IIlqC`}FZ(~AIr z$g*$EW^x)b>G&upasMx2z`+0fzO;8BA-8ls!~hJ0;SqW)<%Y=BpG!=68w;S5v!i|AZ+9c-UhhQ8!~w!W z?Ojg1qJ;aH z57^%S%=dO=p!1q%(H`|jtBEUg<+X6D5YS+1v~6l2uNyY zKY0c()F_DVpTxLg5d8aI*QlW{7N>Uj@DfuNGMk4VdLIeEtqA-HT|ZAth$918%su|X z>Zob;{4B}_+}2MhA(X4YVGqgjWGA;m`gaCGkX3F|nd{$HZ{kRw`4e7WRxFVSi3d6b zv~c_KmAVRX{0H#?6I}6Xmu-T<2{c=?XmGl^9yVz@veb}W_|#OO<7pdF^-SKhdT=Z$ zz|cV%o|u?A+XTLVMChsdT;ZwyqRo@~Q9FoBu#^_;)x(|(0gdW}Bj+xcDxn@4=2Z6n%u zJ&M7meM%QYNG)-AApy~qw`@VFuhu`*IK$kRmo`mZ>xgNpUf96rm)D!ZP~8+$efX8z zMUrXzrtXrUdDLnq5Q&}?%18C;fcqG7^Dg@a_wb`Z^)uVv1) zM4c-Pu0~g!k_0_jDm9VgQVMhQHo*mHT$djzN?->OBr5t#$MQaPH+OCbIXE?6GTD(@ zR#S@83#NrBkJ6Z|f-CbY+wi;8eX70zBd8f*a+H^j-M7}EgD(GgPLZSQzm z@TG&TB_njSnHQI%;;YTdlJ{l^HIRD2`bbzz%E@qZ=yWHmv`t%$E$e>~O$+tN@2~hO^!=^F$^UTWrask_zX2b z@{*&qx8Fqrv)U$o#BDvR)jI<|W4-CZYk+Hx_Sc>J^u;TF)8z9oWz2oZ{B0W;X|tLI z3J53wp&An2&$zbl?ei4D+84cJ(#QP?y2|OQaDw+^9z;!5p~m{P0b!Ggx%g8HYKzQ` zD2tx8b%*9IyXEYdH58_BUhRv1M1!l`Tf(3(owqnJt%4hU+1IzBR|nWg<=`6(|7l@C zbGuVOUnn&YHALNcJqCz%hKrdPbVm^~RjQnJvA@q7@reJ=3jGj;)erxFHm_7-npwm$ zC7tCbB8ejA>A40w#=W_rCD2wF6Xv@MJu)goB69Mo#OwP?kAW{@rP>8qmuio837-sH zTfzjWDZ|PDl<0WR+w%192JzC_Q)_5sJ_!lnWCl$c!%nVWTEVe0ADLdB3!}PyY>bYk zd;e?jhIG$VBaB8+ZN8Fi-Gt<_f8OTT3H&oeY38WbZlXHjCSX`z@w&ESO>;0gsL~Xn z;(`5M3}Dmh=TCxYF1ObQl8L&8S1e~V9mOd)=Fl_tZN^9p@yWv zr@O=0L6kC@>gLG}H)4EKMjIv`{d>-g97@A%Bne)$(KZUxx=s(G!TXHfqo1N?x!LTz zO+nLUHa3Cnd~)|Uv`_ol-GykAt1pj@t-_64|}R^9gD22QC$IFJJhmzWnIEyTBLT!J)kdC6@El zo_DA>B`*;`b9*0ivUuEO>g681cmR%4PhA6Oe@=+B#5nnC>07V3nD!hY!8+IN-JY9a z>}x>p>h+B*EO9;W5wf~E;=pZ)eU9p9?S4HW^Lh}Je;2O{S<}M<`J+bs?OlRl4$_rJ z1o+K$BgyjP#}7OnFq*`W4u~6+7hqSJa@ucut0dy96-LorQT5}5q77D!-uhCk=ja?L z@N}!#k?QK3{l;pLSA`#&I2c%%>pH($IB5qMglj_7#7aq9QOJ?JZnHb<_6X2Rk=0}J z(Icoon(7nuG+cLm@{#@^F6_~+P-`F**NBmWUo6a5WoA7+&EAi&Vy=qZ$R)tTU4OL zecL=!7w>_Mx8d6wu4xA7b?qYqbt`N?paN`YECHq)0Cnm)1uuTbbz`4S==cXkjAF733q1p+fY2jv<6)-wt&`b97W8tfzozGpT?zwb5Ao-U}4&_uU?CfIZ0TV zi-2H>ZRzxob~UG}^BE~JF1+Z{-ZWF(q`B8S!kGjY?Bk1aRX>g~#oI)*(k|#^W*x;Y zFu%B;lgnY;g-TZz_%bW4QwLKc`Am4VfB8V(Hb#mFotc?eRYgPCJjj?{((7)fY=<1t zS$Og-vi+1`H1&&P{~PC<5NxL!i&CWN^|h_;*@&@|RVCCkQ(r!LJtt&}>;w&rlvj&i3=+YQsSsxn@qDqPY9PY_z`o-lLo!uUa9&lnmXrqo)&ET~-4xf` zvsuo~Z>vzErUJ2h$4_o{J3nWJ#gMn%%qMV!Fom&NK8NX1?4U;+ zrxdTB2rZ`kb!f8wgd~oB8?B{+-Nj3gHo6AIf`Obqet_xS_lwcd!ayTccf7NWZ)Y8w zZOi1@R}KUuh+EBK8P+vBL*B0wJ@Xz;(;2zc=omu}3fN%-|CC}WLSj$@E0?N4k%G&6 zhSUw1ur=DUQ1N+iDGk|4NzeR@Y5`#7$@4T63BDC0Y}qZYB~RgbWJ0kvi@DviM0vCS zM~U4VD1ww{;!}m0fc#kb?v%~Km*Fq1S5g$gT%pGOUPl{z0#0K&ns5S0Y?v!AGB00` zCG8Q>rr<~Zla9Ol;S^kJ?A@L^1E7L5&aG{=O7=JD{G@7w>T^4z)jlLvr#i3{>zd(@ z1&m!VAW)W=0$z{Jj{glrkiZuGr+c{MD$Bdla)0YG-81l&-8A#(Z&-!SNxZp`E};~4 z3%}(lreCU&1ml7N@9X1Z(Q0V)aJqb@qXxfZp@vKm$qmL8VTn`C{*=aXveIvdE8@$a zLWLzIQ6@9Fj8S;LFALjD)Y?VgwHX7n@tT+rxWrByuHR3}5Ik><7HaSLl0}aGsnr}d z&oHlju8vpzmTLdX$iP#>hjIENHUhq@iGgaq`0XRIj;gE?rGH^4JvyGeJ6!FgytKiZ zsh!LfKe-2~E6!8^We;Vn`fFK+oF3(LoP+LE$ z`-+`yA{T)n+@{subx%Ed-a#1IzTdL z5YSX$#1fx0zrwV0qk6Ft3y4s!Z1?XQpR1k%ojPk;xRIHR5cYTsZ)7fCo*<(iEj<}v z1ew)PvDPG^Eb2PvwSYe>)FGNR~*0EO85QNYuKiYIHtE6+4E~uZsa#dNRRlLejv*bS@+JC;cpf z6mf*^NwJ{AF#Njz*QJP=l0bL}m13S5!`rELAC2Oq(iV2aR_*XOqN?3|7$?hxPL7AtG3|AWl}fbMoh z>ncw$_ujy|N_d-X!7b_Iz|6|nSQe+;Y2b!^`Y4l(dQ9gVlDU4_?hovi-trd;2Eu_9 zYNFf~W|q3cy!71qH)HBHnxC**3K{m1%ot(ET*I0wCob3i7`HS0L9%j~J>k@7;7MH! zHjM&=_0J}qFWZRy^^i^Gt=J#Nz+b9oFTv`tICD6!&LMs=vMiyJd;wA}%7k;mycuiJ<;yz5K@A7G&fIw8I-B>>Ro!6r0Owu?uJtJ10F7 zy<@*y++n2#6?%t>B@94CPyu0WOj8%-$B!uSRKU%TTl|o}NTd~6tgE)wX4H`DKOOR6 zA=iI-B@I%h2~u-y{&xj>n|oGd2DZ$0UH}WtMjbwcQI1u}J5FSq`}@@!DI44<-EZ-F ze8jJlZ1!YiEj`jNm<1&U(&7@>4ii087Ki@dQ!oJ^LQ(Jbm8X%zm~r5s1hBede_w`d zUawIRE^RN`*ZvVF5eJv!BUB-f|9?UQR_>m<=89m2I}?R%y!?w{PgvmfxC36;dweeF zZf@PW+o7N8?-G6}v`z%nsr&m^iw>Y>$ z8>pZyxuucA$ra^(5f>bUTW2|N+xkjGPVH6{vZuS^1WvC$ErB(x#*`6MS|%rnDdzhF zsgNaIi4dU&@6DXPKR=;70HKqUF^fV@mIx?wHSu+*`bxE>Gk$RX7LG2T&Y=Gn&-Lh- z*qR0JeX_DJo9=AY+=Ot$gzAIu(^^gabZw3O+J%&&yi_H>{-+Uo@H?H%A=a`~$XPLn z`-KN<$4OY@0>9FsaLw$N{A!0ur1ssH~!SG9SDPIaU` z!ycq_PWHvMvA-eOEPOrJbfmt%k6+lvffyasA|$7tOQ6TX`Fc5Wkt|Sg@#2p+Z4F*U zi;XjvfDzKj<1?8oZ=Q~dWb%^k(f~US4|zMC2r{q#UA>U0y5ZOYaxdEESbMI3E=fOM z7cuL&NkCc}u}5v|-hnletXydA>tR`}Cv)RkR56Nhmt#mrad;C(hXDa046&;8LRM(+ z{bemQdauL&z@hO}7r+)R_B4zvNRjpE|Ne;L@=EYUt+=0%kn6?QR*&JVZvdFWs>@=s ziMS$bJaJ}F7C9%U$EC7*X;G~FrBx&+tSs8}(cPt&Uo`2I5xI9yl?tf9fUK*l~ zmK0^sDJgYxn=lUeFZcY@IF&LE=H_ULv(=ukEpNki{g*E zUSNr(VQHni8|g;6yIZ=Ej-@1}yF)-4M7m2#Kt-e*q`Uhaf6w!L-uVY+XZFs$=bU@) z{p$KJb+wLJ*SRFT>3I!U;>>wDDCuy+BR!hR^}hE$G!_1RLy+PNMAyuy73{_#ZrYMf zkua(ShisWUaX&TNblndq5on&}cq;6d5l^Q?z@7g8H?{FZLhXU06n*kNb64)S+j1V4 zj#R&4u$XrEjWIc^B-d+M_DFN=e9_OVkq&M%Lwk1EV#0h>|LEEF)kvul z-mT9-ae$jn^oVo~lm>Mo0xeDESNC_LI3;Qnj0ga>`}b(!1g<{d!(*hzjc${O(WHgS zoFhXh6d(VQjFc+HW)M;O=35v;b-Q&*pxy-5aYZrB8U<{w%p@p zlqmv7T$j&RugXwv-YL`IQawW6$bx$f3p*5xL{#{vc9HS`7~N(kp!UC!RYZ&m90e)h zIt2LPx;u1(6)wgdUfp#DA;4wkQD*9RjJp9p>I89PRlKKvPK^}j7ceT^+}Di)`93xB zD2@%LNHMQ=2Fc29$BTjFnxV%^uXc~p-A#*p|2=0Etb#Lw@Z^%T`$^=jX~NPv^nV}q z)j;o}%m=3f;xAOJ&spy!d30KgUcW}t$?lVoRIO|qV%Q2PwVpj0o%!?DC!po|>%M*j zimy$)nS4YdMZk1!J}0oydwP1j-?Z~1#~UZJdR6(6$RAw5Eona>0Yk`b`~uS$LWCK_ zz>unj+5df-jTILv=@ z?f{#__?3{UwtjHT7&}W~cRR<&6CdRC-s$_cA{Qdal+&Z5UotWXD5J2x1>UbD}|;7eH)o39E2tD&^odF?{b~{H-ygc~y3t1Lp7j z!}E0bLHnBwLx7d@g0zk7k^cP|v8699Hs#_XMAMS1iZI+I=}GF_UxLkzjq{WCWK?b_ zYS;3{Ez}tc2jr3@oqK9Fd8!x!I00vMk+<|$=?M(}^PHi|H|>NG@G*rLMepMKE2 zeDXh_$icXJ%Axxzlk+OLJb_q9DCBl_v4n%yz);=O=o@>T6xAolQXX}eIKUR5^=OBO z+|AAJM`UTc7$f%FB92opf%}pJ_svS8L|}uOu8b@O$qp9TuCGIr7rTQbT~s~7jxCbj-$vb>*k10RCfU@HZb?#YEumAA zqybrc75)(3&_8a1wNS5>f&>45F`e9`{B6{Y!#6*h<7Y;th->!<#|oRkbB`sbnb()Q?qC-J1RM>V^$uj< zhjCXlu@WL9hoA^>$nDCH!c4Kd{fOpPEFB%~E>wxA%&f%C-M@?bOHLy94+CFP!r(|^ zNW547#T(2??tAIPDQ<#{kSo@2YasLb1T&&9wf__0;PpeJRUY=ASz4JnpJ#8dZtv0% zhR-xY@z+;K?b}aQ$B;G;dGzA<7!j7=8wuH@ty8=8U$!b;Bd$B_a7^6RBW*D&1g61% zi^QjUi!r#cWkeAm2t0ZejSybYLs&n6Bbjq*SBGgb5Os8j930{%+4{xFi#i(b=!Sq9 zDl>|d8Sf=DnIl&WDX_FsZwv?rEy@5qojmg&7Ls&&jqKAg^4!}01qEn-ywBO}(W`fJ zD>C*5oB3%7fpXTjQX87I$wayQWo}0RpvljQNe(cai*2d_JrjxfkMJNhuu`1;uqh8! zf5GV<05Yj9iFzNaqt9@@J@6vG5(>fIZSPgjc1wN7fH(*ZzXoGFAS^7vY{B(Pp>`mJ z+|YjdGBuFS8{$2w4^E~#dFWKVF}tGtrB6aQ2n$deMgY+R@w>K+`>^d%+8z882p@n| zd3gchlW)>59_#^i9)=@GUrU&&L0KQ|x(_=wU2U^or=Hdf=W}~R>DP@ufFG}ld+MV2 z^x1Qggj^?+fr;DbdFFw4ab%D^_5*sH;iA_nq zT63~7zx2ML<<%wm;Q{^ffgyHyU3`kBncKXKsOj@Xh)Kj9F~V8q>xcdwhK@sGi&+o0JfsE%>hqM+gC9+jGy6(FKi6 z?|^^!7AuX__C@ao^0&QcFWT#CppniNjQn337R3Y_Vu1H%miwZq1se1crrmg%L3}$f zC6k-iAg1I02urm6()WB%XX(@>9AFhxd7alE%d&|T-2C($=EMo~j{<*4FGm!Y#kEgfKSBho{s<3UWIHPz6_Qj_^Q8wi^ak?&{5^Z)MfJC8RSAAIa zh)2Ui_4DP{|0a{}mIOD+etBW9q=NnSg8?(>9amh2%be=vg=&nsEQ6g}N|gAZngV;+ zCTZlS%M%Q#*xpgEqxQI=t;|+7{kjAzwz|N{4?BY&rD4q|lz-@+QhK+j2qvDr`lJ?&4@E5CxH-DiwiG`tvt&rEntw+2&b zzJ6mPR!y6=WI00j&g#790^f2F*E%9UVi~+?CU&UWwkR%w0T33LWw2gcf_t0&8oeX_ zcv#aQ7zgckFZ%rvioXE!M)2ltm1 z!J>vZY7z`kFE?L<@gxI))Z-}8(&49+7&?OiaSaKH52 z6HNqmuZ$zsY~>bkV`7G^)|!{^wH_`LK+SEXBPU{pqNZ=Ne7*H?|Dqvg_1{^Et0Ei zp}+g2a*Oj5e>}lhd_2(-*Xp&kc}k~f+y}U?L;rk)p9`F~Q{COie4f&o2mdT68ZdC6 zBCY{5L}x)HAMG<7R9n1EP2TS`=~*3;0iX`h&ggAZEOldVY6joK!oI3Be^olkb>>n6 zlz7~88kGK)(Mht+Q;t?L46IjxS{JA>g-^u3I`_=WiHrExCR;4y;55mM=jqh>iSBvP zpRKtC0q0A3BnJ=0rmMtl_GcXd9?@zJF^3?|r)xwwY&bP+k`E|ygOF(cqSc4_mzxB{ ztxkzzOpXeXHN$0;@OZsf>!S#0>4<}t;U&5Wrx^SW!DoS;r_vlp(bM)=yjy$_NAlL({&%PI%_3K3`5Udg08Pz@O$w z`Caa6mz4r|fD>lIwA{;Ud_eZCEIRsiW&38@`6&+2BmNiMyh&3C>?X)*p3=PoLP&2v zY{l1{Zc|RfOW49wozov(8R;L|>*__fF(RbnKL+{rpCa~tkMKhKvybQl)QbIBOs0TlylD0 zb3&e(L2^ZcieF*;@#Sn@9^qxZ;48x+m#ZJ9=X<`M!<@zK4b#D2a6IbFC_ao=tkoSJg!mG%*hxnw6tK>lg!YQBUOjvSQ2Y|oA-oHL)GRpcbU>=Hw&dZ+ADN!MZ#2*`H}TN+ zm?UlV^kr%#XGpHOW=~>u!GBmdK|qx^uTt>+Uw{APNN1Mpw-!P05EI8Ucws#hvd3O4 zt5byj(DZsAjuGb&9F+ODL?z!c`N|$vx&tTMY(D#re6P&qw#<+0y4f(788i^$rm~c^ zvii27eUPHi#BDhuQoC-r`Vu&YBRArjxwcM(d!94=tykl%I_%*lO3O`Au2Ysnd2Q4K zI6F1)OihZ9+Bz8bIGhGVOH<2Z-*nS#^m9M2C9}zkq=-U-Urx<|L##*PeJg7HVyVy5 zhm?;+AYz5*D;x;Iut4+jv66R`zicQumU$8RRyJYF5Z6)`*j{aIPcf!UoG36rRYs6^ zaWV(HcZbrp>ESs!qe}8fd^V&juzS@(5moeg*Du?7+6r8>VjVppTTXW!Kljma1YvGa zX=F}U=#T&YxNJsBFi11xJ`g<0U*EjcQ_dJe3vGiRvRjcZ_doObKuJWQr%!sXmX;q)Z;Jm<_&KMd4cBdgGcWMjt4{Iyu6zOh2WEip?yJ_5;#26-eebl~% zn8sA5GRW5syx$ZEsyc<`Frb@TCX3WBC)cU!(=-rh27x_zYlpKnSdZW{t{h$9C+o$T zUByV4JDQ_Pju7`{B(Ra62nRY98f=qJd=pF(HN(X{F?{%{{L}HgKrCacAbgw>A`XdW zE?iz8j61>QRqpO>A>>9)rQ95Vk$=8Ql_*KoV>h`t#Z^Y^zW3z0L$2rQ6^&!W{e*$Q zFT63_+ElqTvev8t9f#FE2X;K*ZF9X$3cX^|sgrM3m3`(QT{-g54xd6;>Ie*+Xf6hc zvWHBeg-e3ZGDAzIF+IbUy=Mg5+_Mh#OsX);e<;XPkhf^)nXTCN9;H8MEXN`99bMya~e+Qx&L zS0Yzs5)n=WT2@54)x79s8;8(<5AuZvc*|@uvg9>Ne9CLfWM~5IT>=FVhZ49gMZ6i3 zACC2im@6tj$Madrdohd%lTuSw^d=>`qD{Kv2^6X7>8Uj|^S7(+dNOts z2D}KHe79Qv8*n@F z$w}MZg**0a_Va*LdUPL{TAWpU5?Om~%9F~2aj(oiGnv7_;-TaG-Bin)8HvynWpQ=A zU(U5Vky7>(#v!dJ{=a#SrR^TQW;wfXNVUa<(5&VTyMt8_@N&f^DN z-n5J{1HE~tr>dN85|rLp`&re4J&Uvu&C4h)#+4n`e?W~Q3-d{xCm3q)#*vwO0xSxd^?U<7clJfg%LNK4l+H8K@v7O3$VAUeh(tGNTfGgFgMp~U zXE=Qq$u9Pd8r;ISwO<_m@L%9E{wM;C5ckN@N zkOo3BDU^DS4R5e>y&8+D=iM^Zdnk~>g`%W0x;*0BBoRm zmEdEExn3EowYH#pD>g0$KH#naNt<{XvulA@jpeLib|1CPokG7#rlD(K7}7`4 zSJJ`PFWWA8J7PRiPYa2@L6-orJbXj$_M`OU5gb;X8s6G7slT+El-it9B@9P1_DR&;iMDZIk{N#_wgL)c1WG?? z=CwW3>D@31&(*!($-CH9X!Zw1jPJw8-H_b;vjUg8s<7UK9BJ`ZLc_ehp7Lq9_;C00 z#aH`HP!+EvC59+j6a{Us6Vd{;rECd(7T&BnvzPgJ85FX>t*i%-#x#m(@TYaGmrt=? zkrjK*tMFK2?fE^kN1!QF%~)JN*W*oa1-}GOF~u7Fso!X6GZN^+;c)+O{@Bw_bzV-r zN>l6L5?)@;Kjm>iYHc@>3Y%u+9c&wsstZg@^B0&sj`7QDf!sJdM41$Gu%|LMuezVJ zlhEoFghcLL6s=R2^xO>9+Cj+mjXV5qqr$_(J$~4$=Wf9Ur22yW^(B-a2M&Y3h%BX)K3SARezYSL13$x{2FkF?}nd&(#J zp@lD@ztA@Ox&859=c{@8l|G@ui3S!j= zsC_(KoicPl)gdUS4iO>y`!MW!c2UEp7{iv%;4U*=TwB)F?0>`R>MGaJDp%jmAc8Fsj`=7OQ}nGaBVM$)7z+-gi24@3 z&>+&#EX5d*GNkJZ{cwakBDgSVjtdj{9x5xj5g77cG5=wA$ysUigD2#JI4Uia5V$J|U$MIS04WX=)5S%icUBEZbib zW@xwHD*0D&U$O}c{#`s^9#h-iRTgIOrK)(5~KlbXLLSV8J z?K(=azZ1OM3y@v;BzZ=;ZxB@4vH)TJY$sIrHp#O?#3r94Hfspk(#+bG(Q4c21Ii71S(K3P_&|1Z$mnJc0hP{vP7fQ_9j(32L2Q7qevNCZ17yo z`x!5YL(`a|9q&Xpph#vMmJhx`XjPeBqj%-;I*jIS5(|1CxXR6-NU0nS06F)!Snb#`O?R&3| z-dI99F8xrUoG&bTk{j)mmB(CmTs*hc2}dH(J9twXV*@&=uGI37U5Act9=d?73eI{9 z;_w8Yt)|pOR|Na_I?);|aW|B7;HVE-S3fOu+J2sjK%#SCou#xiW#YQ!1X#W5-PjSh ztCMA^MJuNCHb!JnOeosCm#d@pi?SqGA7u!(~KYw#O}Pfl)XUGI^r`T z;?!8aIwBu;s?;CspYVrk$;wkuA4NlTa+3bq_{Iz!&RjSB1mz180*0H@A!>|@!N;s7 zGuYa3dd!42zJDZA^C~A*B0RrH>E|~vRq~N!Gf4D7`0n)H4P!>UrOC-|I_IxH3x^9D z>Q5f}Vh{T@(H2Q5iOl1=Sma5GiLF6f=Xej1^|v2m)KC)Rn4@GN{gf21HL%eWU*U_& z$t~S3spP{$qDLwHy6hHqVISS+1%HZSDTIVUML&Q4G)Ne-srkJ5ci)N%hIww)iSwg6vM#97l_h>H0WbNq2NQ~)yM*+9{Lqx@WBI-zW)GjWXPs`u>;`+CS#*eLW`v3}D61Gb?@Wz)L8&_(Bo^ zG7T!GB=-IzaOwjye8rUh1vMz3sN{zO`vGsvPF+YOd6I)YJyC^vRinSsY*tT}UDOji zA|*Jc|9O_@4;j~q6vdj&ks<>uD^)^4Ziy#AwA+{=yZ6t~wZt2kspwDSr}#3!Uu?X5 za}pr*L)X55063LpNixF1CPSp7V9U2VWL3IJyN2R8in~=hJ=+ zA8eXB+G0#h%zQnQt@kVxKrv^p>ACP27=4>~x%wsAE7DtTo+o%pKR?)nvUd!uAgt3r zGN0W#;hr@BW&1e$JBMAQ1_h2Hq<5uzG@@Lv20sRg@~H+VD7v*VBbl2KQON)Bxn`#J z+IY&;68lyHMe~`KG~h7=)Tb(Tv9|q+ROsRGHC`;<-Nxau_JCQD^qnwL=@Xy9S$=48 z@ig(XU~lp-1h`N$?5OZ8lECa{O(0Drslbn5^l$4x8yMm|oIcfL#Cr;B4MCMpj zE=I05rcMwDy*Mrm7gw`TgOpq=iQVkSo%Dc}EoAMCk^W<`y2Jc@QsJ|qer|Pm{m;VP zYkd9~Wkd=@%!sw3@gJv*k6^HawjMdM^4otQV#F>g^&9N+=8Kf!k~ znTr=WjAy+*N4~5{T623CcIRtn`_(h|5=D;KJ}hE$lERsv`A4Vo=Os#0$T2%Y5FcHm% zP421<*TC(+HgQAeo@9Q%!Oh-x_NH|5^_gw+PlQvxR%4*VP3~H=OFx*S-*e;j#ZA1q z(p$Q@vp!E$t)ivnPt(DwrS^Hdf63iY)SwY_8&#u`3@>-M&JS zsgd|eQlv5SzR;lPvkpv34IADk@cXK*lkfQuK9JvfpE|&+V(+}*@WdNzujXIHAr^yM zX6ttHukK-nhG3WGtn(F~kP=I%Y-=mIgTo;HQCs+6WRyLI&v~3b7J@jFit9@}U9=b^ z`eHN47nO#FF08f@qDL4KKd+t!skvlzZU?%jq=ga- zqq1PYIZeKcy-H7=MZY!61}6QUToe>G4K8%-*(OU0B0oLNfA~N+hCXj+4-fEUkK&5n zJY{@EG`^W71bDAYe~d6%M_mUxfX8Y?6l;_a=Bq1&c*PbkTTE@Lb|8+6Y!&}!S7;>w4r)oleW1l=(0Agv$LsIg|wHGHJjDMT^Xg!z{!yZ_CfqLD?7i( z8rNu&I@C7Ws%>DDBk85cvmMt=!TjtwuH9-||5D6Rc{f~ExZ)2kM&OhiFr zhs7ZLPN5ctv*{@j>gkR0h{`XxtG3cZ3Mbwy^2^et{V08s^IwfrIj^)NEsl>=K(`yv zP$RezeEq91$;^-6B(u{RR>8j*L#1;O>(ZFTTgDe)azuLHle7G>6y)T-Beln)^;wGD zX>~M!#37J3lK(OfwAg|gM8mH1fm?pNI3XMEbwTuY&!a!8wIB+%8cKa)UR<0552Ha> zG(F|D0yY*Ho;63uIaeG3<{nXy@B@t6o+rX~cjKo=ys9ik6VWBgmF9jTt`XS+6e8i)6E_9SE07`In9A@AH9<6M~Hl}H}d0(@;AsAJ8#U+ zSIX-G-TmPO*}bETFSSBBW8X)6)YWE!e6Z_R9*k?vHV(+=WVE+(<@)U?;$Vv9e>+}P zqE@ruRI`jKQc`H^>P6tn_}naZ(*l7^`hv z>nmR&KNtE=3ZDH{JUkP_tC;{088B<0Ez>#qB~D!uxHg`|sor7y6%gh;J4_3rCAR@M zCuuS$H8B&rloO7^kI)tsI%@T}Vd>>gm;U0uA#u{5T-^4B=Z-p?kZx1`)ppN=>=HNA zYZ|GWn|5=JLcPB`G|tm6E)S%-h7qAwl^48dS`M4?>*KCEYb#RO_S)f-uL!@X4L*Oa z-2cLXu1V2dMtdy%(qlJZ_LqwY8`CG*?c$8lMU09vG&NRt#o=QW&RrNJDzU7)`O{?A zYXib#2krQKnt#^{)Rt_mF#%t(X=o7vx*D)5(?P8d2xLW;|C4Ys_=I@QKr@ahADMJE!x)3L*Xannesd~=`D2WWJCM{mGt5V%uxCg#!@AlKO~a9 za#LTZq-4oZJ%7E8*znUnSN&LGEb+KB_?zl*+q2SM~D zoPx!NZATGL?4jKOhfq#V?($pcIi8%H5?9;iR(=_dPaxr{Cd2uWxryFTvfeWqjb-P6 zpa|hJCnK@0i<)P90B!+M2}pQUJ@(v@QHZ=>Qt1ZCOv;iJg0UQP+-21n5(_~Yn2o`I}` zKUR3uBb|~lJou3O>`2MJee`Rl=<8P{&kjwWOQk)0j@o4+32Z>E~UcPYZUSGzsqmll(a@+5ElKrNs<7Ug|~J# zQjhyD{-Q@4TE(#;Kz{~dBEPNKHrHslOVxOSV5FPN(Q`Z%%J(tm#w^JU}J@FDG3Ed}XT z;%Q58`gnVEPv|LAs6RoOx=EA^SyR>Ck?Kj#zDqU=mI zg#*Evr2#bt?kswx#^z!EaE{)tWupgGbsnKB>pwI5`LbE>lz;B_F}-lQ%FY?riQSkm zEHwJmJYdC;i7#2Mtj+@8(IL(OwrcFv0OAiglMjeee*}e^&6)$fQ%D3#_amN6N1o~M13aQ?> z__U@{88fe-ngin)5rB=|eQg+~2DPk%%>pWRI|B0+lVYGW(2Ju^2MhSq@X;cANr*L- z0=BCeq%=afz5;aU33J{ts^~!baV$xcsPcT*E?z8S^tIiQNW4m9KF|oeKfYfAzF=xO z%(j6v<^%mpr=1>jDdY90s6*7L)A#8M-OJ_tcytC~Jr(eyt)X&Jy_@DKJvuqX%jVB@ z7I(gN{*qlP4UGc|mEB479z=eI-gyyyWGeLeTIObP#C$~AWX^c zZ8IlW&y;rL6Uxe=hSpfXlDn(p#_8OkhECs~_E0&!S|0fT{(sRBt{kPnp0HCq3%F)6 z)JsTXf-ui(%7B9XvPm2{}%`C9>US6PJcl8Yh+#EJUoDdNf z)kj;Yuy(d!=W^>sx91#MHeZa89GAE^vY7IkzB|A~DR(WX=H|WbZbz;8Z&~HFJBJv_ zK83APC@SA99?j-hY0QFGWU)aBLpo#pl+w7QVVjbA6^`LbJ)ryJ;(8!iqY2$nsj(qU zeDmRLwfl0z`^wR%vr!QT6>7!ZEBSYS1}_9;D94lr@mkT~@e4#pboH^{IQ=aRVELvp zDjZ!S?Jj_AVf;_j6w3#gMOg`(7VjdL-3yERpa3oBQ08Khx{fX>K{L}oK=f8S%5hBeZnW*&LJ9!zXLIS+<@UA5itb>YwiXfFA z30AM~4g<@m?q7zMxs&a^>9G3ig}t4+Nm1Kvc=ff+d>uc`X+_|kNG~lj?`&+uPsx@s zy@-xq9Hq(FC{wf-e|i6{M05ZY6kvaqf`NoWwxsSv-}ul8?xv9tggDkP-p;=f+!tA; zE5JfQ+`g3pAVPly2SziB4hv@vnN-iljXJ?+y&CwFYX&aj(3#Sz4Af!EUcv(0+`lN- zSV}yIX!(usL;4c34C3_-m1c}plkc5rDBbe@H*mmf90?3RvBh$_`QZ+|Lf*!fKhhN| zp#}$h@9}m}&a*#<)MF>ib|AG2Ui_I8g6Gp2{Q)tQVemH8&$J1x4SeZQL1sV|jc)m~ zQ}+zTH_d)qsLa7HfTL9~%J1fACSAgqYP*OYiLGdEiIaf~gO&;8(EY$4w>6eF;4z?r z<9mLp;gcz!Sp4GieHmP6?Pe2mQ0C2OFDd@p;+uZbY+mi0%EYlhBO;ktOL8!p9b$p7 zT2V!c*v$vH$8%2l7ZljU`#m5r0Dm=FCK7eKpfSZ7f=2ZG*Sb}a=488_^&9xTPodIr z6hu~DZ=N{orGx-IZ79>48deZg9ZIE;b@TysuYRNa{hb$*+!*JhxbwXCq8#(B9vP$^1!1YW`L~r^`DX zS=OjEBZ4p2e-eeRR9iuvx`m5r}4%5pmT-B$3X@gd<|w=HaGvGJrak zf#k#xPTLz9>Sz>vLV&g{D9qX5ZQH-wv{wc+CN#F(@%DK7{xUTfH*laiv;@!(MM^LhqPOLQi zkIf>$SW($Oc=1enHCEPgz>Mm3ea|GmwoEznH@m43S8*nt@ULNII=cx=G#Sz~XmYZ8 zUyMF=j+bN_2ll?`F#|MGmMc(Lcqx1)5+wFYxoitAvyvOneM)HwfKhU5Y0LqOtQEt7 zT0_kfAK+D3UX+KHMTp9NlT7k_wBYrwReq1#E=a0W2=WKlk#;VZkDy6tykbTbZ5Me; zJl|6!9Tw;=nP&l#Z*4^ffj zh(<=^!%kw4CM6_ZV2m1#I^uKn5ob;L7V#a(Y}s#J{iTL3-WVaawhsyoUzFOTd1&RU zqvqm+UwRay!Uv#&6ltAgJK%RwV->w%NH4ujfDo~_bEtj!fObasoX|G~Z6!@wT@vsL zjpuT<$$o*Wwf?1uQfsx5bmzPE!n}tSK{an~66KXLYDiLWWh9msY4o z-q8u|Hk)zcoKF48SuBA&sAAI5)q0&rxH@US=o+X@g7|YJD_g*;G^OO+^gmI6&uxQ z3j5lj2Vu$rwS>~r`{FXr!asu@9V1LWM7NHylZ=8SErmP!200HCP$G+sNDAtiIJd$2 zC3AZ8df(eSj`&4O!f=fxVFdyE5;RJ4k87}s1qSPj|>2}kQ_C0BNpca&Thc<|LM zm3m`bRHrkw0-xtN(9K*DHnzZehKK~*TVuW7o!;W{k2f@^zSuG%y352E zC8dPK>Lc!j!}pk8zrn?HS^dY$iLf|P`h=uww4n+cZ?lFlb0}m6z@~wf64UQy^=+B@ z09{Dcv?1%~C}VxI)nw$~K48z}7&(<K>&C6H=QZIU57M%@>l#$){g1u zqRC@e?{hI8o**#F7m_?(4slKU}Doahzf8N~be6aH5B%?}Yvwn`$Rj{-Ibi+T5ivqkY*{En`j&&x z-e){pKFA^n8`1&D4H}kvmVE_WWR$b#N~>~6Ug74s}{xZc~hX{xa-UQm*L@LJ3U zAAdbJ{iAYrR7FR>ZyXaQ^^f)Ym3j__St1Of(nC*HC^M2%fj}LA#x&nn+xN=0@UXBm zh57&7LFm5!9##-M9U-s((%BIif@>n#UsFhTx+TD}RUigXs4n{LN=)%`G%Y4NrIe3W z@tBNMl&!xM3e|9b2Y2y32m`Oi^x;=nU5^dq5Kjab`&v$%(|Tp6D{E5&&n!>|c-f&X z{&dYZaee((jS%5rb1FQlxdpS8phig!IUsNM(n-`HjIoeMZ#8-x!tD$Y#FNi(J}Jc(Q{}E+;m;)9gbzFPY>6wW8OsUzi!;(0 zE^~maa1%1geq)0|h!KL*@juej@uwH*VK!F4sG&0etIQT8;K5UT^_^ik9^6^77 z^~sH&<^8Agi#d_rwY%#Fn2_OE+T>G}lSxmG0+hz0WXiNk=4_L@kXpDri>9w6;cF3D z0?O{e%SJ`{?@#o2rCyYGbK$G}nRi~lN>+aAlPl2mf!VK{A_xx2mgWxK6B))VC$Cj6LT)etp+ zSq_z=DNj?q-gq9J;7c5bi=d*W90DcPVjhy`%!%<8F~p%8jVW-cZTzM5$Amy$VI#m# z*10MtN6C*|B?lj28aClY=N!WK)w~bQF7zDz^!H(xP(jkp&NkdH9{x@^c=cOMV|LZs zundj|CnQ*E6`r4%o0glGo^&vN<`Hv)_6AGkz!F|K97wru$}JhZCQ?MhmEx(3`?^%T z>D$R>6h@kjB837qrFRNrv7Zo8?qOpMK~s1U%cnfwo>^)5Q`D5%kL8Oc|K|l*4m^G$ zI)$>B_QlS8>OB_iIU&eE`Kn&pgXi-clM)Q>Ex#EC?1l#pZ@@D?4Gf#OG)ou_PsWC+ znym-YEEY|<6|>7tFT(;W?;bkExkR6X&K@8^+a43YS~6nrR)buqGRRkg3>0927o^Z| zDR4n>^*Rt%=fE(sdTqedTyh>bQp!?7*)kwJT}>DGB})vqH^a^#G9OTV1q0+ z(;Jf4kEtSAP{ngZQ?8H{%?~XDhpa!@#A2qldclhrIOVr1xbjMlLKvd2F`)M^d4KO7 zDG4Z1_2sM_Tb;7B zXjuxX$#H#7`dx~GTqiljugjDBsfPL^K9j$PaV~XimCdY?0ivO%Pm%+hghukSM?jb7 zpY6xrF#Lf=Q=IULp=*-=S}%N!zQ9+FC2KCoW=#p@W92NcW{zRySly}-T!jYC-pQ6D zz|i}S%kpkM)S(C^cRR#AYu@bi?p3|FmBqF3zwDJ6T_yCbCb!{amDD<3Th!96y3HI|*L`;pSU zs;3YS@*;{h9o`G&LN%@k$Ut}j>*-NxHMeSbCSR?+)jr-*iDp%@6{CMs^T83^&9fq% zY(_e7c5h!uQ@E4Hc9GoQSAvM21ABBJkn+BrO>J-_J<>0Tz{d`@->-geT)jqZ9i7fh zE5Q8r1ie>K zIo2F+vh(_5nH?o&nRT~H_)zB6c2&iT{d>WB7zIctL$=3zhc$wcrfju`Ti{G?$d3sg zum`o0RL~G(3(3;c72`m2n3IV!c@3OmTndQ7+(Kq$u`xSrUJ_Jl;IyYNXTw1bAp=HWmJ*R;77JN;D_LhrFphZFP-3M74I+ zP@ge`-iCe4uZgYmgqMJ$mO^3riGPA~>TQbm;t0O-Rt#*_!OTN>Xsj4DK~}T?SNA_D z;hXX`IHI6ZpB`J862-!#Dl8RV)zn=^h5_tYa~5dc?a{e37LPUZzL+7AZXG8qxdbZe z13`vtaN1zF4r!ZfBeF-fg4?LrDIrKvo25@FxG)Ql9LvU1$l8ws#>6(V1d)hD?I&5I z^5=sT&al3Y8W1+hO?XFEYRp>n{)K8;ywHTEVzJ*y(T*gGL&2Y%3Zr$CNO14@#>{V^ z-C3|4&L*!?t5pMj2M z`yjKxA>-jh_BpH!!>2g~9Qd#BEs$@My#qV!JM=*oboFD8CqcIe^R?;wdXnMu4Mn&ypRas`r58_czT)+Uhz2q)eeCci?X+CQ3t+6ZDUd8G;ciC+WY7F zi2(Gm>`!{0Y&B2zpI`Dq45+i_l-q~#0DxH%ii@MOm-#&i!p^vR;YBPSbg(Q0`ZTxe7ff@TR&4ALd#?86I0TFds!)L&z@XEZ%}>}N(OEJ5Ygi?4>lbtveVWopWw zO7uQZ$mK3no=a4u&!qCysX$dF6R0}HAgmL(gaUIl)FoSu@l0up=8<<0f-h{9w!0uF ziQL3I^_eLEd^#?~hEXF3J(O8f=3>vGzH>+IBx~+@RR#FRpbxT0@l&m*uyU-kd@kHtHIA=~zy}qq-EJ)dc>A$8o zI$J6>WY>Lt*~n@>6~4~vR^^k%mgHXPuFxBov}9+s*e{Nmt8YscemY-B3|ah{2N$mX z9V?Veq=ioE#72*C6eP?s-9cyGCPgjc!Xh-}U)fKFQFn7BM&W)k`uxnTr1z_TfKSWu zX$RL;436PG@hv^W(XaPa`;?nzTs>?^_{y4-(&m)yb(J)G`*?`!4;rKEC(OEL@-=|+ zcwe-?4mlyWk7HcrD02v8Wet=9VB3~AzrVbXD|DvYy( z{vV{2eiXT2AChb4=AW8LPlLU#l{$}bLS8vAJtm{1W_}7xDHoTta3rL3OhQZP6Yccy z$#zHd5P!>vTHofy_HG3>x| z>iwP%SJ%!ASiF+3i+wjQK}Ziu5HOhrqe}Wte5(|C${@jbW~to2J@}3b^JTQ{9oqB! zV9x4R@X3=gW2f5_j$Gn*pH&NOML^7fHp@jX+xEWGiDfDX~?Itw{~MWL_)R$LF`lQFjxl7Zt%JIW~g;!tky$X8{D9i)nMauS^0 zMfWgqgY!QnS{>wL0%wbg+UuM8ryKeU4;mdSihqY&P<`KZttC1eom}`#WZ)%Rvo&@e z$}MY30RIC?LWe z;mnuxSr--gdQDVe{~^HKo2ulQM@zE=GXurnK+{`CA!us&-(2>>JKvP~*P`&vYB|&4v(5Zv8@TX47F?(Xg`!QDN$y9bxx?hxGF3BIsr zpZBX%#b1`1Wu~Y5zOU}txv|7|kCr6j;e*8vBgZ3;ln6G zrYh!O1$S2&KUEopH8dudv8ikpf8&Qt7#Rs6M%!57c*-urcWw%hmmS+PFq4&9>st6 z0?ik43{DxHR%ULVu9_miB#DT{~^Xy%E#lExvcMn-GZ3psvA^_6sr&E$8yzpQR)u~&s-+*|p)qaf;Dx@;3DKu7vI-QNW z26Ignb|Jc4V!T9_(384ccoZZfiwn6ED6wd){tRMR)9d~z@ht{ z;n;m?^2$XR&6S|ip!m>=U$R5FTW9WkU@KIpw;~Ua_~vDvpgRBE^E(TL+botalJzrc zokW`DTKL4`{vBROH5ql1RMC@A28#>3Lp@w1zn2RYvkG(>JfL#?)Z#v&Y^P@R8L*;%E6NIFF{O930xO*%{#Qdwko$y%DuY6 z1fabOTpQ@)e!sm$_bD1RW!>FAC|l}8|0ZMN-aGbRb5vw#hr|3RI|q!hFEy>cs`JqV zl$-2qM6#ZM_o(H{{ae_Sn@W^r{o{bR{35)Ay>w~te=Gxq{mGs1|l2P#(5K@ zY_Lt->&!7Cb+ZxQ$)wDH9kUJ->CT1em$1PT(=@yR(q^0JpMd(+V?}fvS+)=PRODC2 zjg_ug@uf%NEUP()q_yS0pib0N$s5qN(4T@+4+OWo_y`aZqq z+y7maV0VIpPTuwRw_61+y(2`TpMmI*j3q3+EEg#WV~AhXbUQ*rtxtgqz2QV8S3_4;a-=U10-*9y3IQ9thE39hh?^AO4;2g%-E? za>0T;`GuPml&jf;MS37OF8mBi2>!Fj?j^AD1^@L^ykF#WwEYLk=%FS^7N8?jv*e+M z^-1k3@#XvTO(PN8V?f%&J1f`S+SAlPM}G#+lciiQ67ConI60h&7LU(@r_VvpgJw~} zr_$EVN(&3F6#+O1!aJE4+F$C97-h*%V7?KpTnw*SPO}2UaOGsT_#0_8#c#xp%S|sj zDpcIM>~zUyn2)%TFF1d-09&_Ubx>^S{;C%u1#3t9I1|rXL86HG3&cTo&x4J<_4G^Dk|9estDXH!9N9y`6jC47%6@Op3KBKj<&LNi7bfbp2{x9gF0W9 zIOViY+CGbLvv(u`k*8lz+(1H-iSpMds~Im?`-1M76{r6UlL4FH&I~>QHKXm>C3VvD zh;>8&hK6kqaW(zAJ#F;!Gqf?a3AqFP-ep0KPs;mq1wAa1hKFq~ z*{Yx>Yk(4%F#B6j!A)oLNX)BMobG%U){FX~qMI(L*L_Q0fR4BQY z$rUVBeCsu)7X3asw8pk#m&&-_3`h8^^`s zYRBOnawWhfoXrIGn9z}bOmL!9Yi@ZDUX>|VFAfaJD>G9A@{eBWGk2s2uWDD&u}nw3 z+~$6@^r4mej-0`^zPSBG_=g_%K|!|Pna1y2;I2L1diF<9_p7AA$ z`Ya_Cq=V(0_nqfUz6=Q4W_pmf{*Sh>9%=FM@K*)F*=KKe>-)Zr2St*^F6jO|UAuh> zu(PT~r>;wH9P7{r-y8=AMZ*V9f9%p4;X#*4tng@8=4vsK zI{W{h3nl&s5s|8xyQ8!FYtJV_jZz3co&&aSl?zPdDtn;1hK$k{bjV?d4jW5_Z93b~ z{I<y-AgCb-(6w!RawR64&)l7sogk4V|k)#Qi-7U^JBUsk6-#5 zGLEHCrd|Ra1Wwef+U9E^hI`IYL;5T{boR!QaoM=6FWl+_W^1an+epzh6|P&JPF*um zS~=(8@bG6K}0$r4my;FeCWpo12VWC zeot?j5IxF zb{jy}d;VLSW(`)%DO!YCCyG|gDB3EUdo(z!MRn`Ce00btDmJ_UE?*dzj%1It^$@p# z4A81e?tBnJAT;oqdO!}S|K|dGsX_Foi)AYy{xJ$bNN*}5AP2aHK(b+j)R-A!>Y45A)mDwGnqOg! z@a*mqRO&t#Q6?sQ6sq0f$neg;f+JVeAbq5o`BQHQW^?HO92in;N^mC{1v0HucCnTY zDYqhEg}|*qSQQ?fq!E&mI%g)Q#)>10qi4sOa^@8jb^I3d6-E)284E#}e@I4*RM!OK zDbXiapRE63_a`^qeS2UUljIEfM2Xp@{x5Ukn^npS) zs$`Vk4mDE}r7GGeor6)KCd|GuHK;^ zEyz6!<>3T>8K9xZ@VvjpQ1;GBg;QV0ix!K_U(x7ek$%m;YK%TKXk5L{KYF>am3#UU zp-??fnZFHL*k9J)JlkA;B{aR4y-_B*@A7uTZ}9 zy>)~q+*oVzcz)0Yi3aay2xYGE7yQS*I^n}Z2zH8r$DoZ`g(LXAi;qrnzZnI~fw#n; zU`B}a#D*woF#Ai%!@#=JaMivfYPBVf(11t(EgDdRh?xHq91KLYDWhuY^NwC^vr_lH zTnfqPM@A?CF{@KgmzD&LpY}QgqbWkRi3x==|TZf)}$ADW&{{p76v*7bgKM7Hhn2Y4T(h|z<|Eb9I%1rZo6xM)%G z8}|$V!3giLy4%aU4LKdVWz!&Q4OPTR6zja>#M$v%KkuLw*sC>wE6+fI6z&P-)%7Pbqao{G$+kHodHdb!;P^Po8a&GK3KvQi(pq{}A7c#= z5@csOG!&4%wKcRBd;gIDr)8jYdtvB(yG(;WILMwltJ>{Hkp?bwF=xaDVEvvD(6QHR zO~UpQde6u;6IH-WJsQk^F+a29A(mdt@Hin(8dtJH>TK2>BO;!dL8;&#!YBda*5?krq-v95W0M@bd|Z5mXop#x1oU@t8UVIzF5#1R z-H)q|&Jw+bQfV4&O01{P?TzoIx103PzdZ?5Gd}TQZ~v&;$k-ar(7&8n62EjG^l_x9 zfS2F2uq$}a8||kYp9bzA$VKQ&*nRi`-=xiE#mBF|dqLvXz5dOiBwI#Q)TH;n6lmxt zm}(>9!{~KD6HcnRO(12Uh3Pb*w>9d;(wGO``01D!Wa>ru(oHIc*FB7LvSzbF23e$3 z>%u$3Ijh)4j)IB9E#|PgnCI-S&J>T)^GD7JmT496QSJa4P7}Tg#EZ(^_Fyxib#}%F zzC;)vob>tazZ}$Yd$H9Ot!YYT{9M|VpLl(K4(q2f*WxcbK>Iu;@cYH}yM?d#_e~@k8uaGyjhuEj9Cg>nAoN6BZT$-1Br6@((WUQ|Q_VR!2^#L70Qoy6W zCvGRNY}Y4eO`dN!@cqOc62VnYy($R%RTl*Kg}d*^@0KrHeRu75`Jn5-1k=6FC=cW_ z+b6!M5^P|l;oa_P@7(Q$(A}B_TA!Ect+)ltz{+~+VLtd7msFkZ@9itt0^Q{b5`LJF z0^O7RKYg}3dC0+u^`5xd0(Aa&6-K0jSIl7&eEx zM!KJ}hgE9r$9&;9N-1!k1VlsiJ4wh*ZpEf%dff)pcAI~#{kN*dvy4pqK9dLPD6$Ip5N zHg%vT(s`t0_a9g;sjLTBiVf%0R@W|oC%&AxEnht7MGE+GLG1F?kaO40kW&{83F5JOx2HMW@>pI^(HWnT2w2NF%yXr;*=Hm*!Sq^w8DPydeQgnd8-Lp=zA2&PdKUH(FqKA zSW$k*Ma2MS89oLr>;=fBsw93LyPaWZk;Dj^E|b@W!JCHYc{9SjI2pK64@Lr?w& zsnF$Tn4h;1fm^=~(dXK{s-qU7PcK-qafUx?a5g&7+0wT2NXr+WW=1Ob)9sm*G z2hNh_kXXF@q36M!@y!xc!@*UZVaOsJ^0z=viQ;x86v<6pBkA~E8c5rKvUY^3vJ`)M9bk)1X8_l{G9Sb{#8FFFx|ynU1}xrzEn=ddpbwJI6r{fQozHsEO{gFZ zXvxtp%qYR>-U>h9WcD-L_UYrUnVS}Sl80}6@9)JHgMUWF+`W&~kLw}m-JtxbM||u_ z>{&x0$@0aKl#GP=t5x8jZ137#&YNZ61^4dRSNbqf5#Vusp!dOQGnxDpWbY(ATrW{f zV&P%Kq7v2z)$CnY-^(Y0PAyKr=T$!bz@UW`u&?h$|B9A9lkU1II ziXs4>mQg0ifzlho79c%#%*mMk5)!i`1)d7UgJ80&!ea(<4Z~!4zW2#3*9vI0N5;(M zL|N0x2kQJcmEk?)#4dMt-rv4V7H9ruMKPL>_SPq2{|+l!G&l*6hBzFv+MK0_X4_6h z{b%uHgEp0(M{rsj=Y)zuRdbxbssKs8zl8_A`oFPPhrx|@E+-sr+ks}dXI z99&AJ)9A6^N4sw}wQ>ZMd;UU$xoJ^u zLdutY)7h!-L_Z$(i&kEqg#!N|KS#7GH1{`n=$Z_EBh1^vQ{4X(^xNubw~kAT=fW-6 zM?zkKj z*hLilly1)3X9i#9gwl|6WG_OXUCTLN_JzRf*$+Crvf#egJ|KxzJKxI(=o$AV1C%B7 zFz|~Yq0HEv>_KFQgdF2r6|iM_FNIJPP#-aMg}-#(a2a#zZbC*r_(bDY7!>FL?W8#> z945-zX@(8JPj}NhVK+_HLFiFRG|~Gonl>k+!TpuSl|NO9AHEZcZ52cH$V`05rJK6b zH}or8nX>7R$a7LRfZ>Pl{F3KO9C&Gg9gmC1QQo!Tv%aBWI(tL*Nc!z2u-feQ`zGQ%7O{Mm^s`$(KM2 z`mT9Q2>-kN;|qd8zCvJA)ufEU%1WjHo>(Z;4NnhJOW6A#6ncZko<}bP0WRFYb)ter ziVg&DlF2*j<7J0TJp$c-RXc8(F}vdw$OO6D9I-xC^G*B^aS&1;kWuEZQMKZ77?iIi z(2CRS(oJy}9KuF*HUCYiURh}mMgn5cIAoYHQReS6Pmc?~n`mR#w69K|;?a=(zv{OiBsarEOnr-E_vu?3R(vZ7HiPu0Xp;)uY0a z^;}UzIz7V@a)2YiPCY7cv)S1F--)lI;qr) znI18VLjsyi^4QD-snG0Cue@Tks~J=mg}+cf@u&%Cp#~8K^%sx+Uj7j4Tf}_)U2`_# zjISLf1hBKeINR3Y#Y?<4>>BrFr)xc!S2>@48&E{YGSG=%(zNZ&UsGW(6fK^~$jJdw zJJni4k*x<4M+S`Eg_9}kxY|^lE3pzZM{sW?5c=1{sonU9G;K_kd8s6HDE}s^`8YSt zZhb-CM{_ftnjuVYq#0*pvS&_Y7e@Dq!|PhX;69>N&b%Tb&b=a%u8JPVS1#$#m9rRm zthYW>FV84P7)uuSSG8?9PLfJn)Z3W*sZo7k<6nceVaErlZ!Pm!IDIx)u!A^`jTX_e}{aE3Ej+VgYqoNz6r5GMHTDNC~63C#$EAI*1Ps zb7*9a-xL9q&D;xAKbNm5(diW3IyA_!FFkBppvCq%FGSu^8UtmMe=c4PA3UK)|7?mb zk`DNVVd)!NJFD2lY|vGuy=68P*X;=_M#ik)xUh+1d?XQ^T`fv-;T8Mn+GV~#zF6Kb z(COPfOVWRCMS~rkWC>7qN(If90yCChH|-0M8x*^*r;vxEk+)%JnBicdP}Cf z6CO7)ElDx>@6wIIrYlkM!MVH#OQ@nH9JQ*4-m#>=tNf8>Iu+srzxT5n+<+2%4|ALZ zl8Xr5rofHkmZBNl*M)!BXieR+QW0?F)hE5_`Ih7qre61%Tf`*R{%cNSYzFxx85?qz znz%Y~;UNN8;bgf%T{-oy(NuaFZtpoqAE3;3Fm1IDldHv4Wc;3HYGw8i`)wk@?dl%(9<|r*uPlb zvYh;%^R-DN)q}f?<>9HDl1@!wi&p3c#o`ivS))XBn_+y7;|YJN3j~#E0c+qta`NJ* zS`3_Ntjfv^Yx^h(rnYse8q_EmbMk{x8#ujY&M<5hX^fy7q$N%c*C#(t0DHNjk&3p= zKSx#SSo8HmHu~xd9_@hOGA;tsrBOMkp}vnp1jSUtLkcv9<0Phb21P@jsX|jrUY}zD znn{+ubEoIc#1_PKMH)oe``U;yn5PeurYc5 z*4+1*0yAQW(6skX|sYn4(&DXCaO`lcCpizG^R``ZL|`2mI; z(rJgt_H`FFXD2M zRw1bGEK8;sMa4|da|_o~7Nx>yVrQpo%A_Mw?HBW`vjnc~D;tLT^{x@J;_Wi*yo0^9 z#O0pHJ*17a)`C94nr^=|mVlEJs}}rUpRes>;}dxQ*yWn0X!`D<2o-TbKu;3mt9uwI z9Vktv^|3+ki!Y%%@C~N3bcz|8F4qg@z$Bp24>)B=Ms~S^2G$&tn5;%B96_&VSlO6x zjSLRLbgz#qF+zcWbd4^k>Ynd=KG3A_kR4@&(Mb210?vd9o6W(w5a^pWCY@cMhL!~> zn%kR`uX3C%ZGWA4HV~w8y|qJ7EgAdC>xH|G$w~P)4N$v%v;C!hIJXvlXHCq8|1SI!Ff~c^_xp#9Dnp>RJFaGqj#Vq~osWMHdgpG7Ov%@Uueu!R{9M~1q%*L| z50s^>Y6kJVB_Wq5FMs_7K4h6{HE6Et;tfV)Dlq7#W{by6Ebel@Zo0n9wtRRs*gt8t zBoB}#W|7_AUpPMei>YV#T*2;r9Ud*3b-#7uJi?`~==H-eEQiugFMjlwz;Jnhc5#iv z)|rye(Hi;itfQb9FADmo-RRl-wXu48hqkqG^YJ6U+U#BTX3oOX$d%`PYn2hkI~7Ow zx8q`MECbO?uSa8Nx+Cy50}t6+;Ps$B1&6oN+Rou%u8}>Lv9JHA6Lzp?%_$7VJC?|F zFPPs^F8k2$yu;pZql0B{C*b|Ex+lP4@b@?1VUD3ZFNX{{c1XBIRvTAG#AzI@uyy0u z+PCae1FFdh;*~YbvO?|X8T)+A<4fKK?7^W%|J7pxZ@eqZ1q=yLzcuHo^w0u&S!{#69!uVZJ*LK%jXN`V;qxz z05cxq{E~^fO46+UVe3}JOPAD*=}hc+@qPS^zS^&6y~B*)gSg^3m6p=X7Et_ts6heBSH>K#NG`OfViBm@Kq@W1JNVY!%O3U^?Ctr6*Q1$fj~qK;pbkfd+QJBn(wqLM zj+xK2=Q;@*btHF#?P}n~_Bj8+a=F`O_&Sw1VxVt|RNv%wrtY@ig|P8i%0umHDZz;cbxqRy%L*Y^e6v(|7xig;7p!(ybOR)n~s0`!MO4`V^p2kH<8H9Uy$IS_Y~b(i@C>*8!0zUBS>%HF3qA@r^6T?`yg%@% z!~Uag4{-poR~TSe5S6|{-3xkXuF>s?lp^_!RQ%1E$EX2`PyKOCUh*#dFTc6A#d9GR z@U!EJN4=wKkM&zq%;9*S5-ZmTCpn&!bi>%e<3oAIj@kRQXYx6Bz9!icB!o~#y}|w& zE=%J{VwfXnaVN?4QYf~$N~5e=H7b%n;Fz|2wlA!2F@w^Zc7D^QxMO*w@?N&B&p&aL zcxy1ZgWZ<~LG7&18-uOYH&^d>39xVad{-#&m2LEgeq=HsFEvJn>KFe!2xIWS*J||G zs(gRn+=Iv~LyBZ`>P=nly$*uuxzFJlwz}uWy{mF~LN)O3MASW!%+BJ~%|Y(u@e#wxiCreJ=4bsYG}(;fcR^t^w&hC-0(6X()fPOI*AJ>LI`id>71X~g9KbJm-Wl}$1o zEjpg2=z_aZ1k~9Xt7TcxGHR=Pqt%QsO>Pf*QJaC$Iwi{Srdp~UB3%i5Klbe#)TLla z$;)weY>gIM`zR+v#>}68mt5=mMBS|*eZi-G>V<`Wp>MrbZV{xex8l4)FE`~yX9Qc zQvnN%=2S~?z`VRXzbmP}JyCW0e>)@bbVJD*G2^LWbTkBF*~Bu*4eebG>l@ZqZ6>Y! z2;rjLEg$w(wsrR;p!;Y4fRl2Po`kQeG`lf}FW~Fm<=+x7z(Kz^GP&s2d=7qGxP)uj zW1a>Xrs`;@BW8)SO-VzAsZE$nx0Qcw0z^B}Yd$LBYZeXR4^7H&sSC&a_Cv7_NF_~Ff>s7?&Uh`5!*2#;~^=@cOVx%HaT2c02@2o z7zZ9Yg?uUHk$HMGdtPiS5IaD2g)H*B;R4 zcS{zv(UsF8zY#6QOxNad_M;&QaSxA)T>hIsJ7=R7?Iy1JFqHT?8!szA0{#U0J-U`W zi|nuE871&+y`$aijaBBANZANkSX!`Iu2X^++O)7Zr-$|T1YEnd@>;vLscP zyR;>$YFGm&$=HWSCTvGWQ}H{iscPQ19uYAX)p_Y$1j&?*2UnqL8mspQfxZIP$&54M z7w7x@LjEB!%ijpl#T@u8~W|;qVkHa2Co{9#dw)pb?Q$rxdB_dAaAJ|9$84 z-trwdlOWU-c9t@F5F;LJSZRB>mW2pd*=&m37j+dSaQM8eq`R+2p`H!zGbMp}Td9oZXuVLuzj7uoqd7MX)Q~6Z; z4-83RkJBot@+c97R7G03`Do^)qWPTF5d<(6!9cwVd!=8+?;U&sY@;(jX~(d@=?p>K zrTqWpGVhp{!12O{Vpk0sWI@7CzHFVHJ0{8+;! zj@QnhFSm6PhqdjuW94_5^uMmB(1E}U0<9~>nP2tCyN%5?dJA2RdWn{Yp9;1`eSIA_ z(y;)&#-P#%3)J}E>UpV8rQ2U|8{P8G9ps4(WogyKue6Q|q4Ygw3^m~U;kb52!sv;% zBL}z~!_)T%_el8B96Hl(G{3{pVu&RK-tUQQl@A{qffp0~kZEo*Qxhg^G9UTh5}UU| zkz+~tgB31rjt|g&$gZ#PdlluD|JqRm2Mo<~{I!mo)5H^RHu$hZp0KkTsZr*o z^MSSwtx`ne;J+*>QOca%#uZqWPChy9Ud13Yw*-FGJlh7^XdIXY&K@#{A1sQN>2ysZ zbj!L$<7)<-Ht7AA2DSnZIezr~&RgMv17}ft{qu`8@$g)a?^{h%^`HM-Qd#@_r&R>~ zK-7r$u`>R>40vW6b)i7>3+8SElK;ZybUX7!%Hh+?l37v2NqcW8dV&v;=T>hv9M`iv zd(Cg!MPf3pvL6eS@`gS~(@@2d0KRp8uj5i~3fqFQQR2<1^tkGG0c8F_x}jz72|hDV z{r&!V?%yh_(yG;ItJ^*i?_4|Ui^}RzCfJmb8ov#E%eRh>vot;E50vWHl) z{Z+YY`Aci%xiilKj|c1avYNm6aA(RI>vaw8+W3B`Q6}(nY~1A&xInD17qxsdZAj)lHDWk-uc<=*msu)#n{~ImSc^E(QgT79 z!iYu6I6G2m+8jldO9{9dGR_s2N$O9lW<&Ljm2TxTtBEHyWh74-u}#J~{;wJeC#m$> zynxnD_qKoL$7quLQ})Q<)AKa*$be2^ZE&8tH&8TvOo@$rH;%UTr=1u?$&fLnP}T2e z9KdWCaEYVKsSz?T=l-p%v+#@pmnGK>@m5-_w!89%tf7F-NYd)Tu-A$!42KH$;!2FhsdF>5 zb5^eYMgoxmbvwHBqG-nFjT4dqMWMF4vb?r~S#mJH~6yKSChZQR5jwLXG zOw>x?aqztjg!6UmXRJ`}*#QM>;j-;c){{2NvS zaNIi+8G;|uX7-6*`?K{=uU`|mJwh6McP^mGF=t3V`t=3g`tuNMV=L1N9e)Z6dUXrv z=obYq|9=*s{fYw3Za?&SbH$OeTPM@_@1V8cgIq!qk+QJ&UaS6Z%o-%(<@K}-;ps=8 ztGqz3Jx<7^$K4dPoj)|-GdU$qncJB+LK&uL#v5Qb&W;jD0vB3nwZ)-KabL?45WOsS z{3QFyyH2%!+1SX}D_`jgRuhQh>Utu!zi(YU>vv*S)3o{C5S*frLGQ}t`}~Zvb@-|z z-ugFlTFCEGq;0b0&;D0g8QYN-(#T8U3{1?25r!Zs;_aqJ!+VxC4VHZZL!g=)5V#k%3a<}G zaQzWd$IN3$=lbvW(6F3rT%YZD-=%!8H+xHsb{SZ{8b}IM=GRw~9#WTcbGBIz$e%iM z(N;zz2IJI+R+U(JIEW9!&<99m3JYwO+0^*NhSg4WpTRKqf%hf0BA5}MRcG|Zsq3unUHuWiWl=lX)oLr({(r*;9o^K zZzl1#V(*lGTS~$@aeVR2%gP$~(R=58KV1e9=watfma{@nvr?-8$BCj)`~x7{h|)9* zFPx_D+>_eg8N=x*R;xvbNQYsm49V(m_Dcj?qHVKR<8{U;a@7MZm&3Dj^K#Qu&AF<% zNt;Jg2J{6+qEsP{{YwUX1l1tfZ~I3gs}`NuzfhhP(;d8aQQ{bSW0yozTN0AGnf3pZ8gQ?T<0_SGqXWP%!ibn(&Omrivuva^sc0wf^EB%i3+$GOG zf=Y<8WviDlu^hOqaC0QfZ>AGo0L8p6aZSw|=n@}64Ly}2?P$hVyKZ;y!HYk}@E%o* zgY|(VhTSz&Fk+qH>P7c&9|eBwavQeNLS{1?`^%iaC%7#fx}u^co~EX=K+av*m;;e} zYTNte=Yr#K*z0CTKu5G$O#PnqgiKw1h<+m?`WePv^q%B@rULV6S?lB*_H>eYMK_@- zWwYx~S~}|)_C~t_LURLHKCFOV@Uy&?RpqNzT@@8@2`uKr`@Es;Dc4)VKH`-hx0TVq z`#Qd>aC|5MqM4$0_EMu#ymqgp=B--cX_I)k%CSE-f3hWUEnw23jW;Wx= z1(5BrUVe9CX3h&NneVBG08abo?4wG5`nfA{Z9an@N#0_EE>Wn4 z!|b$ru!FdALf0>h{`45mZB|W*$!N%yx?!0X0l*Pk?!;QVLtM&v?>3!qOd3~<&v3NF z*(7(%?=^ZVjGp(pp*WBN2S3O3!R`{T@rQ3`iPoQF?{(TFIw%wrwj*3{5A(RW=u%s< zIZq&+0Qs^K2mX=v>SmGYjGIEPJ@uqf`(!R3gLAJ6@v=K5yO`08d~nuc*l)2w?eK7m zsE-?1-axvaEE3RViGvm75lyRBD6uw%tlcm4e4>yW_veM2puh>;7G9Hp2*;?-NZ zbpfaP1AHSe;7sEuR}3z|G^@pjA9N<#Y@xqZ1mXs6J$kQx1`#S~<4DY1?2i{a;QcFD zjNcU7ZuCIN!U%VMzZUbyq>Q?q$aybP*7vM4jNvNsD4a+54xOoMH<1Y+VRT<|hOuDf zBzKYg+Q@Nt+?JHDdoIl)rUP2_^x7W}&uP3=_AI$9f|)#3Se5cu*(QK!a|>W3swrL0 z&JD%ZW|50#!p6;vSc)%AY9ya@`PUn@^7C2{2^!MPoem{O$X6!;-|AfO`ud3DyUemV zzBPEGQ8D1m96gYL0NPm}`Gmi}e>2f7PgoYo{?4S~SwD>5m)`Czq&JYsXDsi)Z|3m~q zQD}EB<)AW4T~Vd#{nREl$gw6&rjCmIn=3TlzghD6YB*%vc6Y8F3SWjZwtQ=AwN*33 zi;0n@AW^0pXUz#d=b1K*ib(BKt4%hQ@pM>j@>vxvh0P3ONv1^3NuLx^*ZwF* zpSfpZof&-Y9;{pkOh^`}(!z&2j2dZ%*3G=q#%83$%l1Ekdcm*koHe?Ime=xEk@Rsf z@`{LQh9>pIKqYp!Az`w`m-^O$q=Gew+UN`FWPq-r@l z-ok->YPA9;+%}3zz_*{HIpmP4(#9N#~*_bo@((Bd3?i(*m3iZ0E?%VD0w_h z$o_#8%f`x>FDU3>Z>W?t&`L%7wWBOD$tt1DVyi-{(Q7+V&`~*$kGu7+7Zz;qu;7!~5=CiO|I(jMvqbShQ(I*1)=XV)Qc|<<@;~tOSe&N0P*u4!I~(q}??Y)sxR<-ZZ_-UzfO{(rSvQ*I@Cx zN`(F-6$?9!t27vY@f|r#y-rNmNY@8w@~ri$5Asl5O{Ni*#MOg`Wlk54CcWxl0af3B zj^Ge3<{%|v2D)+b1sj7}V=jJg^`#m07%;(&!|Vr7_YR^4=%lmIoSb(*-oY;rYEsn5?s zp>On8l!>aUbEObnO?`4{DU|HHB&3D`>Z6hfu>(9LwywAa^L(RIIu~<_NczB0GMx~O za)3enhLj{exNw$ml_-s}S`!f`sbmmv!G# zkgt3Esf0jR57Nd_+}navVCkEq;)bN^8(boZbBO2wI+x{W(79F|mrLCvb-3^Zhaud7 zvMgKEk8~JV$}4_IC9I&;vec2~F9cyNgYR55`)Ne7M12{amzImQlgTRQ8*LXvz@&Yz z=j~oZkvS;YwJ>IpxNe*rD4CF&n#`1MYjhS|<`g#KB@NG0< zlz=~EV-r)+_*dVLb$Nb~o-s{#2w$mDivT(|4frVNVquO8>od-iVS9L6&p+?I^61Gc zpKml{!tosE1h3B#CDkN}TK?wEs|`CWErmICq_*Wez}Q@P7(S9R-Smf=7b`c#yGdgxk-wviDMu>UPYaQm3DeR`d>MYc2J5no*QLyXwAEZ0CZCE#_e=D>*JTdo#-Zffq@V&GhvE#r` za?&btN5=^IE7r1i5BFQ6oRx>x`WaGv8DkF|5)JEA7e^y=c4F_vwN2G@dX<8*5KbHD0LbzpwU5S{V1S{QC!S74i+b64q|8V_h6OGsC>SS-*rcIX+`D-SjFG=&^M#0la3}aQ5xF zT=V^jX8#wxmWE?}Y=X6dP;LiB0f71?>%6V=WA#z{r*W^t?>$uv)Ky7Mci5#Hx5Iqa z9Xpfh2?4S^mtPYPo!(1NGe#qEUwMBjpG%8y~Du=g{yBz0(v(EU$MLK@U4lUi7}gz zYsbrWv(EbW%{hPZDV{pDbdBk80EZBGl+MU6X;g4km*1R03$awmIdCUCXZMi{F`Xc)CWXhLbJXZ<%n6S7GamFb+@ z7OS=E!*@DlS9I@0PaKnJ-sUV-(FM@z(;L4MNl=s)JWt|RK9;Nv@3!)e2nF55xvd~U z>UDtN3JNSWJD%%XVy?~3c*iAXHcrwuNmNN`>Hfp3)4OkRpS@|-N$lz&WoV*^P@iBp zl(u$Cqrobfl408T&-l7tB4}V&F_>9mZ~7Hk?{|iD!zviCq*s33zK;Go#$GnJK&pzt znFP2!b%OQ0q6f986N@;h5ByWS#$lQS!W^Yr~wyIWdt@-VSelR7z%K~bB;kU2hx zlvof5P8fk`Uc;hPJP}`AvphW^XP$$ijYgvDu&vhidBRfntOEU>1dexnPRyT&^_Hi! z5_IsD(W}u`8PB^%K2AM+JfCOy_BzcJugY5|=v7X>UT)D|UrY3TwbhjFQ3pjHfr&CT zc#LNU{iz*NN)Qjvu|7YT0sQy4MHK27=hZF@QwwuNw1`T`r<0s8;dyh1!)O051T8Jl z&0T_?#vf;;^Pi4Gr|Cr|;>CpqV?5}fTE`7#KkS7;kf}Koz(G)7+jf+Q2A&A`#g2)h z_N(`iemx2h`u5T~KR@|#J1~JH*!Mi#;Cx+1TEP5z+P-n*#AK&OCarl7n!=ABUc9tN zbox=RK!LtLE6V&Dp<7RL?O#&#og`-Gn_;h{9*a2|FZb2E%0B)J()hfkxy(v}T$&6! zrv6*Q^xPLOOvHDt^~S=0Q)ly37Y+PCQas*(!ac>><BT$T&eL?&#M z4F?|d!Tf@XHr2`=VQGtE0YlZcya@EJ>!$WZ7saJ6Vu@VIgkUqH%`zsZj3%YoQqZG+mVRam!~R4Cwxg*` zE_I?vDv6@DJU632{J(BC)$i|rcqf`>YPjRe0{IuPir6xKG#|CAy~hpQ6%>h8?uEhv zJXd4*;-enfOs2H;B}(U;1B_W!)&Cl@z-l^7JwoVE&&w!*nbES9r{Ti}^gTONzf;P0_WO#8fs&1Nv-^0XSC&K+apD{s8{0l4|W6xtiCr zM&0>+>5WBkf0r-c9HKYT2tPfFvDftt0t`O(N2p$Z`q?tuq|*;1rOVV&Q!-=??x%Dp zmNJ>Vv1M@a^&tp+_FDieIZoey>S!vnExNcCV|DSFQEB-2I=kwd;6c>L+U~gj++AHI zRo2FfeW#+sNlCcBe9qS>U*vGgvsxp%R@395UCpDZ(cUcd0i@K9GWgVzQ#gaP*;^Tn zojUfPp*YPT-ZfrbYgy8 zUZr#@gFVJFl|f5KiHAc^v%?$#MKBl@4k=ddqll+L#1(aLE}aZ9BXlfnqQI$7=f8oj zz_G;bKxw#hl6G0wP8Dw|=2zZkmyP1{#Ps;U^`o+uo{Xy;UovHkT<_L%2Q$XQ-dnfg z&398GaEzkIAn_3L_m&Yg=176Uk6!$DV1=90{SFquc)d24PUuax@9K@1J7BH>JMN&{ zo5HIScK{e!VZSQ9HbRC#>D5<|Z{s|ADlIQ}8be+dPY%?!qtB$PSCo{)+sZlbzZl%? zt#qqmU2YPmQq!wmO5%|1OouQ>Yp2Ue{p(=8pKGd2yZy6bd}^t_2Pbyg_w44;=c=$9 z*}L(r+IsM%8{K%q7BhpN{EJ&Js729T_p?8HDBDs4E`SWDa^ohcSg9unkh#hXTiV8t zSDRS61eX#g^`%v1V~pq>CS-Wfu`mT^qlgm!>M1<9#DN3t7F3o`fuSQR9hL0u_UMQd zDp8*=szk=O-g8Cv)Vit8D7F6U77QC6R6Mze8*bjb+Yh{eCC+FRoxTh&(j`^emtQMP zT`dx;77}xI!3dl9{Z~V&kvJ}wmUPR((cNUBtVlFEA2ht%#Ij!KCB6 ze`@Eq(ZeD(S($+57SDlcCq}Wo@Fyq}4#ZyJ!56TM5By(zMRo|`Lb-BzX`(Ys zYMH{$O%8ZT&uixofTOG!pO-!!FY<4|#>ybJmeiImWPTL<&uy}!HW9UcYOO|03Ga^= ztokK3#9x!k?89%Brn2{wk8b749eqDo%j5L*sPYZU_)tBm0VAQ2gd3N!;7893Wo*5| zlJJoCRC#~p2n;5X`kua(!!%*R!nlxf5(S?ZRI{$(MnXx}wYcTgLJp)&BS7hLihGSh z>&3w`aX^7KJX4iIWfi%sPAcjRwJWf*dfk-v^;* zDn;Eu$R3f5S3Qw{West$uy@MStvVYE&F%V6h!H-h3-BB(d@tP;vr^`f*jz4qrm`lK zc1U{YoaA`I+n2!V-P4} zU;&yR&I&s|SBjBGarLr+`%vvDxZ$&|e#5pjUX@95NOCWi4It^Aex9LQCRDAosTegd z6}g0ZN_(tC>L#W{jn?RxH-41~+UY5*s|Bv5z8oB%9=_(@5q**6i1#}i_+AW?Vt{Z; zdzj1_l}PqYNeDPny4T=qd+q8#?HpI0wl878H<|3B0P#M%%54)`B~c^@k-J2DUzC7Mt@9`V zv^1f)=^2#T4+fo5pG%eIk>G&lZN7@RN{j#m82S3%FHQ7n@e&1$0pPW%63w=`G6+)h zjorM)34Ns+OXTZ(TYK(C#lxLQD!Q+6OR@)F!@CA2eLX$#QORHR@^xmbRYfPJ6*8^H zi*tuv4l$}@-l^&o`72=vhEg|BkgtWr07?mCrfxEB^XL<)Q}Z(2}GHA263O_4|kOZX@%dHy}2CZogbU z@qJvJYdBUD@&*NTxs~#NeQu&cCwP1|E`s1TeoN}LkFnCYtX6aLPO$yUby+TqvX)c0 zm7?q9RWP+}JK5N!O1RYkpKbK3XxF?bWlY z8yjg^QYz$>wBTQe%*HYL)?On@#wrxm=e3I;=lSPEai?<`A`=HTk~#`h>@_mKyRr3~ z&+z^wu-`|^?7)is(?9%;j}xyhuzvM*vcrX2Zz##d=Smf#-{->f0ynEuOR<7LCeBS6 zdvBu_GqhVsO-D|gS?uc(ELYudkP`uD0Ww+TmWnx=<|tKswNBQkBR9M<6&-((+_rEB zHZ_7qV?|775htauJ^<#9)3^*U%y0LJC}$z9tW%-GloJD~Oa4nxKyLAPqL)@c1~$y# z#wTS7@A+7l5VqQk8;uJ#a`5+3R%BuaP7hwb(LP%n=4=&irm3P<-unsbPbyz@ERd6C?h zm3JMMJ$N^_ptXaSG8)`36qES{5&ZElvcJJ)S4n^KaWu^7*QmCogD#nw?UEV)f z9%mZ)Y3NasqTs7+EKkC}A2evHt4R>4fo-U#{@FD=V41F6yIns&n4+l7ZZZ}|yOLPO zu>H}ue+$n@(HQ!|s9G*a;0kCMYT^R>!*9TX>l7{LQC7F1A%j0|Z}Tml1Kro}o_=SK zhN;wFQiD3~DLOp-taj9dWwvBfRIV{vQO1`!v1-&s8^MF831=IVpU|yIy7Q8Vw`9e^ zSV+*pjEo^lL;PNIO&I=Zj&xKpqqCtT#dt(oMrc|cAr!vf*OzeMtS{ZWN z_2#IF@g2JXtHkmRCf+tAqCCjO=hG8fC34TYq65=HNezpNws2~5r^uUjLJ8pezIl3E zV}>7O?JZ;t+zTK-h?!tf)uq$GquzczM{==8v`M1}FQ^O} zs-D=Hi_+H)C$SO$noo1^z4<$r4!*ArH{9f! z@6#ti8y&P*xyN1tb9h?Mq9}mR!$5bU6IvXqmK9`RQP9!OGh@D2B;R}7-;>RH5GJ#r zvQ=L)dO1QlF#caXc(=%t2y88yTn1{G&20J88%_|Ctv1@{>oLB!r~T#4*)5X8 z`uyQrN5v@kdN={&bPhL^NEV1tfX41d^fr5kWn^6)5o2#7<=gv#=aR$~AG|0?$C_~= zQ$M!iTSI59(ccH7b6r8=0kaz-DxDhyD>|?l|Vr`ML6LD^l|wW?AfzmY(5Ro z(Bkr05GFfi9JFNJ)t@`K)t_%i(HjvP|DOdgXhZ1wB~rceI}aKp!-j?8!;igxRnPt5 ziG7kA2=~5T+H@b*$D;wxx7j$=oFW;&-x(7m8n1>kj6-F)Rg_k2V2wE8?H!EGwp5O> zUdwMk@v>R@F&0-)s$Vn8G@|l%Bi4Et{x|@!t=SIl@QH-9z<}w{Ng3YP>G}jSm|FXz zO)YIzb>5ux$>%oA7J*u-2HMoR2^Mc3|VdL7rafT=%X8a{CGpiioW=MMu!!O-FH zdTlr4c3AmW6FxQF!U}b>Wgd(Bqm^`v6v@B#-YjSEY0u#3FO}}HiL1hGZ^nT_G>eKp zmWC#nDXdv?(kAG>9uvk{;wu{+_nYXiKEv5x_7pX`+y;&Nc-K9B??lvO=kLp-h+8a6 zp(z8S-sr&WVX54*!?iOHCz+j(h1Q2Zvx_^^gc4%`xjR`&1(O9E{c&&P0per^g_;h1 z{@kmsRy|zyb%eD1{TLffb*ffN?RkWJ-O zbqxFSz0&1>ULaLE*c#2oNS(Ei7JnYb%Ya~#h(-@k5_U3n?SFr*@BY1y`x#CL%B(3% zM{BfGL#>2*`l3bd>i1_EW;&0fF`whHCx4SPIWckKZRN*;H8C>u-{`b{n+Ha?{v8TH|2nM!8eQ+;LDRtP(P6S z<3@!89;ENF+29VizXQGsN#JXKyTpRZcDX*!FZ28L6K*Znx7;;s2z6{u|LDi}D|r6< zn}VZvZ$=V=x3Z9L*QO52CqwF)OjqIQ)7t*i{ZaGg%SF5&KK^bzpO=5nffb=9lMM|m zCJmXTnJc~j^9rHMk*OFPey@PXC&&{X?{5L$Z+}NuD#X_}wP;j7f0FyRubE4#aTVo2 z178=$-S2wJirx)qmY2^)Z(Ulz!QGpu&8|}4)8X!aU@xJc0nvHI*glXEtOr9E+avtA z%?Dn8>ffAdFdde}*!RFH$`q2{7f;`FGo_VvBa6!<_`R%kV#M01gDKQwuzPJeQPSY& z!Bg+Yc_*cnl^q#h@omwietkS2FiZI%;1wjm_pHOs!_$bKAt85m)F^Q)5#h7m?)Rdj z@BM(WrT-H$IDowWmWwo$90)ZZ@qEAX2q$`S*^Kf6>AZjMA4t2+fgik~rQTNWn?8qQ z-(#s=qhu2tnfGujKKq*jr}God0QBQ@X7@7ZjPzX@vg9!^eudo!59Rf}qVHwhZYm0m ze&()c@xKlNuk3TZZxml-tJhaovIOf*N?J0YAbo#h^Be3=ze=849XY4ZT~d9X%M~2I zlA7w}GCAXt4zejhk@phme-v|UvHEY%`U||$)dn~0?&lFrhmODNO zmIpT}BiPvg*D%9umO5(;#lX3ul^q<)dNP+zeT{LuUw!6O+<&tP)`g*`M^o0*>`cVkX zMa=9Qul_#t`6%R>=pbOJrvBG-Uh)8}RZPtJzw;*1HJ|Rm0I!CSxH)$kFIrjn(FvuD1p32wGScXq$MFD5meOVI}?@WLmgm6a1Qrho9F`Q>AV^F@rE3MKhKYcmqB z)Tya!PxpTwQojB@?dQ6>h7UW)MR%?J0s{3c4u3%9^Z3Lx8luy8JfiKo-HfIuMvXa` z%Nhc@f7Y0uq}&xRQa(FqPi02EyqO{Gb`$TnT7!)w2=D4O{=s%ZG2zOPw_mv26n{ zUnIgl2a`o`bShVEZc_dn!Clya0%+Ql*xZ30Ew~Ov*C?QjVXm(!xxeS_Pry6VYQ{|Q zv%^88g}xB1Oi$w}6VDUD@04V@!1a)IQ_<=b)U&JMot?nq-rzVycRV3=ZQXG!fd^=V zkEc0ENx-O|eIv)+(D$ovPauuR;mX=G9)F=wF$$3Mxw^(*yOQVTy<;c%S*JDmPwEiz zA6~xKKmA$Vn!(ElmEGk@cfTi{7F>iAUQ!5im7M#M14)@*9=;uX`ZXLDIT3S2^(+aW#r^@oS?TT}jD7YdR|!xK@`Kv2DC=`2x1JVqSNt2VB}%%gKuA^;DS?7WWg=|JY$`6F7tS{rX}P#?_2qD%cJlvMlYO z4(^RR5BxLMgUG1G1L3~=PKCdzx1Tj*9}wi+m*Szok7teF8SDR^BZP(+QeDw4syabk zU*{f8Jx_2GJtU;|J=Ea8%k-!BkQF5)y@rjR!QEaD|8&&kOw zJ)9%$&LR2VL6K>lh`x#el>x&EWn(!OgGu=^8|;NdU$gQxZj^RUZo*Z_UPANE@4z`P zm&X}{!-pk>S~si>H=`A^OhV7ya=6R^T>av=(24u^p;<=NHM(QB>4-C&y@woB9a z94qsvvC-1ov21pZ$M#N(J-Ig`{;9McseOHVdEVwEVcu@oM24JS9*l}xknao@&?66> zSW+TKT-$^~n18*xwcZfaBntqaS5bjn4szC(jza zJ}R@npl;=|dbKo> zIO{WdSg#C9w1|7Xma22y|4z}^Nt88(tMOmDyG^cHq@(CQ-p@p?-c1AQx(<;+ zuQO`%^sw9D?bojSU#8eyau*9lZCy!`=A?S|#+sB77Yi~nCD1B2oJG^R8Lfxc)c)wA zaUl2g?euS%hqv1m3&bCw1#EqHJGN1l4^Y8^!ktd``#cf}esAgB6@1;e@ zMSd;!Gat#k+C96VkRs@K7irNd|9cXc+tSSqxe^X|-fawP9KrN^n5G57&D6IOD<~M! z7dA7Uhkwj`jsoStm#@^DzzZe;k8iv^-d!YlmT*F%6}UdtB%cyTb z#gzOpG=VpbJTD`j?x+4}vZ;_kBkkI_j=pQSFgCtRb-IH_q}}igBD^YEY*JEi;y%CQ zrcjrciJ$!gw|Ty)E?Cv1x5aSzV^K3kV&xFkv`(ANtgNqRP#le(pRoG=?~1lpaY4sl zsdN03$^JW&JEYPV&DBHru|eQ}yMPMe#@e3&`mJu;y-o;7+b%p-R&QrJr7PBdD~FR^ znnF+vyu+H@>vY+|4Sb$ud=8=fj~7#?PzK2*fxLh0jNNBVE{<*2BO)fFrnvW5qtbQz z*q1pR&f6XD!>Wc;3(veI5&Dyg&TV;HU*+6fm@qOT>~tP~I@GOS#(8oQBT={4gsybo zgP7mv^i)oFg=hf;cXyJP!M0|r2Z2rcZs=yUN3_;@q>NBV&>f1x#yBU6+9!`u4JTE& zQt^VQ3Uwq#*9<>b*dIN7^!uJ($`e$n|8ds} ziih2Q2)taJdS2Ip_59ti2MxUOtp&3X2;yBh#R5N>$(r5$n!$ATUSCC>Lvzx!lZ_Q8 z!%I7`9Wr&=ywIUypxbkw>l2<)Gn;<%@w)&%xLMRd!D^Nn98?ch|LVMXYNsxm%%_|J zS_UiMv3Z|CVj=^RRZm)^*`95>rEQ{RoAiPq2+m(GGwU8j4a($9`UD5aXwQG+16Oq8 zv#5qW0dq(k-7(F2o(!(WVdzpAZQO%`*uB6rBk`mN+)7FM1xpRe1i?=ZJH zs>4x-(|Fr?`lQz5az)2oTQ;Yy>RzKadJ{aR)$a2MaP47O8)28!(7j-Tj!r#i-*c;s@s?>Cw?KeCIW&wKK4%5g5gF;=>S!_0Vxr4{7 ztnG?NtjkMh;#PMj?jf3!NR-1(K461@5V%(cP*0-(9W($Wzzg*^m+b)1!$lRw2*HAa z1w8#+KPARQ+-og9tH`f5{8P%*X=m)Df8fu?bx?6AAv58+jI)}VaNtn?&>1e%Nf#3% z@e*l&Scuh9p@i@Fv<78LWc8-+N!)M@B62*noANlz3k4$fAwU@?*v-({M-ET!Yx7rR z?t8qlYiS;4c5oU8576P5N)0BIS;#7ZkcVPQM?c^I#T!>v$yC!Ci$q{gzmWrIn%Dyc zD&_AKCDtQw69+$dqv*_|?jNXV=}+R=Wu#<&^dtpQQ$~*oyfV4(wj~9R%`PsQ1C=)g zoip;`n`rK}^3~+4DRTOCD9sDwKw-sNhZl7wPOpSl^{Y~B7=cxhS?P$+dp`eEqYAJ> z(=`|>{R83AEwo^PCR{!27Z_LOxv7O2OJ_|8P}SIMILpRDigE&XDr+LE#GiSNBa3gq zeeiCTM;%`O@majpYDDfp$SWVcBCnE-P~8j6Fi~J9B8nu4!T7#6F2sCJiPuuvmX;06#to}B z?lbsb`psiyDyGaTISyqVMyb<&?S7BSX^eSOI#6*y*^PAdjF3$>zCl6qd9u0F zNlwgMHKtUOlnhw2RzZ#ElyCNGquYq_Q_lm#jGel64dTYe73U@oboCQ^EK!2VG{tI$ zT;9U?TBF!j-y0?@9Hc&j;qM%)p073>6E{q>QN)=r5#+T7a~uhUv}Wh?9-(dHljX>d zm)*XBFH*|Ns><@#75VJ#z?FsBC~}vb)uVj6->KEoq8iVZ^OuGTy4Mv{apjICBFIFH z8f1(brf=w$&0&=eNtW(YPT<+yBBR?NuB|M<(JF?01JJ{>|AaLMJCp;RN|9k<*6>&m zDLc0RA-i9|3Y$cWn!pKWu<;$8(u5RHOOTP0Vi0ExBJeZTwmqqqPN6Gz{6;|>ssqzg zI=uL9e%`rr(tU1y>15q()VwMJ0~ZP~M59(NsbHwas@7~f!qxdBlZZbyJLM92{c@a~ z-Z3nHfA502dDo2ZKGtNqo<^rNlSD3~jwKbD3r;JzeBC=Y{rSlpoy(&GHDDZAc;dtV z;V5;*a5B5q=>oKL-m|Z#PG;0)3)qf-8+u@!)}ZTpN<5vqoB2_^k*46d%9HncTv90w z_@R29x|+DV?xbawcq=f2HFXDNyhBJTJ?|hcg5}EtSD&RuU}h0C=zO~gKCTH>&CDT9M}*tM%(xv%P4hplw|YQ~LJjwpggn_JaY zd<`=Cn4s(j2XtJI(%vl~?dU&uKNFz-ZR~%=0~Z>2<>A;f_}-sW6Clhk$jD04;hvw` z*TtvB3NnJ}eu9AzjxaoZ+E}&S6^au5-EVs-PEh^kq1T$OyjOYZB8F=It{#-ey^pO= zI1;JioUKO>o~~!9e|P;4iu{U;$Uq|+qr*|+6XbLnePlRfYZme6@6gTc&Dl>0a9MA- zIdZ7qadsP{@s246e^Jc5ye3{LI`n3I9X&o#cR0!N9rBiAFR5LZX4r)Uec#0A5A3*ttQf z7oM#d=5Ncy#Xy@nVr{MFAAl$rq_hzg00Da*#Dl=G6;%|D$2<``v{%%5mIjPPF0R?) zb43~h*3$;oiYsi4)2jAHtBW?&@r_ z##CxTz_Uprt%i;{S?PJ`KA*P!QGfO~4L}a}g~09p`q#x=ePnKe3vfc*4?slYm%rUx z$Ib#a+RjqZbw+Uv*l%IJGfW@7MRZnuidT1npdqKx_~!0l8}3&qfJ$=|_rhT%UdI8_ zV%8BM@xaB`NUgR@jOId-n1^g&@*%o@eUWke*zw`*-*M|Ru<$9qdRxo^QxeHi40b~X zI6Q9IMk6pG;_%S`kdnoLOsObE#cSVlXVe`3I;#Yp4(tALFj!2 zx-9VHKVok|P)qo;OX|!XonvJV*iJm^{IQ;? zP)t}i5LJ0VlfcqkNrE0;CT&a#%pZXosf&muiq1{Az6}9|IpyHmoGMY>( z=^Wng*LSfa_tgvGZC~d(xyn^ZQ&OUzdMcpib_6clL)QU*+?0BFkWU)GiT`Hf9i*1O zCRwRwar~8`%HNy>Ca4)wjLLel>@ScSK$fg?Xyv?kw-%yF26g3DP^`Dg~Bv3Z0RmJdRNh(UyX@_|74=Fvk9fOw9wJovZnpEd@0tlE4AQ-@AC`g%r zfvjwVs!kyJ+vz^oYF3##y;zQPE5mTH37Z+T=gfQ<`8Fpq-%bQA4sZjQvD3)d;(E~>{yBE>sOwtmFQQieasufUG8kx9SV8w{j?`kR z#e=m=YhxZ(oTx|~v%iFAt6$xe<=6+c*)|tWb4Gv4H3`>jQ)LVfVc3on#CzQ}Bh}y;3}eR-+`-hqiCmNrco`mOsT;J)Xf#SoJT$#e z1%V0^B?_961E}E`IE3Wpft~B5a1+Z!PLUFN^&^fLJ%-Kl(5+LfC_ybZloT>^AjD*y z|06xWK|%|G?*`h90Lg4wP{;%=2nP8JG+sv@r9_osN~+9Kt1^2+HVUrK7SYnmYPJ!^ z`0-vk^3G#*X_iR_pg!q6UXr>xOMx7KH)f=!fK_Jk`7-~$+gNamT>47At!a=yQiW$1 zv*qYD+D`?_G`Q^G*4};DXOJ2Nr>Z;9gvOSwb_zRCpxU6Zls&EPW{YoA;K-L;^*S+;I&;E zZdokv;->AlaPDe*o7Of5rmOr}gKZ5^16Z5C>aHn!Ieu7T}Q?Pz4v<|bDa zUgBt|Me3-e4_fm+?sQIBX394JATN0pmmV<)lV`8NrD5~PvuDM6D**BY>VGdoL&h=7 zw4ssGDH13>;-mMpIg!p^mSi=-8BeMPv%b>f)EX^@dRhpg3^5I%QGIv@$lmSi$pf!H{S~)aIgc0y&#vx&dlMPan)XK}Q7dkfLn+Y^W3Z|rfH8THhTd-f{XsQ1A=AG$o zd*yXBm+mZldvBp-nU$rf@7|bb`Zpn|N<&i$1M=2IOC1&{nG4^`j-dFhRJGGm*~;bQ zrF&Q8+|3F9lSWbO4c1(tia}Z5T#xKxd4uISNj~JzjBcMg%J^SZ~ zO>i{7&us0Bzy=ipxZywqK0hRm5SaZH)uEcK1_O8<5W=YkjrNwYLucgo+(51gfW}?* zpR=B|X04zCmXLx*qnM<{@$#Vus${7tqd75@s&`dH5-*bC38=Mm!-&xQ0RWE!k%QK- z6?Lr!95b4?oL$ljj1C@jJ^%#2usm9Xi9}%-48+i~_3gA~gK~422wAA24qz%1;E6wj zwcb>{m^AN!Iue>T5>s~F=M+Mh@d36hs>ug-tgLL-cw}dw0ae2R*OZAz;QL0t<-C1- zW@(fA?K)xlw|Xp(UKSPx63XkMJzMEnE$gF{<-%L?c69n2_sDhKJ2T0VuZ+XIsl~$= z21IxEEkBagEZdG->Srv|m%luMU5aRHPy5+o4f0+&5sv_LDwe-jgo&RUU4WxKPB6dPgATHZ`(EqJK$ocZ~Whn zkvx=$b}!1CT^b<@vt^fx^?o(zSNUHAL$36EMIse#uo*>+$+997a3~uPpbri1$z0h} z_gr8BCdi8*Db=bu{ZhPHHx}=Ihi!ZZ&i^ly@vtdZXJKhSaOoUS$qFY^#tI!W=wUWT zJdDZ`?6Qr4RbUVdnm~VB+X9z0LF4Bb*G$x_sMn|8%NGQIp6*-_p|;iPH@p#RhRFJu zP@Y2GYu0Qy?$P#maD*QTO&HnYO>GhlY=kkJzrFcW$BUh>x{Q>^0ji+$@Lo)$i~+K? zs`o`e1Hx~B|F~N6IaE9IUUDss%pSJ+7PAzCp9*Qx@TT_r%8MP=< z#8n4m$8;_$q6GAG{nK151XV#sOzYNeDY3s}i8K%g^PlZ|Ka7o;Je9RmUD#of#( ztV-HQG`s(LfU;y}8!{ykGjYdk_N#*Jt7?f@RMxMC&`P!L?y8jtg0a20*h5y3tXkaX z>d=Al>N@ea)x(#56k;=<9@#-3j><*BD`OUY{5L3b#?*xW{p;I> z5N68cih?u7#NcXzParm1rfI*h1)NZKwul4|)a)9MHp>6bJZ$CDClL@MMtuMi^ha0< z`x0iHAtoKS3Ux0@DRcsALC%Y)IwgB^Ul|R0(xzNRAo)O7-zdzQ8bGZ^OY}p`IctXE zV^hEfFJ9mQ)$j48d31%4@Bgy^e_ursDxUnLp@q6PL$m8U(Qo@6aW$tmu&cQs_Nvr^ zGqU(1A8l4Z$ZCFf>Yc(2ye9SOT;?rRC$(z-Xh|VAZ$dxFX(um;c5c(u&6TV(6Bl(Dip!cHd{vE9O~ z!IiG63|z#e3*Ou}dC}i$^8%6hyGB`khlyF;$%2QQSCC1ugVCJ4Mo;7tG8~7gA!)Ax zjq{2Z^3BxMi&q{cP8vFlJcQ&T)=v|i{VJStB+%I-EBhvbUQS5{^bS02*pd6R zApe&z%+B8sTe_o#kTm_AuXKufXd4f<;*sPjs+v;tH691!5qCUxO*vhO=hQvr$GZv2Igy_XWvj*#kt}ZD zv%S+rhXDnN6(L9j` z{L^T_LXfDm2CG1Y)L_4PS+`JXmCIHQ!<_2%l$Q_vr%v_Vs%=WXD?ETI@S5|XOBqIV zRU@v!^SeVX?^Y2u2M^8ZhQegsQZRonqK9koP^FpG014N+CiVC9Q++MFPMn)uAV#pM3f5 z)RRdkFz3i@=&JuwO^aj4e(!a1`bHQY_*Lf&Dm?F||L>3c%*lo{ejECqN)ZJ{X|rbA zQiMl=WJ73?c6qnLAz46#O!T)wN);$!R_R8j@v_UTdXcBCDH!`zTWD$p2PkXIbN;pv zjlGYod?i+j@aS#8;eEOUrybTCnRaTRho*FRUr9`r49@{uQH8gE5* z5@=EMz$FW+d(VPuu(Kd!&1%eE9(+c#&N)>jWsN*!`y+iQqJN>HyhsTx;4Lr5RBNz6UPm)kGa8Z7 z3`hKR7{!vLD~THpfI^P0<_g$zTltm^xwEW3GHORh2G{l>0QoPbnM;MVhDTtVt8e(F z^z%1z#`f_$xMcZC>B@F4p82Qs#CTWXXi|DrWA)^TXjX4LKKO4(GkS6NvBCIQ!~83WG{wp3b@GcZ4b; zR0|_-*n)G=hHgu%_pmGTLy;|_SE8c{CMAACv~s>Uio!fPwqe zdf{JIPvgs>k=4O`Ds~G_)NEqMyy8WOPEH$ui653srrj6a%Gy#x*QR#uR;@UHP11DoHwMMrN7g zT3}w?#uzTJDRX#-y@v$&v6`6m2NM!AEYS!N3Q@WslKo|D=+6myGoxeHRvm&*$Io`7+?$Ubi z%``*~fP_Co$7FTfF-LQ|#e(I>7zi9f-`2Y~#Rd$bRKCn>Gc@psdU--OR5p}`C@CLj zmoYAql?#DTL0^pIPF4DYDvF(@p$4EMkG#?R=q1t#?lJ#e7Q*xEAXFoYOytDs&K~_< zRV;`HpVnV6ijoWiM1|2?2z7-gC#0&;G ztG));hFgNuHky~mAv;m%uK4yOt7?~Fj4H+##$CFZ;QY+AiF|!xL z_cfA*63urR0c2oOK@}&Y?wr*bb3#6&)Z`O!nnby+)hPA#w6Eha`Yt6YJ zoF?L#}#DVa%4MJ1fGl@gOkQl9hbEZSd$HJ_2%xVhbG7-&{!))lf(Ab#O zV2G_(k>!>GBke`2DAO!VX{#v_iIeWStm=bt8*bgH zHaVbRkpE)Y!FZiL_l`O=Gr(0aUQrYjJ+|cVN+Po~jVCaQ&>$1GTTP_UrNHl}=d^#J z=MY6$7fmULo*ApC@!7rg3rM^3$dTg(PqNkv9b?dz-u{7QqeeiSCq1Z%QUU|XFdV1o zO}Py(mgVZB09EwdrmM$SdkL562DNe4_S{~PPn!u}yiAWW`-2HbEhATkx~KMvelN!U z?x~aJhC74$wj%u|CgiC=r{tM2L}O-xhB$$`~s=bT+tu zrw)UvPLIO?tA%c`BaH`>5K|n_E(laK859*o0p^X)Tq&MrvTJoKM5>Yi+qr|geY_HE-xvWv%$shvGLoyj#M z_h*i+Mq+ct=vN|oq%0eeHK*^xDrP`6;Ua&l(*~}PeDB9beK#Zi7rPB;1#~VJbD<`P z(FyH4F>c@1wU?JX0ZO_!^KD_6sso}aF_5U5VY)Uxjj`x#&jqQIXp%&~NAa%^X@xwy zwL)W8ioQo=Tl;jL`jYkld_m;ZI&5S~RjTpanjMp7Vkw=3mxL}kQh)8kz74cq!bb&f zbrB=PQ`%~AH2W|{k6P}xuC7Egy{55B#!pZ3j4ZRhGs!Afe9~~+5L^sZ8ns$FF?X@n zlIBK`1JITx%~Pf-Qx+ee?>XJHMfIr?9Q>mC@+R%_9$ZV&&(04};*@34Cp$ic3Ytys zPQS;Qqbz@YxunTLu64a$k&Z&XLHqb=Er?P(o>c@yyJxwotQ!psNC&UeIn<0lq;LF0 zrC(c-Ov)K$fOd|o*9^xd6Q%eI4cH<3wqwC5*~!NL-+=`^4)NMz?)`OA5}Q=hL1u$3 zxgu68$}?=6<-!*olS+OTGW919E(Jl5me-OM%x?o zc$E@ma73tC8e~LG0Z=?%GKUXwG;|9JF(5vk0S*iVKE6m5H@UPxhAsyNgpK}lB{^c6 zz0wS&>;9@#s32|R6ztGS@IA*P(4nD9%2KLM=L;gx&^BH25nc-;NhV$o-)QV5%+VwX za~G?J4F^FgEB4ARceV?_6^mB8wd$aBQ2_(Up>Da9fNZ)}DLYTGdXDu!!57S!8c?mv z{{4%)ay~9M1{@#7DmE`rYC%;1L%DuoQ1&0J`o}Li+LKf1#mrSCY8E}{OFO*ckX$te z-7PAXZVy3+v`_8MqyBphf8as{c#dX&T$M8#T5YHMZT@PGcKy`+M)5v-vYQ z*?Z^CeDlpWGo38^TH*}_ln*KnI54sF&EZ=-MRFc1^kfN%^G+CZm;{U2K2gq^^dg#E zTlC5OBz%ndZAo+cREgkf3SztV|DKNd(dpJ@D#8SACZ_RcG{k#mffEZ>3|Od|#&)Ii zTs6J^BY%L|#Kcpggr?3==hwu3I@SsdWao=|oypilt$Fg_q93NRr*gc0s;Y`?Z0usQ<`trl{4aB!5t5}{A>UV2{_yH^NRXJc3 z?Ps&42QgwYD5+r-Fg>sSo@|QW9pf}pV#>u54 zx0~u)SWqAERDibkBjr@d0gk1U+^L8WcbtE?@FnK+07 znA89s&6fc4Wq}UdN+{}Nt>^#GB5#p)(fw5RQ(kaUDPOCB*bR7PaLGv-d};k&Iv&rUf(uYXqrsi|)_vH8Z^(x^+j zF`L*6MahE}MWYu84VNy7Vls^hfuWl87k5uI2VOs}d0M@>u??34zMk0!B8RdFu~L!Y zrh+dR{Jk{<|6`FMqM$3bhSN~}(b*uVc#QzdP*^ruIg>QdCxihOjbk#viltJGa_1%} zf54rr|3E`2WV-(C!soXsvy?^8J9`sZ|1(ZT1kYlJ6XCmII_wE-mF8rY1hwbSlBt4) zG?)pIrUFwC`e!SGTxY6-%55?1lw~dGkO3xxQ>f`h`(2oqFLXk?$-d3M4z<)lbDZUAS0Axdj7j=mfFw%J%3y+_NDLL zpP_zE@&lGX%cP>p6#tB7t0>z?I%NSGast{QSbOU-4S5mpwX$?X~+HI0_M;-}ywkDrEXg zsyxH}X9x7vNiF@9rgVO}mz%vpUNwMf;DkHum7Gpx+0y5qB^YXCA!Pi#*3ZevCL!ar zWFv>gEEp=Y-ZdFuB<0!4Lejfx%@~7tiGz(tLx#3L&^%L8r@&HO~WFP%74}{24HnmQqC$AE-`)6v& zy`Hl`9F|eA`G7PW!J)*u!3bzNaIEfK$5%8b%u<+*W=fABj)p5BeJJsZlK`2o)>Y~Z zhTF6E5`rCU=>aK-{}S5n?tEiQndqf!QQDnf}1%5K}Il*UMqQeyHor*Njl}Fu5j4eS%74lPLmx-a<2pcIvKQ5?ACBshf za8_ts4g9<*yO&osXNJ)~K7$;IDF}4mSLf6})>?6MCsjzgRX)4gi$x(hq2u(3m}l^G zi^8gfWtR@0MbMrh8c0gh`p`+U8XVr_!47naVZNX!Lk3PzBeu1{@@B~UU(v#uVvvK) z9sIpVgGB&fr*1T3q%L0h8&*voa4Z5Wr7JLl%^N3I2aX|?A)|qLZ~rWTxKK}cVd;JJ0clfC>pepNtM1npG0OV4W!2pewgAH=a1k<0vqh;Fcu`#IqczHDSXi?PA ztyO*CmR&uCvf})WVc>{Hf?NSDZp^$dEN;fbi=7GkWD%VkZ*yiQiM-wS6K4N^CQttV zjxMv4dT(FIUyiqKPD23(GO9c}Q5m~#!`~B8!3f7D<@NXHjE1QXhia61gr)jiRSo&# zO;=TTGY%TSU9}mMznn(7dz=P@ENRPkRQn_&8RCh9XJRwk*4i;?Y&jh(5d(lXaR2q; zyY-8H4+~>rGF2xJqz;GN=f7S0*+pFFTMul9UA?V`+{>0uWn@-TG*gE*7_u=M+Vwul zHt_Y#h3)6ZTkLm=Fl?MD<%F^r;fI4RNzzXr12g~vG{k*dvLkb~d`qfEpGh++$CO(} zX;3V2jofia-+r(aw_M%F@GC|*4uq&bW2RJHum=++1v-ZmxMq%stM&Cit_+a@ADb;; zy|YlJHnT>FzK-EyUA}C3zm-08e^;-!hlc$Z;>Fn}X4K@!w{ctG8k1e_ z4J)x@$NE}*ncXMlGF;L=Fw`l0T_iF4V@-%!^RxZgp6bm<7~7UijHEz{h|&tCruL0}*J=&-P!)8$>bZDF+xyC%j@XC{~gRgR5MS)zUlQFGFk1Ko@%g0Qt26! zHXEHF#2*{{*2+IvVsUl6(dT|Na(Hzr>qRO}Z!^@z1RQn;9Loc7V+XG?H#@)*oZfu|((mX*q9LK`h~RapYHV-2EG;@#+6Ls{9khYHMC+0#v)GxJ_HesR^O8VZnd zF=Ty>*Hdwh?Nj}ngc{ua^;F(5eTtgen>_Ekcea1N9DF@Ez0t#l*pJnvQlru)jlgPGb5pen_}V@s zEqeZ-H{Zw+JeS>NB#@|or~STj4{3JVhtVga1~l7^eym&}58zTGS6rb8=pQodjtm&# zh63A^739h)_xR(Uc60mEC-Wlq9!JEF%lV5y6?lxH-5+Ca)uo)Zdn5t%N!gR-I8+D& z;8RSWYKVyOmc~Gr9>AG2slKS-+(p^(df<=N+~C&Ih@GD~A6$_CM1SyOK@+fW534uw z_!mNP>uR$rx-&_E;a}lPn;)%V4Zs69kd* z>o=r(S^R`DWUp;{P}AlgU)hhK9)8wq-aTt9xX$kLQBoaVDWQ( zE^8O(*nOs`;kd2>9dF4hPSHLGzFSG0hbb)EirAT3!FOR&KM2f_jL5;I4B0m6xt-^1 zHeA4VUcGq%0h_NSQ+ds8s;WY?u|-j8<<j8pqayO=;;&n)+s7K+k(PK!!L0X!>Flf36TSl6>rWPG^lHh1$vHHTM>COVGLH& zh9p)eem7?SL*)StaH0PS{}4#Pwo=)my@4p2I;sQ60LNcaEstUeSc}lEhq;cCDzQk= z+ER2|gxIU^1KtMvA)582#iO?l7bJ+?oW3R=6ks#wxVrAjrrAoUuFF7 zT&AAjeMnKGOQq^`I@M2KDzSZHIc%kWwoY-`mB&WEK)ub*4sh3k$e{N`|z zwZd050~=hp^JdbxAk<_cghW^K;?-*YX(h-Q&cpcJ1M<5|DT^SbgDnNf`fI3yvB`xRv*D(CI=>)&H+T?iLue`+e-XbVS2&MUz&cuxp; zz=Nk3$`e)+Bi5#?49p>3yl?HaS8*aN!Q}RcG#RXT6lhtOX&a)Fu;r5^TcLr9&5c)^ zdbIf2Csyklj9H_|3De%hWymr9Upzo$NBO^F6p=*;SpTw@tPDT?Y}F$hYpqjSlRWT1 zxTHe85H(^lbBNqT2h~ytM;G@CAF?;9?S6M7EQjvh%ghR(spn4odu9FT_}0k1mV`0N zSSk&IL8Nq-kyT?^^TfbZ45E_vY;4(MEv^wHYym;We|;;P{^Py}2eA(amQ35Y$acr$ zyNl=a;(9>mxq__$S8xRrAITbdMx`TrY#;UD)=e18E=tcKim^3Sco}VL0Ka6dlQV%Q z@5;>FJebFJt;9PTDi<7RVH! zx^;2;*<1plb~O0hh|^bapJRmy1FBXIsiq=>-gXXG$uoykdMP!-H@hx`Y5|ACWS z%Ct|1xTc+{VI%@FL`X|PFpUTZb9;*_Cto&}097YU5j#@8qV59;;R6Zms@#biq&0DZ zJIuA|rLO_gpL-q?+Xd*Zwl>ud7Mf(FM~@?c=(WNie3}1^dj`0WKf#z6KXl%QFg80? zo4p1_YraOmtO1=AwlWTXAgf0`M>$aIJFoR@;(kmdsu8y4Jf?W7H}PiM#ddEa`?e~H zuTXWn8DDtpu?4spAXN+~MQiuyF}9EOtv~~gOV;9qbsSoW{@Y1Pg{F)^>_F1v6*Ebn zs-HVjAk6{^jyM|I2Ed{n2qb0z66Mq;%bt|4*j&ne9({s=<`ZR>({qBp<2U7dH(!`Yf1RyLfTjOoB zm0)q_6G=P7CmRh$E8E;VP38|I2`i`9Lmtv3MiQ_xE07cC>xvfTAGiV|Eb!cI+dkGY z3U=m@UdkmIz0CdoM0JVn+YEU4B+ z5c!_8Ye~Z^PY>!Yj0wxl!W4Ze4cSni*M}NRoHH&%H@xcK z-@}+zG@>jERNz=wAfX*OQF}|eZjrPYExdQ5asvxQBBfpHbSH2WQUAzH4+JkW;D|f< z+8I4@gk=loV}9Iz_y+of#nOvMOhlf$a;*q3Ez$Q=N96|_QG^P!L~DssO~&Ttbc6q- zi}!YoP&7i5-K_Vk10mtSqTgfGXV7^6jU)GIysgF(ycu{{wsDhLyj*btJ)&r`3ja;7 zefzH$QbETT-I+xnk1M`o#?p(oyQG%Go=rN_jFI5jd(Q7I`i@P%lGo{zK?&}l03%#M zLrhFze!RY*xOYPPI1;zclhog5NZ3E{VuLTc3m!~o`HG);Bw8XS@p=S3tcVAy2O0WQDm@U-v{o3e^*lR39SD#GK^M zH_4ILuhH)x{9_Ggo7_WpW2`0gM{1#-+-5Fj=Sw{Nm46aTt{0ccg7 z|7twXP1RXnZdDY-7)4Rov`GfoQ-dVEyb1Hur1*IDYI8g!au~qE$%aW9B=8y}>G%8C zapHeCCit1W!}sutzuN5mW$qATg#CSA_kmO+{tT(=ysv7}Ae2a#E58d>q1MKMxF>vV zaGNaf-QWp7q`>Kv?>nNO`@YL5AA6)6RS?PA1L}s4vk){)C=kG8c{gwyP(XdvAo|of zVc!R{;R|8^`x%{E_w>ig+h7lc?|t{2`%~kgNGm_F$2CgJJtIzjO-aS`8|5fv9N_X2 zqf4BH7di>gv60v5MYpDZvWkH9GrLklGH=p^$!0)DzBPS;h^jW_< z#0aW@^%jH|iKj>N2BP8ErKR{dA97(A;mU)k5JWmJ8H8MA#2vW8^5*%$wXCbJPY+)T zFeMcLnTs~Em-d*y`Sx4;u9Cj}t)~HcA;T{Ho(X<82!i~N9U48^(xnn=<3g zu~Y^P)zyQ^z-vQ|n6aD2Rbfg@oc?Q%yq1rd5+J}e49W2E1ZDS!?9`&%J6JZL2_yJY zhqAM9Vz$5jCmN;8<5)sI_iY415p$%gx$92G`wStsziLt6fZ{_&8iNzEXKo>~f_W9Z zE&fl~mC(mt#}-@wDIiYp$%Y3jtEQ^<_s4dL2*TT0lHa{S`^$n2dy*d@UP{MtJ%wvK zw)qWh9GjFH_VH?pr0gj}Sjym(1Wy2*n<)5mL99+{hk-XXT3$&ybP=C~X)fL=|I)5% zaeuM!em#HKuJ}0g>shA?LwvhVu-rnC;2`p1Qj97q1t^Vbd%nrY)Gf=6azgLjD5^#N zvWOlVuvAXT;5|8{r3b)q#$48>n|F=nR1aQgpsB+CkG?=SW@LDWK}cS2KkApR3g!gcUL|TL%FTUAxdr@YK(DZ;~gSe%{}p z;{+KoLUcJ1cc+9dk<(@OqFMv zVTv(80B1EpFBXnNuH|OFRPjEW$9ZwpQj0wYz-V*ZlmjnO7#1~{pV;r&SgQ)MIu+ad zz|^g$L-^}Tae~Odo5CKfBJ_3NbYSO2KC}$C z26}Cw7m#QT&u^6Fhq$K|BX6ihAQfUGwmghhEijtw_bMjUKjRh2d5%$Gc=D#$Y@sL- z3W(Ui?WKV`DU4RJ^Hs{?a?qXj(*2>&!D6_7j#+1lXBQJ3zJJafo$u88N(s=<>%zhs zssr6!mHkgag+BtN5-Eb=tuterII|n$OR*;?ZH}xj{%pF8*Zu8G(R8V_OgEUTR2R&4 z8BE4Z0-V~CaSsQ}*e!= zj4;C&Rvs7V1T9ExdPlGpF2A74Mfvb;=Pa}C>l-Ryt99|-8r~@*M?F0RJX7vVVqv1p z%eBc<2blM$XlUI)$^W^LPTQ7tV-02SHUB|Hpm^!fP#%g@U00TY{jM>E43H!NMOwC^ zu%P0SM@Gt!Hwf*|0gikg-0)M{(jbM{dCM(sWH5MTza38w*6J}ZS0{<1XZmbv<*%u& zwNwR36x~HEY1UhtBz=JlO@mBSfTYf29ndFI`=*D?`9+yekkNSR{gpg16YT52SD^8~ z$T$`9lbE+Mhe)j>lrWpJopBx&V5%Ce(43V{CLW$TV6g&jM;nojHp(gRc+Vh* z5xDR*9jOAnO!6BAp6JA1QYlPpSUU}bCU8aX$n@{+u(ejM5Mo)ZxA_8f+O)16w(YW3 zhPPZ19(uDvMAN**KzBJAK$si7GDCqtkxuRi>d-#RjZX}%$PO$C87r^_J-+rt=E6zt z-_9zr!^RH3oAFJpuEh(o;QSV)gzGeFIq;gpi&W~thy@&-spOX6<$msL(~%n33eRDx z{u{tUm!HY(cQ9Vo2GG75c0TP%c%1qD#D$)QA<||L9y~B(e z>GZHMLVg62$(B|Wa>^wL5CDxk^d$reIw;4-7A@P%d70X;L~$n@COt)mnNB0f7)))` zdK&eU&fT%j6GtXems06FTWBla@3IF#wnAy$Bc)D3Xpw0Tuyh3Ax-1x^PP^lhkicfm4%yWxWbX)d;GO)qSnXMId}O12Hgx+mlz|#y*Zh8aB8zs?=KA;9P=OEYL_9SlxU#_=h9bUA-aFEjO8P=cHG#vdDrWT`SGD00Ng}V|}hoLc}z~U>IX1Vhzpg$7n6afvx$D7ilg;NwOjaQ+>O!o zWAIk{#L2<>Bnw9T zwmk$tA`ln$3!U%aRN;qCpn*jLL#6#ZE%+Kkyf#~8P#6R%B(PH$ zcSeg4CQfM&!F21`7a6RFc$u)kSgUruePB1dtGowLl)vzxE1I0jf!GY5w9j0x!m0UY zR(7n0FN%}NF(V54cIikI5W>jeL81wm;;cy0iCf=!r~f+P99kkCMq~47vxtnO+E6E5 z>v=4Y3`TRQzMd!TS{y6^YnU|&F+N=lzv6rWmnC;cN^_Wyvxx(R$r>O2qzB(~R=a*? z1}-20Vd5}nTTRi6EhQ?CRgqHk1zE1!*&i&s16ZD52HjUub(}yr!%HU$>BW>mRNzUTc+XI-5anra;% zT2?Q2{XW`$gkI&-Y}Z*D(CICrzV=AXH;tp|`skl&HM^o-be%mHhta#gk$GQiY;N84 z6>z*56`7I{>xDdYy?N@n_AHbaGLQ*7xcTIhrAlqLYHoDfyddvx9gXBG;viH^M0Qpq z-@3W%ED$jD#WE6LufIp&k(_%y(nc$KZX*S6Jy1nOIaVOm;xI{)!#lF{o!JlZ5d6NZ zUS%4fAbzz)J*sWxO@&!Zud3%wNt~ADff7wDHs&6QT-#V z{;*q_|8^B;3kh-?B{ZQ-xnh20HgMw{8S&O_TcBAlDsSHB#+p;o-&-)O#`lIEHKC`= zcl*;)y;Gq(K1~rfhcCzr<#bSygiwqdpE=dq_tvi+p;_PWDPQ5mZ~cYE_wBI(%kMrr zS5WKD*=Dh_*U$HFO(WwH9&|hxFf2BwyTS`)8$7X_br%6sxAn}TeivaUws$q)}XjQACqPb6$81l%>jh}2fJb44+yXp`HO5eTZCSMJD; zz|0)fe{qw{Kk?RD~r$NeSRChm7clPwClq z#Ko?t{B8RuG%ZS6GUE!SuHe8UEwXUoC}Qz4=p`p)3MW`<-)vr74UbsgKF}&SHHJjU zV>*_grXBXeXSMO@mOTtH3xP(aD3P1}H%XWKcM_`Nb}0(gpULD&(4Rxbj2c0k9cf}w zeX-zktvo*OZL{yd2jgSrBe##Yj|crz9!E^KjuVUa529~7ZKRRzUl)D(Usr?NeKu*( z%OGu$y9f1rqeg-!kx@K(S6TVpnHFvhVSAmd?6e=NGX}DToS6k8R833JkYUK2l*7>_ zJ{ugZQgyFaQ$>=Km6fhJbDM7td7!CMr2_PRoV0=aE1BCcW8lEx&a zH;^HNzHM@Qs)$SSaXGk94gpsuS$p~s($f;3FE`X5}ncUo`R`{?mwzy=DO@Q59 zO!O4>4KEY~t<0@j-=*&hcEA4qILW3V;Tb0c5g(G>}I=dm2Xm5E~R0ILQYvnh$emCpErm4P6Ui+YY zAOlzgIdm6|9=m6f9(NXf!ztSI^&r6X8pfP~oSavk&89J!7L9rwhPmh-{_#YMfJ~gy z@e?^VN5kjA&F`Lt_~mU(0wmnABukn()@N2DXVu|rgt_^&ES8@BW49~5A7Ic{Adw5f{4s+?(b*H+w^jkP4UOGwI`-woPcVba5vg>*7f#C?3 zrpSF~S@W{sg+z=$qw;CPmMW?);%l_L+-}k0!|v=&^NyHXCy|dn(an3uh#K?*|D!Jd zbsLTvu}b4_8-?LMoJ;cTo9*d{K5oC0FRxG8&8D?ol8dJ3vH+co5ET|o+D{+HWX!PP z;=Af_-6PsUonBL7ON|$`u8EWx;;-M)hZJ*r8koBRbZa^g!KOqtVT~gSFf_t0lY_TF za6H{}PXG`K@PvLmP6~kgJ@G3i(FX#UF%52?kREaFi2{@`(TiNLMn7vSX+3@sb-!K? zWBDtjvhPdZPJ)?W1ql-??zA-w-X^JO zM7|G0%}5HYsGB-l>H+Yuvk^kD8;>U+o7uen~t9no!H(YIxzG zy38*^G1N>(z_!$~YPU7@uz7>~UfJQ*ZB*MO$;V{`CC^k5D&D##j0$D5z*l>O?O>kU-TR?IGs~S7w8w?_I>{Zgdb-5tHLlM4yGXNmR zz%RAhz4!ByeG3U4q1d_&_C{Q0sQvgE9CHH4e|}JJ|JDJ?h`e>gszc$Rn4N$cvtM^c zm}IYd@*n&r1#IpOA3}Lwoe1^k_(-NpcM@eTqV(6;#S6?2JJ!rPUw6QnJ=e;rzGJF46E!SssL5rR zC~od8IkqBcirjA3xd&=P0O|YAA~@aXb%vT! zX8Kl&NH3B^E+}ZtyPe3W$%;pP8;v`Yo6ymB3$WwJeV^q*jiQcxcv<17V5zsj%0h-Y zrL6mvD2^5>jt2XM^$f*mkN}WE@z1+BK0e}hz7Hr`Eh3Qq!2P z`Qx&6xvYsBDB)m3gB~{&-!Zhw;7Sm-JdnjIG<$aKC3Gt=>^14BsJIK~Jo-(Pmvl|i z;oKACioyT#W#h$WoDp{@%9`&k|486LtdEYYKc%t;A2yt@t|?A@&AC8y#8(f7CEv+s zUh%?jNg3s+S&6|WvrGW)V^se#Orsq+iQZ3b)BQob;nbMLBj=>y*qGOV>Azpa{6Z-9 zjnZ4c=n)eF-BovGCgr2W>9eak1NKoyhu%leaacI`Vl|rAgqSz#u=KNu-7U}JDOB8{ zuWMJ~kmKkUWl$l%yA?SdJ*g+_QSC~2O2XG$z{*~3b zT%W_wCtZJWpN0olN|o%HUYwC_$xB0uD$Biq(tlh9s6>{$*CK?)#%${vK8?4Z%7RB< ze1RK?@tihEEMkCRNM^8%ll|){C2)1x$e)f3~~~ z^6Cmo*p4%PyL^@EhRJb9-t2lX_K>Rs1g}ib%_GFE1|_)I!NQD7klUG6J?lUQqFccC zFn4a@$vuBLylZ0|FVo3imGL#G<}|kEj5E`@-{SL)+-YZQ9HLFiFmi|G_7&|Uen%bX z{}nv{hOo-M0q)RQr`j2YTUJ%V4ER)lDQ07)Qk`MtjCQ*8#qo%SQNslC6DIR{s&x0H zYXQa5KP?O*NXgQD|1L=4dTQUcXXwJ0glVHrJ83Ej3}LQOYIbs9a>Tju``DPzdseHx z5IAEIHMDQh^?YYs|GhF;$$akbw-ik|1rslaPmA|u?{Bl`K|kQSEe$<89-l+$t^E%8 zgnUY+-t|3Zki8$PS2?I5b29FCO1iv3%%>YLBA8d}Uc`eqLT`Cc`f0YDVN-s0FX>rV zfvAD>%qy`d?KfX4&*zFy6KMvT-(PxmJi4|=qrf~m*VlWLvHhFJi3@}Nf52kI3_kAl z9BR$`j#8_k+->A}r$DhwPpz>1=D^1BfuzH3V&@V|-5i7(SU@cvEkBwV&?y+$7?PM3BuSGGMZ%yt#z5?I@6_&O1a{WQLM<0) z;B3V0*j3LYDNehP~S8pq9eBz|E`8;lnyO!hY6Q}nk1aKl8 zQ{!`N?a&7XXxgt24!K?uWB}&XfGB*_=y)88*W33CvJ3?i_fnDz-yzDD)4-e2QES81 zPgp_1Osii*2NL^gh`q48yk8%NExtYO7ffvp(ld!#hItLd`XmmbZ<*ObC$UaO-$*%!Qkkzf@AQ{>f zJ@~vO6Y7>76E>Qne}4?q&;1NZZsO6=>K1cywcU3lmJc&xdogZomr;_t{jJJjVBO6C zNZ%k`|G^^B9zWS`mjw6LG0OjKDxlzThMBl;q)u9H>iKHgA$O?FA={56JL_uu!}p{l zo@PMe(4hw@%@9`e1X^z5oB5O!cBc{U$9-2HP5`d+LB07LA`mRw3l!|qMYk#lqy`kfj(pEB`+y| z(owpTI@U-tcr7k*YcC8=T<2|4@bUrL0nBeZcjs>)u#7$$G2;ieyXil!+mb%o_*aBc zip$4glH2ZV_MvqSYKA*;vz{}a;6s|*$cdKB)fxV~GQja}Ad+p;x#oOcu5yC5^5AkX zPkHa#-IzFSk$dq^M8{uCP9u}f6`gM0*4RmG^`0g}3o(ytAMLViPcXyqLtSr%e$jSN zVmIqAD5ekZpAddCZNC2v0zYDtz7>(zE@nS`zne6-uT)_DYnf2H4nxH6;~k>M{`HGY zO?UqR+rc*bPJF+&?T0Z0J>_07%%4uYAE=XVRf}^Z1lK!}5a2bmx!C>Bboce&z&eO{ z8Owvarx85nQ)Gh9$G<4M%pZ^X+-|!%@aB2etw7o>)-w^n@+XUq-ENW%RquN z_^?R3k5_7;V0z|d<<|~67c@Sl&&_{@Kj>a}OFjr~77@YoO?*61kV!~%uXYt1+2|t} z5^CA`-Ytte{#EJ$fKOr&kFO8yiD$4eiK&R??xz2-fH#^w z>3cYTv2TY<+L5J{5Y<0oa0DSzx|V`$~Tel zg|hUb||Jv6$b$vba;ytsUH(b}x)>_q4VJ4Pu%Ne7-*ANeh1#ksVGx_>`R& z-cKQJindp;t!3Mdq-g-weR-_Wn$-gUo^9Nh?fmcBcuZe^*2J4AhDYwLyBK|!j(Zze zhlwQiUo>#~WZ!dn4z#M51Aq3_$f(x!ZNWz#=L*sG4-gZ57 z%5TSB&v%A`sQ;4H-QjXlTx91HAAhq~M$GkTYNA71SH!ZzIK z7m(=^mz2WG2kTV0vxD&nSTBNgGebT*hlZq}*+_(ii3ynsuyR&+HqC=4+Rz%fDTD5b z(Xm~!vd;*acsBJY>a<1wUkjinqY4lt0qbBBN2v;Fow1OYT4IgXVSz7Nf*xObt2>@3 zDb4=@@2v^&EGJv?*qlV_NpOwEbnH0~%4Y~HI&0Yx^-$sP{6^S=pY%KCQ_#`hMCn8v z*RwF1g8U9foVB)EaXO??iRl%E8fRu7%7q_zPX3_- z8DR`oZURYm*mKLl!{Nb-I4cKVXa|gB6i}^b*z9YB9Jl+sM!?OY=|RE)yiXGn2!iZpQc)}LtfRouPT0rRbt3HI zKNJ{xI_;lgj!0^!P$1-s#TaWkT~e+z(M@I4{+1w-kth`j#b5-{1IllP!q&3g%y@ZE zUti|yW~#M9VBkJ{xrKvl8V3(7Jlt@ex*+s{*WPbo<|&5d|2b#5aj)+afZzzC2;kTF$7TH5?`u#ZW=a$^Ofb87U33Jm=|i<9?~mCod#j95NBl z!PcF91%Hrd2e=(`&0npLlF$C+``qf11?%qB!y4m5nh~tsA@jtE7O~GIa{J*1#nZ?N z`nY&ygmUDneJ28FD9EvUdpF~ylbDw&PJ~k8spWw)!;Fc3TWvFQ_&1h&qKU7t+Jm=k ztSYTYi2|cVhj<#O@x-0dgB!cRs*C^S0S;8#`GdweDMC8(CJj4P%cK$YbcMWoUx}JI zms_6oU_$V(hL-U3pYF0(-61L(Wa6mu*$xh?>7OEfgt^W-7-lGOT`%^8Uj^bMN!FTw zPA%(oAv+MKVEF`z<=~|_bDi4`DjN6_VRTAo@h%21#x$~lr=?$AZ${3NdvE2nB`59& zRh87)jE$F-yle^$~zz!jYJb~}hx>(r`x=qXk~NoGdqRJ;E3)|IW(|)grHhaI;EN~86U?P)K zcp5HT!t{vbc5g48BGMXNqFG!fzh8j-lK;o?BI8j*6W8KyYns8>f3-6yqlTaW!fqBx$p{TD#=G)9dZM z`{851Vnh9Qe6K|pqyLg3=zRh+wX35@4GRc^Dy=B%wG@0JXQy%d%wkiu$9?N zJ@Je}n8D-G(&mSnz5ea#Vxmn)Nmn13rpk24`)!B65KlvQMoW&?iHVU(_>BR6$U6-p z_pKl1a{FPuZOfIBF%c&RLhL4U>)duFICSM0Dv2OsHb3NN{8Mzm_6+4oR7A-95jhPb zoeVsif|+@p*U3SMJYvk3^xbWe3?_T%j76+HK2?QhRmNHsMo(BW8pp9*R+dCvNK$ht zvQ!$~a=N8{?)~rMS*btZ;L~Tf1M-$H(0b(!!Hd^AUxZTf|CVwEHCg)aO6%#weYSikm%Yo%i}7uMMk}kEhfm zLnVT*ITDNnC(+tq!G zcCT_??zd|MU&7cD`*tyGb4Op7CfU@1=tV~@vm75yh|19eZ&z8!T(?(b)Ol-!*Ay4` zz5Mno9Y&l9$*!=T9rhz5Lc&e0k4rFu!4r4&F=J|=co}OB2i}v=#6W(Dx<#S5CuMo{ z0e19Mfz7SfQs1$}aVS;F%^?yLJ%^uvLOr|LE9Qet&pB~J5!q&L_B{g9V; z4&8i6u^GHM8i%gg5*N2u6q6D$Cf3+!I4FP&r8i+*7O(f}TU}3rvQ#3wrNo!M!6*8} zK_A~Dxe8K;ZRy&|r+06-2{|Q|^f-(b*xb#yiuJeBa+(p(k7nHog!gFCW`yi_qd~g? zy1Q$Yc8$ z!@?dTsg=sZA^;nel;=Zsh~YjfmO-5AvJro)AGJ6|%xuArTk)0)@>%=%FKY0@3FO&? zl=#_QDEjR9eQ^dJL{lHH%`z&ylCbB$&2a>uhu@qPh^C@{MPg97;(YP>hTkz@7C6A) zvButw>K~=w^M1fbeYJ<;7dlhtB)$t@TF!BDdE`Yhc*ZqRDV0V+I_%E;n=k`~E<`oF zIMDl{ead(^iEv3KYF#GcHUlBeX{wW8+k6yHd)8bcW`cZm%Jk@*U|>2PMy$XTyx&8w zGkGZjB)Wa;O3xcayshMJa090sY5AQBzFUg{FMs=68w)#fe?Dt;wEXxn+GyfOh-z;* zSO5!lA00s>Cz(u-z59EB@T+^V!5f>R^;^ixAuRudQ+`5DyRB`aG}Ks7zSN9w!p~M9 z8~r(~k|D&eCg4nXWxK5a(Li<8Zz$?q9GvS~ZSE{?0@Xjs7#NsUB>{IQu-AIa9n|pG zu%{Y<_p<2TP7ei2xZIv}p^fJJ*5w|1wJA0Kyp|afKClI`#jzD(^R))Y(Fw@61}FCz z)X;fQOf=zsPRV0lcQ-C^YO9dVn<4d4Rm~vj;RFP1g;vG5yL^xVzQJ4af-dixV`-xb zSMO~n9v}O*VRQVRTwWjN-(<)yy~!fbK|PmQIF>Pu>NgI4#n?8i*dZFu*KFSJ-HCTS zj7W|DXd-}rjqf4P>&OtX$o!AlthTgDY|~d>vjvT$@e^BG?1fVk9W!pLR2E~TIt)tl zcgl8+C@2k{6x5sg{Eeb4Zt9hFqiN>H2JYCP87tv#l3?be+_(1Sn|$H7XS3N~uYNxs zRVM>wY)KU4BPB8!&MrOEt&G?Ff3QDVo2KkI|B;Q z%YN4r`n@JR5k_x1$O=QFq>vJ5xDPSAi(PL})wel; zv2ewxrvA+5U?u6+@K>gw7Z;}-hy^@@KPjv;vSZP zCGHRr#jRf@f^H2Fq*pC@>22`wL~I~!&-Rl$$QS}BLYt_8LoCc}f$o*ajEheqlC^cv z++GIv&`6R2yCtSe%lSd}0e=s{&DzyfpvlIlqo}m`Ars8AGfb!uiWAx%Xoy-5jIbQv z$n*0;9Ba#(@NH$d%o9lNQ%HPvFy1o`Jq%rdTpm!J>I}v)@cC4r52(RS9vC zB_$1TeL%@;XhQ)wj#Zm^I;yUF;>v#s4kRPAx9g)O_HtbDdh0<&&P|lhBsf{L%sO9Q z7Ygrs9HM63xnf$q+j6&`k@4K%{th}z!})RyEw)@%wbW6CHi5*!?NJOtq}g^^#{7!G zfX#NTkE}jwI2!VMJ{lYVk}>ypL#vQz7{{kZysi)oebLvFGi7$l0`_V?~EPg6c?;g)3L)3q{ z_k7zS7ULWebQPg5CIg7&QRIy!{0Tl(i}s|x+?x~X%LLDcST^Ym+w?&>Uv2i9X@8&1 z?egw_@_<@$8w;w{nKg85qHxNC>z=Vf1WT$oUXM~1(V`Y3Fk<_BUha)#-_9*A{&Z z?-!W*6`6BgNJ_a&n4ue*Z*58{$zjJFMN16@(nT}|GFeu9F(mvC4CHk*461b1%P|B@ zW0BNMpP)$j-kI#Z;6OdG7DQBUn1pEtKv)2jeeB;u=NDpEKgZ9cz+nZk!$YT1hF!-h z&CcOBA512g08{KJ>$VspAC74!ZK`c*2u$j!FLf>r_C3eG0n|%+%%q!)J9=T^>FIKC zIq3k-g<)}HPGtkp_(O^o#|Uy%P3z|%uzXQmxg%8a4*&mx<<}vXD!BTv2BPf85&D-D zKL>|$$(v$)%$DrhRR+A5V^3i~{4dLPibLgI%f^=yg z=%Tf5mTV16=(Qbn;GBaepeJu8c|RW}E=vU)`Q2BV~ zbI$+we%engd*9DIGuK>m&CIsva_D^`Y>07F=xUvf>N}iX&HZ%2+^gB%SH_;3RU4NJ z)o@X-3q)@H2D-G-_1AM2Phe5+#w~dl%{%HH<>5?JgVJa9lz@6qZ(0~moZ6Onxxlf= zL2E)nVx3zeDnyfSLSMYSi)E85IKQL{_g_@tvCQEkRR&ys{iK`_%}(|+`DwAhYz24v z&%#KO7f$L}SUHDHccZF2H%qzCrYk|u)%+0R)e-QW+|2%SWeW5pJ=>xtdFx$yPi zj_XtvZ;Tg7Bnj^Wc-gIn=BNhCqvhowa4V{MI9ai2L7B*=i(*|l|MT<3?dwa^Of3N{ zEi5L~!BEAJhcahHeR$TR2CjhV-r?%Lu@ZA#lg-?k6~#Y5x(FH?4N*gHG$w-V;D+=| z8gza1?1I=VS=p{IvW^ey+i_u*1rHotQg`8A$YF#ss^`OxPXt8GyhB2=quf7AjMQd& zVeRr&8-yl=guM|rMXC7*z=(DK>i;vUk1xMb$EW@8Gvlokbe_A!ZEVR=tGh+A&nBaL zvag~e2j|^PZ8G=bwUALrq1KH*4-?nB}Xc}#vcoMI_}%PD4MZ_t~qAHi;#-D z=ri%zFX;wze0eD5B#OPXkN>?U-ofoep9>0h0?r>K%J6wAsiR91vfFtEkd;cLPGZs9 zjs!m>c!L5hFsU0;EHw}Ykl^19R2cGx?U{O`Ybo`Qto!?`ug23iVy~nuGM7k>GBBem z2Iom`z-VC(ZhZyAnDd{Hhh*&uuDDE0;raK7;)YS}x_19Hna@ruy|g&o?@gpX{9Q-+rlv4|dU~%W zRnnj>9JtFoVDgfe(NsC=hGVFvjdH_GHTsUZ>EqtPt!M}h4oGd z{VR2CvrjSF0VQ*_)BJ{*%62GY;v`k?>EURp)4NfmKdXoB1^)4d2{$grqPy>$Hl?(+ z%gH^fWlUCr7E;~cJtEK{`J%b=MazJ*)Zj$kz?mFCT<)_(4U%XxKV8MZH2+0XEoC*e zrcPJf>qJ`O&>AA|qxkB%XN~qjS!ho8gHqpr;$2qj2ekw;z~4K!HzI0rPKpIIB`#*SY|us81{3Z>bHhL0N3X`20RAOuC6r@}j0qZ`)Wk zbUhrV7PkNHkGYLc1J_yud=m>Y=DIuXKlCf)vC`S%&|f2z6#HV1gczSY420Mi`c3KcT21PQ&>V~A{aHDP)UvDt& zZU$25^(i$ei22<%FG7Mk4VP;yjCJj@>bsRH#I!Gocma##k5}GBU;oG#eIgbbN*gWZ z=`Ty!D&O-DB=~aPanb3q?m;5{bkbR9yfa@!$tf#~a+AxJnNtl}r!ZF(g58E^v}T9* z{X5F!dv7eE>+8|V?=<-8y`|Nb`}t3X?Qq55V2}uxxGOM!cgOA5P<(VVi6J9xn8j8m zi3udIFmY$S^iMz+x9*3oV1|F|ic`swNXE*gaNboXu(|cz9 zHhG>7V-L4KllLT<%o`V6{>FMp3WRz_m5)9hVHg64>F6{)8N{0zQIu5->T+|=#{LA? zC5e|EXdco3{`=Y(F!5CF8vJH@6cGzWE2kTY*D2@iI|Cg#tT@p2x%OR+I5H`N<@Uo+ zdE_oqT~CxkUiQY7kd~IoBLkCqi&jcHu5OC80lIB7*fOW~yVRCcnE>~()CDT+7e)X1KNxb7Oj*$7OWIGn~$#`ZW`E%cO@ zx8fod^rbGVG3b~>)aT>gRO!OzA?Lb9c!ZD#git~EXZW9rz94IXIc>}=oOK`p z6+;KQ@U|Fh(MR`Zz7IU+Dr5vQFl{+j`BLdwXi5RixT*?(j_@@>`h_UQ+xI12A}GH1 z^+k^16$G{AguYKyiS!FR=zGhR`2G_*On_gfV)85F_z$1f#!d?VSBlq?1piYXa|&RI zVZLUfKM0D_CloiC#XtG*Ds(KXwT3@9`%5SH*0=AC9%Q#Y(<&k5LdP`2G;ET*IH5ng z=3Bs5LIEM&G`#K0*X>}&*pJT7CmYCk$n6nrc9gxU>0Nuh^4xi3yC3<7)VhdO0V~KKw*}2q-vG539g`k;9y?iwB}sFu zsqRJv*^$(RBJ%u+K8xGWFnDx1hf5yrS~;RB*psf=*kIjis)ZFrbBi33e(Zv4RkX6H zVJr+YgVjj2v$CcC%!CewmL0Q zQwEZ>@G?qJIH~pAUbn`NFibh|I+&!N*Ix}S7gJ8RpCMmz|KjP$;HJ#~c+v6qH^7T( z)89Q0(6GFC=1yK`ot3C3ywidA>)AQYbf@=5w4Gx5qYGCcUBGtu=0n)yATtLPf0H~? z-U?|@<;UBb#fh^!rYPpbO{cQdiT9gXOBtz3(B3mV91;+B@}{^-$^pIg)x(mkPVGlX|9XKx*|TiSlI>z|O9?~WL@1i>F+DEOjf zbMIm6#Q$a5Q`p+Vuy@k~xmr7|pIZJYFwOVx8~I?9@(?I#f9)e&7s^z1!JqxDW=Bgu zrE4@87V;e2NP)T;5EcukFW>ChuF_vp8Qtks4)D?Aj@j_3%7*%|%KIn9M(ak68OT{A zf>lN`x>1KO7RVpTBa0f1Lq3TeFMRmNV$TW10%=X(j?L-{n~!bVuIQnr(1-MuO7Bg&7$o#OM265 zui2K}ftP$d=!<9KOpO0i^z&UjfI`_^^_f2fffRB=hzPH$?zY+9<3|VE;XAVr3yP8! zDGOO>eQ~YFL(+3*Zn}2_ITG;d65x=H$#lYtwoJy@7aSm<+%`X9rE#Jq@%T352R7JFC+x0L^ zWwO5y2U>Cai|%=Ml0DnQPds6giUg7hqjcf?3cI}C`51;@!q(}Hn923_#aB77&!Y6n zV_f`i8%MhlhPo{-XQ_lls!u4&4!5Jk)pF0 zJJtfgU)N~Z0zF$$gby)sY^;f~*VEakBBWlQ=XGq(sn8>vi~*5`jAb}RV^Vonc3MM9YmkYWmltAIg0S&oi*?7hZqEKC!f$F zIcXdRu{)eP!G}S1AR?O$*ZSXLwQsmCEVZ8^F#&BjVz6LY?+M zC4v>+EZ?i#t%@|f?fcVl-F6?Ab`&G#Qe@vR5UG;8dbo|pqvH}rt@M$FSxL~X-ip{R zDa{ZiKKN*}*;YYxRwh3J;u685lwq*5hI; zl~1RHBR}F-@!4>UkzMg-cD?Ifed%{9H=TgPJ2x*SR~)};8=MjKmJxykIU+xQtsWBE z9!nDPY?1rMgxkiFI%VXuttGaSj~b<-=f4rxjDFbs6Ajqit~r=1QKmU$GOLdbD_U|B zTg2D0t_ykLC)$3J%1@63YvRnm3y#JktuwKrQ1Mn>_9zG#{r0<*8MH3y{pSAu8S`jj zX<@dD>EQWsi(_5)ITn3+!-jI%P@~$7Af5*6Rj$9-gT5)R``b72)Ad#x{cAB}Y7ygy zatTE|?WpYn?HR{!rm!laQTKoZaXO1zf~4aC!DVYj4g?*}YF0j57`1JnF|1NLoo2J;x@46bV#ftqMw%0DGTf13*Do^ILSTaz$G>N0Vh~Bs*H08w&&~_nw>|!L>aX|?O z+bQF)oZnf+2~jqEB)q+T#%rj7k`~Q)MyC6|d-eaH7C?aT%2{Z4W)E1>2&F*!{%BbH z`MU7gmEa1EX!rX47unArW)e9eF#UaW;utWeapL?=Bd z_Q3|=ZEZ6Mc)^^;v|1K<4bJ}WUZrG<-Im4h<&Y&Fue0x-B);H&g875zKy=n9@rYhy z5}p2flJyq8KKdNyDgO0^Nq+mVd->KW|I#HTef0g(Pen+t@Ag^F`Z_?VaroXVb-7vI zt8koly(_!8^vLtGTl=#SJWz~Me&{N!*zPWI*d!b5=`RfQtH)3?y=eBpYv>_Mv*<5j!KrCT2NX;QiGzc)FO= zRQ}iJmzkWg{Ln75U6>5ZqRteZ3zAm8K8Hl50E+GgioEmtauA2v-yssj__5yrFuo?K z;PIxY1m$S8$u!~`d+PXhk)3;<&wN~a^TXyR?{7mngplN+@1ltNpQ7E!C-`pazmDk2 zDbZ#*;07JokLc`K&*!Mu%INs1{Tj~uqsF(eNG&0=F8GNQ$aFItRITgk~2*v$rtHf##f1(FQx{Bpy$vK?$mn-{D5K zQRL&W^z=ryrU~A;p4;!yp~a)AK8pPH$zkSuSU9-6+va#dmB*Lbl)%eO@Ik#!>)!kI z*0uNI@%(7opQm0{sm>R&$ReSg&2Yhpjx$sR+=NIr$C`Ltt z{pfg5I^r(_Y+k;KWvP^a8y4y{Q5>oDf)uxxsec%kbMIX9L(mb_{Ks~WpHGV1`udmW z$9*EgymK*}62fy&m$qwG@#|3k{$!0;2#i0Lz;TBEn6{Esp7!`M!Rwc9_3%}+_H>NY zcSFi3rkp)2m9u~AJQOZ-;MUv#YR(a`gAl;u~|(6q=(uWX!1w)cB6NXts~2J z)}Kh%?_T1$xP%01NA7#_(FO3fnFaf+rqWzzKC~L0^@X1zP=>=i{oH%OmU!Mh<<^J2 zhoySj7^&T8^uKi9?Rglq!mLofcrWUay9BFf^vzXgtm$a-N#g3H6Ay3WHqVF13^2I8 zYBYlq;xfB9XN2;$cHSEoJ5e$iN{GG>nX8U6KJN7DA>X@=wj=dG@t1|pg6KxO*QXuK z^VCz(V4$SOygQ~U9_J^s?Roj*i|?h6nG7wnM6krgXgAUQ>opqM&?8c~JCOr>{m9^V zZL$drsn36}dL^7k$Wu~BE2jQc8*N_xtUDi?C=4IIN^*t(!RtIc{}s`sYliMNSOlKRp zt>bQznxe0bulk9tAWEf>c7mPP_{S%~-#;UJpT>3Wwj}&W{9p$bnhH^z(yg@O*^+V0 zn_G`oMzR%7I?>_Jb^qpfHBh|nO{{D4SK1tfzfgX;?DRMz0H}SlyNgyVv=B{`48%B) z@blAn!1fl9GGyMn{u4uX7-{lL$zluo1X3pij*yQ4uSmo=ZmoYrQ8QZw^%DUuJ45*D z@~3Y`6HHcI@Ehlvq!MymoGH)zeA(~htiOAMbMv~V184WF1U*?Rv?2dV4(x*q_@r*m z3O&|iVZ+~WaUF~#Cfm3i%?Y)wV*I13jjP88nF%qhoIN2lc?Y}o0>`#}3gq3Gh;ca? zw=OG9l}4Geu+Wxa;S3(M?SuZb_uX}$7N@DZZq|#-9M4m~*3AQgFUY+T0k!_8 z3U@b+9EFV2p@4p%L(rHiu%Aabu5gpx4uS9n zCfv_efrx+19hN7#mlGn&MUJwPhN}ymML$Kr$C>!eL@uFgjyN)7{>|dkZV#pS+u+kq z#E~geNlvVOjxUe=U)(pyQXo5h7Oeq$Hm1k$U<&}WY?5hs8?Ck2u-N~u9*cae>u5l` zU9BhJczys`7Dc3+`Ji(2-rxiE7?ewsQ8!^qBvNXNs1v9A7gPlr&J0+j5MRRlGYje( zB#0-BhUm@Drh`Shk-z~4&duz>j~JvwB;guGUnw!+ofum9<~RF9ZrR5kjc`~CgOVfh zJ9gkGDU)AnyWJt_B0d|JkLSk}FKFvtfA)ZNl#G*Z{dTS8_~}WqT>RpJeTiJEs!Exw zo!vyn#2GdN8xXn-}1{Bnl zh0bo|$D7IT#;J6j!wihxkGpc{B&3_J2{{yx+V@8E(4<_Q`L}`QhFYvX@*`)z&7Mz+ znxyQsV90&;az3TYX$W3?&?$`sQ3Q&>mVQ#I8GNnzwdp;B#c3r(@pDhs_(bw zDOYUPq(#f;KspVQ7-&hM>jS>zeCUZGBLd-c?Uxs<6VgCL?VPq~4^xz8ndDn&$t!2^!Mni+)o6q3k z>eYn&!QJUZs=3xiL!)&>^Zf$s=&>4g!*MWVfLhQ1OhGV0ENG7NRBk<8{1NeP_|`ut z+Mojxx~_;IfA%>WkHY^7W~IkNM7~>TOOE5rO+1dIRbaE+##EbLx%FtuM61mP1;%q^ z%@OFwzg_hwkyYxCH(QLirH#_$3;`<0M4{eCOEUoy4;!6{`FpyeLr7FuA!v9~E=ke2 z_zE!EIj6&|ujiL{(-hC(S~5X!q&C1b1F(*ebZT;R$@a(guT|soNKDbDo$-{5EwJxN zJo$)(#62s$Z}LA0+X;#6ttdG4*5N}xZg2WxkfJ%n_(}BPq-i?Zf7oQ6FyHryir3L3 z{3DQJp<#^u9y!I_sE{c5Y6%MsF_2#2M+pKMZd;;sV>`c5ao(%G?JuYeq5bYKEbdNv zw?g5E_4?4g$HloL#fu|na0=@1M*R1LomLiOM8h3_u1_bKbfw*{a*N?+r6)x7c zGInhrzNCMj$?tSp3vJkv_PspFXFf~|kcd$Kr^|X4bgzMJJz1;xrZ*dFl>#<->QV0E zg(RsAXs3SO?QG}$&9KPcA+(Y`!FA)p^u&s5E>|M|3;}bds8$dXk(tfmj4d6aqz=go zi+=iT>hNJH;-lCz4{5Y9R*Z(KxwE2pn#yVb*LP}h7qQD#_`53#(U4B3F%x&PsIpJ8 zMOvgzxvRofu0hlgff0c$P_fV|A!|YVi^Y3i<>wBdI463&D>35#e3cGNSZbw=#OW{O zoN6)~yCa>%#}&UjTW#}SCr^DySG#N~BNRSuyO%<{Qrmbcar<$=RmNp=cy~EALLn`u zw3!r#o`TbL8n`~d;s1!5V<&-qN+T{u_xF-sfcr>YebQmK!xSl*8| z>d7retam?rPKU)>fo0gW6e-hY8qkqtN*n}w2AE3so9#NIAM2zduAMi=G?4 zdFDR=TzfN2XsF~hF?Z#bCs*IO5E~~g?+G5!q4}EJqkEKI+^k!%bc*RJ}>;#jUOTJ;n{Yb1-IfBuOVMy z#&5N(8lU}G6`1b5bRo?;{I%V(x(o#d?CYZn<|%NJ>VJMjrm8b$V;ps}T3zB^@%iiI zyA_PN{nq0sbkQNEH9a7CkKMxNvNWa(Z5NrjFEiSp{&d)Jp~Y*v$i%oa=G&Pd5$5Ve$yr^@w<)HXq@VL`Zxf>ZU z9R|1uhMdoTgQfzNq3tTaoqwx|=+ZxC78Erh-L84VUYKA&{&ZTj8cGTVX)+dh>bi(Z z2?FK(tj(sqLVHIhAXsl$QFtPKN56&cjs`QrsEcIIer<2##JpYWAknWx_Rhr!g3>@@ z3u{VoFprjb{yq!l-@1|Z&9iG|uKd}9MIe*XFiVmuuh`J`R(2uni?Bf}Hlzu zMl2UPi;+89`KN^A$V9y0ubYjvbl#$d2Se=`2nm%d^phMxbGqk%UR$iE?TEiA&o11w zcEAdA9XWfb%W|X#nPOjv zNs!{S`?V!zdD5vF_|3+3E`D@JpIIogs3JwFe@Pr=8T$z$k3^!M)AShUeufa^#0@@0TS)_Z}K0`jk|hd1*0x zSZ{A+;=}CvLT{RJWl*JFo=60QNBl1uf*7+hs+O5fZ1zXnKAYDwSm3w$j*WzBMp)YF zhCjr{E*Rzar4NJwe8)(~xGSLG0G~D--vp?f|7-}Q?Cn!^yb~In-a$;(FniTk7bT{{34_jh-)-{QIn?O zB%D4fCn3W*Ei&P`rePJ4q1a$@109O$L(=UyGy$$PIeT`2n*a;E;7B?iB`90mu*Cjv z^a(+(dM<5V>JTSKD^NG2Bt)QAy_x(BkOCn)JOZ4lX+Z6E;R3*FM7>s1xJOpB_V`JA)qkTwgx)m@|e* zaw>tBwz5eYsj$8Zo~iTp*_n^%tIO$o4>Phijf`2s_OS`J{P{kseF!T$a}PpcD6`_pH7fqqX6+X`GwL+HDb+I&F8 z>ly{j`jgkxDPiB6rUw9ijcIYlmMHD?EsCJ7!G(+aw|`G$hr9_3>pz?vO!IsfP65?$ zz$Mv*YQ`=L!wkm(Gdl`4%Qm&^$+^rImHBp?psY%U#%v5aevS3QbwVu z6iL!58=&8p^;pi54HK&L*&##Qozai=c}&zV>^8-opzZZl6D<$Ko-Nz}U0$~i1C=SuHSPE^9;T0DBZQ`aaL9zuc&?|e)=G+#4`!9T55S02ZR zPY98G#KQ(eMoit-1nyMhFdtYvSK4I4lcbw_|87tY)#F0CVIhWLpQqh$n;hsD3@7?T zOIW?k4g34HwMfN?hUyf?$IxYgt1!v`zbpB7^S{#QTFXY{nb^&WnQP0>$5JI8t^C}d z0`Fu3Y-R$7=DnUh$;};^gQ>Dyy#r< z*`-!ChsNdi%VAuehUaz&jl&8VY9yUNK$ZfgiJ_i2&UpY+5}G6TuVh>(H{$rtD!m@9 z`jp389eQT_mR42y)O}_20$W*)M(DaOCLgxhsuIyVsDxS|8Gc{x)2IY52-t%yLM;5m~}JV2zx$VwvX_ z(L`_R``Eo#db#ifleN|IA#Izcqu1mDCgxycM>ry|sCk1nTM5*v+U`f~C(NhSC%KaOGbA=uYH zU`w?#LI6X~xt%A>SvL8fhqrhqO#}MZ6GeqP69@vNxNSt1bd#)KN=P;1Gh^W7Wh}9g zJx7=XQ{Px!n@aE$+nXz)rrk`aVM->sx;Sx;(tV8N$;mL011hjz!x`yc>5(c&?lje! z*q*)W{p?EX+4@;s)xwTiB0X~Mop3Yd^Sl}6Jnn&#g8lWWa(9`Y%l_ZWMy+`g_^FQE=%)wEM_zn{m z`kFPe4=tix5asTGDJ6Kyzc7NkkyGCI@9aJEQ8Ny*v`WS9^mqp%tusN^Bk*sQzv?Y}R5sl9|{cDmi=rjiY!_V1(xFLJV4W2)P@H+G<$C*N7E zi#R#TZ!Xj|L;6{KMDgH)(hy+yJ|yokM@jm0hD_z5#pQxXeqmP`C0~)m4hLA3S+@O3 z7LzxqrTJEgUFVaH;icZ3e)ay)CUoJbVS@z>6@)pn(BD5qRlic*0*JN0;qGf6`Nh?SF!#Zg#LFFDwu-IO0% zk(d*A;FwggQ{VY{y673ed~4HF-Z7F&(8Hw1lo?84VWnR~pPjt-spt$AP}5TUe_a zNJEe+`9mOA(3-xrfNZxIBn^_RMf_Dww@@ECki`f0z+`U=ya|BlR{%ra`HwW(8nPN5 z@YuuNnTXh`{o_i|-AqU?|7ov2^B!on=8gOjhWRjlpCkCWHChKBwg@RT-a^pV4=BR` z&4P&L7`;1#?8; z)TQ!{%5ALhHn)Ku3tRa@VlVa}VDc3qp?0N>WdG0P`l@LnluMz15kZZ_b6$`z7Mz>g zK<#Ync^@Gem##E>%ti{hK~fBN%TC$d7LgU=0pJzfKf*WY%F+c6T#5NV%fAd+meVwv zDsE!*2-D7k9naWChtGt+WYz~Y>_*lj$(Ve@dFS?#dP>d6q^{058TCf-(=}Gt0np>1 zGtOWzhNb|SAD4g2k0dGe{9F!AYjiRBjBJqhgFiDO${B3U=hm@}5#stRZrHOy{mVaj z${8d&QrcG2g>O9(0Q-d!E8|%#^gagc9P>waGQ9?mo%NMWL4K)jX7e% z@MVJduW|M4tGJHYv^xcR&@M?6Ql_?RejLbJF>@b9m9jMh*~EoA8oWPUfVN;CSQJzY zAtWBF=AM$>m45a%T@)JVbO-ULT$h)>)L6#=X~~ z!iE_ADvHAEnVGA>Oiw=MCh zh+r-Lt?3YMFQnJnxVk4?;uuNWC93$1J6A(c=Mjzp=-;ADP{RW!44C5bQho?;%HRFG6|1P>cm+_7s0I54%uMDza+jQN+jOy#pB zwQEI{T}@p^a`Le`qY#q@B>}Qz%ac+}iSXXeG;VUG2F$2w?>sh$`pOnC*RiH;vXJET_wT?hOQnl4pTP^E=r21vv36OL*5O^IHxQlHaHPupoWu8JIM(D@W80v^t}dwm7R7$S3&ppy?txQuNK=kLuc9p z*3=8SEE}b{!c|OqxPghB&dteNiY!C(>`@Ec$unORxZ(d#3*arLX{27)oN4X`8y*A( zTa2f$5|*~D&~0s;Gh&d&ZO!Om_b9Q6$^yn6ea8Cxe^xFbcx3%1i7R1A(7ze#KtDT` zOxdc$_4y~3Nqns8Au4IzO+1&Z&7VzYeUU6t>yX;g0 zF0RUFHTb#qZmd`Zwjwlz&p2`p2;9?7G`3DV=JmAx0;0+Qr0J-#cS}wz_!6uNr=M1? z5^Tj4)gvBN%)q$B@iV52BAu9@rOqNZhtkAYX5$l%Dp?VjDoW+IY?mKvn814EmaC1! zJmUj^Y3k6ndw>0>1IXF0s5B~HJ_SzSg{UqQ*ajJDFd}sD9{EEZ*Ng27=&c|9wjJ6} z*C>#+UJlb;$gU=cm~g;bsVJgUbFyy7i(k*(L5Z}|`JDxq8iNQ9R*1>z74P@y#nak@ z@p5!DCKA)WP3@AQu{bVZ8S>bM;pJtrgvWKH(CPf2I^3hRih(6p_4!J9dB(Whq#w)q zJ*(_g8gNHxjQmFb z9H5F*tzQS|`8=uF<(w)57bGKqw#MQ_M%2$Jlx-+Mri^NNZo=^9?16j9Hi=OMZ!y3L zd-JsFlo^)bu~FSY)|zW0y2|;a2fiVACA`?>YIZ%yoypx2QyuzUU>^v&;bR3i&$$@|wxDbSn`H8N}Q-;PS+!DN)0Oh9vP4=Fu$@`IxYC$-?sD>OrQsfDT?jLen6oL-zs z8QriXWE%WQt9cK6!eVt+B;jmoq=)=igO+1%KmQth-ZPJ!*Zu8t_%mFZw^EA40h!Mj zVJZk+z;G-ZBSf+pnO{`YM>B*H#BOl$)bXf~xx59K!%~rq3|p;sI$|)yW?CnwR}ouP zWx_QW! zdlPX|-mKU2Pa?&nRJ32PnkG_~)X|xYeMo(fwF2N1pQH~+zBVZDFNB5GAPf_@_p5!Vh;twoOrT$w%FAAp{jNgK3UErHJDyNaHF2wjt)8Dg8Vss_NSFhEz&WXhcXL zwi1T2D;8wejnUby&QM=LVjj5Br^5dxkj}ZqO&KHK(kt~X;dF_Nk%=q zMF+)6eZG_zgLvJ;ePD@T=34=>OFIy|3Bs_v-4pp&!B3)5VX@NVXZ5>5vr~O`dzzgX z`xH1o=UFV0w8j)@pis~d6lBf~d+#NwBz3q^SaoaMZ9;GIhLy!dthmA6#aFbRD8m;& zE>ajWVDLNB|F3uQwT%Dpr6+N6~UmQHlYQWG}^; zS_N#1cHy^#g3BylvW`btfMqjM8<@gB;s@5r2%^O*?zb^B!)40uCfUV@Q%mF*G>9s} zxr%D`1{QQ;?w^zv=;}x32@?$5!G)vG_ea^Y0ct-q(cw{R6x<`+F^0-^k41Z2l$ z)C0RMM@d2zK&w?wws8MEJ+Ez>lQ|b1!E_*{YaYzp-}xOaUgg5sat&F1SFKRAF$Aq- zwgle6$P5`cN{MK20-cGaQ4>kyn8znuupa`OzX(z`N_+9$P8Wj~jL$HVs zt*Wa0PhF00Gs6ZbCKwn%MLd=dGC+d^nCcJ;OoD*0FD|49xu8*p9`@1ziwFrUc+`+z zEIOSy1_fq@1(=ELMn*QoO1@%&A~;EqQ7#2{+L3cGoQBel0riW8#SbUPe|Pl5c@;XD z!WSkD5+R$CQ;*q$DV9<%h6DKrKo2rpr|8?CjFdeo!fe$~ugY}##x{|4z0_*3avhK~ zm>YcqGs}l87sc3<6DbLc3P8gQJ2-+Rr)qQ{Civb#kDqNEW1dFUncaYv%SP#YYE*kz z0OPh%+RW$OxkK9fWQ-~a6Hde~1(pe~n3yqvjNdBQv6f5kqYj171D4TaVn$z24si|G zV7^_60q)6_k$K~X1TDa8Vh3tAaCnMBipimtseU-97dv}e6Ynwhmgw%DFZN=*nSePq zMemY9WmfN6GSw*=+5Tv~nWP~sA|y=uG0Rcz`>Dh;>TFP%4t9I`b==jckSJCg%_ra| z7j&<9_GDc$qNve8)~43CI`?xBSOBp#I(RirRsVN^l#G+if0-ZvJiziV@)8zRT1tOt z#Cmsrim53`Hj5`C3@as=qPv}8kZ9qTB&hYORs_n&h1-}^nmUqBy8b+laFGKi27BQV z7h8!e*)N4W4`bciTA~{xTQrtHjdOaNNeQt$eNA1bSooq^(%u|TYXP7~9`tIi-HdBM z{;q@cQ3>pg7|@Kz(_2=RVQwue-kQh-v|QFi)I~VNbe71GMxhE`VMeumQq$JWgSavd z4XH@l5NPT$`pon3Ik$aEwe(b6(?n7T@K7JtY&B)?emllVgk16K?Ax0GE8ieXXIa^G zO1;DroiWMAROm4{>H_I1EY*cvIQNLi@C}-#@&;KM;q`d7NFhkC9F|GV8*!_GF&(w@ zoqK^X3&F1fs?Y^m(S&kAo8$dOXuIef~?1WIixahz=eQ5ObF%l(*9n=!~mzh zck22_Y-r+4bH*X@L!V(8Nu56vUQl}to6Ca^fYQm3GxPJoU{kU_nu_X=8 z#%o(*O0G%)?+MGsXlTxT#L|zkccKSc<}o@0vX~c>b?IU0{B3su<46U_)lF&EvVn) z{shbM+KyuXf3H`HjVY;wJ-jr9IkLC4PS5z{tqE57IaR^9B{eYI#S7&yl8akfPUXanjZp6K(s6Jpd>0vWW>DjWV}LvZc-9b zXrvX~U?`v67u&AU?!+|2VDS+No)i-jbQD=TpCk04$AC7W*sBf3jc}ZxY%33dM z3rJ&#|Ho1TR@a|(K@0PZ{*9~K&-ab4AnSQ$PHYG6UEP@Bo#_L`eiN8ns!<>_RXZT{b)# zAoZ7{y4~StvG1_XhtHw|c3)M%W)&~OxGVEemM3Oo+h;bbI(7I@~ymd|2W;bT0vL&76y=CP%}L-1G_+h z9&byx+<>6270WoBFJ9`M0qB1Nkn=+lwUD1>KE1j3p=Av(MMED$v9CmT776qf&?@gs zCwbpkT#W<-$~><2K_S5s6T$N?GQu=YECVE0*)>U55g|b`xX;=6%tcZI%7LF* z{^ddd&4J>@jv;qXilC4b67*eKcRbA`Xr3BZJ_#;@dgyDuDykwU&li(qm=61zU0vZo z8zg8(+m-cbQ38ezQjfFYaXtbyA_r~C=S5AgdH||Iq^&(sU`E$?RLG?J*uU~zUu2)r z`L`Im1?z4IHhU{3S#zUTte493YZry0AxlcGc}5J5QS|2bADi4C_m;*C%sTH zG~f-h9+vvnl<^OBysf#8Ff{HnyR{BCWqACfmv#xfTXr46G}>=a5hdvp-z-}$%w+h` zQlfUo20y>HdhGp7w7$;W?-iiFO-WHc?$muWecRo3;Ix9iP{scThG*Cc_QvzbgEQ~k zr;BIgZXy15O*H;oBzR=Ij~sKG>o^!4VZfXdb^+~g9VBBds-~ufdA_t_rbd@pr~M=L z?XwFF4|Q`TzEa}-bB<1#wzd;CQ6|xO?0R>vKKi3Vpoyua%h;grPfrL!lY(ZpS(`StA}w9otfVkH%OX~WwEi(wE~S0*=Fp=` z2F8cH-Ndw`ROaOKL7X}?wZSLP1Im!l3U0ErlLH~?*%_c4EAQr_^ZRrj0|Q$V8Pnmq z^h=@|`)3v%w!e&uocLGbB@ijtwp9pCnfgi8dRh_7`+?eiYNvRZXWx2TuevQOGFoeh z)#aoSe(rm?eT0)o;9belW{4=Y33$niHF%P&h0Zm}mJ~@ZloP=|%4fBrIPc!-c$9^m zsH2xO{JWO9n8@A9C8Ywmv#lW%)91EUc8AZEnwsX;ntZ}csdQT^IH)eL^=(zCMXY(Kc)s@o`Z>Wj?gDS~BS zul+Iaj+uFMD(>6B>|&26lM4F!$)2Q}gX#j4Z6uosWS~D6l_EkuU7#vZmG08w-mhQO zSQseQ)f=APQkD*ib1jt>CYvvMAY~&n3qm9Z@}M+j$we-%UY{^fL$hFe z7wp@j+yPI4?A!Wk_>4w&hP2iH*WOouwbcdfhTv{Ric68=6n6@=P^7pNw-$Hz;7~zI zk>b#nLVyH!_m<)kT#E*G32;x}@4NrRT{kN~ot2#A%$~hx=9y<^bOWR%zpqc%Kn=Jl z*(le*GG?^F><;o4c^#8qjQiqWp|eIdac3IuJ;^h)^q22Hf+VOLSo<#ZOlF6#y&n;t z(3@}VpYR`CUgjQMF6|T!-}pkqCEdIC=&CG+dx9q)gS-~P}`t3?=tj)KINeaRD6eR-MD z@H`e>y-9Ld{N1+j*awkZIKrV-krwclt(3%fyU9^zUw(W45?3!T{AqabE0%`WM(gKj=6NA& z%&BSHyYBr?f}&+Mj?;Q(re0*nQSx@)cSxk<=pwIx*w3`{J{R=JJLAPIit-{FdwY8~ zbjT*}R{~7^VqiHtE1>AC6 zdue7$ITfA(fu$gGWk!YKb2DASQRA*%3{5o^!1b+V8Z!_8Ej$YG#UB3=24phy=f=RAKcw0yOt6z1?YhVWTT2bWWJ$#1kABdq9Pe0(mP5vnJfRO)A! zRd`8t%81GBs081Y6*4mGm=F3JH zT3)!&0C2doK~6p|MFq4I2Sm-Dr2bW<$Y24k6>jPDL0;S$GxE7eeg1Gg3n>T-BDEX& zu){AX(+ok@7ag@(TuZ=6Jj*w{DH*RW!-yO{Y5Omhns=ruz-p#jgn`YGHt|;4b8a2V z=W{3H3uad+oB<1XhSjA1mSX+Y?`Sgk%BKQibBl zV~q_NbjY`h1Xa{xsu*?8uj7*6Dlh78)P^bb??tHUSHH0oY-_5T`-Mc8l)|(YtaXJg zKO04St7M5kI5_R#7@g-GoiAS%pL~_yQ?<+0(qIeAR2-YtdP0c~!i5v##A41FPu|wE zMe*wE9B%tHV=2vHu+-8#Mst7?9qoLavV21P2;XyxWQR)^TvApRB0GDD5v2fjv7-1G zqX;g@kAX14G8rPa%`HIeL8o#m|3+tn$yhZFBQ<( zT`4rF*tt!-=80YjY7%jQ!qr`kT5~(QDfeMZ`FzW0m#^7MBO(6I-N!nvZ%=}@P+@58 z?)pi@lf-Y~Wi;TH`+ZfZ$!kfPG54T8+1U#17w?oGHOM&ZOYx}bagB>CnwgjgpIzE# zm}w0LI*~ymJR*O}J;Ujt(kDs&_3F=`$JBdvVkAv|lkQgZks(uulJQF8J>w^Hz+BNU zYVuW2lGQ==9BjgbI2f2+%oO9wa~KMpt@ULJ=yS$^aOszCb(qrA2W%&^8ymAFOWtsm zGZLsewew}A$d_FV6}IULQvmZO9O*I8X~1abIaEjZqNfEh-Tyf+1{U=(+~hCIKl3~y z8`#qGPvTc;3H}iw#IbO!{}e-Df#3bS$T*`>BECSj`SYJQXc;5T;vjE5-m-;RVo5HL z+FO0x&6u3a-HIPI`n5^Fem6no+co8JC{Vx5_SU3D_c|w?9|v&Twt4p|{j_;qzi~Uc zGj%QL=5XI$6Vk}N+qO$&_wD0}D7fQ<2oplD9RvUgqyz8Rx>jrRjKrU;oJ0BYb-=&A z1Z|>WKq74(_#1F5P3tf3QI!zHc6{|cr1PR&V31H#NF-|;O|MW zC99Wkb$T1XuD@mus{XC=P0fduI-a@Xk5b0$b~IBdKDWa3EuaWX0$)em-2d4O4>r$H z=cWWrm_9WB0=nqQz|4P!_IDlXPo)$P-EuN=xF^3qWSfB+-#v;qg z5>9UPR_u(tqPOtLc&+?eeD_^|-JXrr)J%sh&D|uvh1X0D+Lb)&z$Fg#hY>v0xBI>8 zt_(6V7Clt+DHH-NsOm=7u!6kjQDLAJpS>LTLSHQ*H^^@@1h6aKHTXR#yT|V+A&R%t z?V(Pk9pj&yT&1lFOS@$htGWwr4 &94tycL{b@vGmZ6CWB^*lXaaWW5c~v_sq*=k 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 GjQBsdzf!;e From 6917d1cd76f4c25429c9e7d6914be01ea38010bb Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 11 Sep 2024 22:39:57 +0100 Subject: [PATCH 104/142] website: description added for all other pages --- gen/apis-md-doc.tmpl | 8 ++------ gen/blog-md-doc.tmpl | 8 ++------ gen/changelog-md-doc.tmpl | 8 ++------ gen/commands-md-doc.tmpl | 8 ++------ gen/events-md-doc.tmpl | 8 ++------ gen/integrations-md-doc.tmpl | 8 ++------ gen/mkarray-md-doc.tmpl | 8 ++------ gen/parser-md-doc.tmpl | 8 ++------ gen/root-md-doc.tmpl | 10 +--------- gen/root/README.inc.md | 6 +----- gen/root/tour.inc.md | 5 ++--- gen/types-md-doc.tmpl | 8 ++------ gen/userguide-md-doc.tmpl | 8 ++------ gen/variables-md-doc.tmpl | 8 ++------ 14 files changed, 26 insertions(+), 83 deletions(-) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index dab363ed5..cd878138a 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index 209aea9e6..50b52ca2a 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index dfb63c124..0534d8acc 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index bc4a400cf..41c1f3fc3 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index 2c47b0c35..30fa25675 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 596de4ecb..2f09f9d93 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index 9e70b232e..7c32530ec 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 5bfdfc130..d9bb63200 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/root-md-doc.tmpl b/gen/root-md-doc.tmpl index 822b30ab0..07a723c6a 100644 --- a/gen/root-md-doc.tmpl +++ b/gen/root-md-doc.tmpl @@ -1,12 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -title: {{ .Title }} -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} - -{{ end }}{{ md (include .Description) }}{{ if .Related }} +{{ md (include .Description) }}{{ if .Related }} ## See Also diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index 556fbb3f1..73e3dea76 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -1,14 +1,10 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -meta: - - property: "og:description" - content: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." +description: A smarter shell and scripting environment with advanced features designed for usability, safety and productivity (eg smarter DevOps tooling) home: true icon: home heroImage: murex-logo-shell.svg?v={{ env "COMMITHASHSHORT" }} heroText: Murex.Rocks tagline: An intuitive and content aware shell for a modern command line -head: - - [meta, { property: "og-description", content: "An intuitive and content aware shell for a modern command line" }] actions: - text: " Language Tour" icon: "plane-departure" diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index ce25da2ff..60d47474d 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -1,9 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }} {{ if env "DOCGEN_TARGET=ignore-prefix" }} ### {{ end }}icon: plane-departure -meta: - - property: "og:description" - content: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." +{{ if env "DOCGEN_TARGET=ignore-prefix" }} +### {{ end }}description: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." --- {{ end }}

Language Tour

diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 3ac46fd78..4bdb0fa75 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index dd58e4877..dfe641df2 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 0e22428d4..3070612bf 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,9 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -#tag: -# - {{ md .CategoryID }} -{{ if .Related }}{{ range $i,$a := .Related }}{{ if gt $i 0 }}{{ end }} -# - {{ md .Hierarchy }}{{ end }} -{{ end }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: {{ .Summary }} --- {{ end }}# {{ md .Title }} From 1e298391562c521864fe95d7d88c6e734696d6c5 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 07:35:26 +0100 Subject: [PATCH 105/142] website: description / summary bugfix --- gen/integrations-md-doc.tmpl | 2 +- gen/root/README.inc.md | 2 +- gen/root/tour.inc.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 2f09f9d93..7e5969849 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: "{{ quote .Summary }}" --- {{ end }}# {{ md .Title }} diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index 73e3dea76..17d331769 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: A smarter shell and scripting environment with advanced features designed for usability, safety and productivity (eg smarter DevOps tooling) +description: "{{ quote .Summary }}" home: true icon: home heroImage: murex-logo-shell.svg?v={{ env "COMMITHASHSHORT" }} diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 60d47474d..9cab909c6 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -2,7 +2,7 @@ {{ if env "DOCGEN_TARGET=ignore-prefix" }} ### {{ end }}icon: plane-departure {{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}description: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." +### {{ end }}description: "{{ quote .Summary }}" --- {{ end }}

Language Tour

From 158196117491ec6ade34b6a4131a0da555e68edf Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 07:35:26 +0100 Subject: [PATCH 106/142] website: description / summary bugfix --- gen/integrations-md-doc.tmpl | 2 +- gen/root-md-doc.tmpl | 4 +++- gen/root/CONTRIBUTING.inc.md | 6 +----- gen/root/DOWNLOAD.inc.md | 6 +----- gen/root/INSTALL.inc.md | 6 +----- gen/root/README.inc.md | 1 - gen/root/compatibility.inc.md | 6 +----- gen/root/supported-platforms.inc.md | 5 +---- gen/root/tour.inc.md | 8 +------- 9 files changed, 10 insertions(+), 34 deletions(-) diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 2f09f9d93..7e5969849 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: "{{ quote .Summary }}" --- {{ end }}# {{ md .Title }} diff --git a/gen/root-md-doc.tmpl b/gen/root-md-doc.tmpl index 07a723c6a..5d1d3e780 100644 --- a/gen/root-md-doc.tmpl +++ b/gen/root-md-doc.tmpl @@ -1,4 +1,6 @@ -{{ md (include .Description) }}{{ if .Related }} +{{ if env "DOCGEN_TARGET=vuepress" }} +description: "{{ quote .Summary }}" +{{ end }}{{ md (include .Description) }}{{ if .Related }} ## See Also diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index b5e043c3d..46d4a3f76 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,8 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}icon: handshake-angle - ---- +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Contributing to Murex

Murex is community project. We gratefully accept contributions. diff --git a/gen/root/DOWNLOAD.inc.md b/gen/root/DOWNLOAD.inc.md index 8f6e9c28b..8f58d4a34 100644 --- a/gen/root/DOWNLOAD.inc.md +++ b/gen/root/DOWNLOAD.inc.md @@ -1,8 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}icon: terminal - ---- +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Download Murex

[![Version](version.svg)](DOWNLOAD.md) diff --git a/gen/root/INSTALL.inc.md b/gen/root/INSTALL.inc.md index 19831bcb8..de27309fa 100644 --- a/gen/root/INSTALL.inc.md +++ b/gen/root/INSTALL.inc.md @@ -1,8 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}icon: download - ---- +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Install Murex

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/README.inc.md b/gen/root/README.inc.md index 73e3dea76..e9f79565c 100644 --- a/gen/root/README.inc.md +++ b/gen/root/README.inc.md @@ -1,5 +1,4 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: A smarter shell and scripting environment with advanced features designed for usability, safety and productivity (eg smarter DevOps tooling) home: true icon: home heroImage: murex-logo-shell.svg?v={{ env "COMMITHASHSHORT" }} diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index 10b7805f6..9cf4342b4 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,8 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}icon: recycle - ---- +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Compatibility Commitment

Murex is committed to backwards compatibility. While we do want to continue to diff --git a/gen/root/supported-platforms.inc.md b/gen/root/supported-platforms.inc.md index 4b7e7c95e..8be47fc16 100644 --- a/gen/root/supported-platforms.inc.md +++ b/gen/root/supported-platforms.inc.md @@ -1,7 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} - ---- - +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Supported Operating Systems

The following is a list of platforms Murex has been tested on and the diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 60d47474d..01e22bc52 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -1,10 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}icon: plane-departure -{{ if env "DOCGEN_TARGET=ignore-prefix" }} -### {{ end }}description: "Murex's unique approach to type annotations means you have the safety and convenience of working with data formats besides just byte streams and string variables, while still having compatibility with every tool written for Linux and UNIX over the last 50 years." ---- - +{{ if env "DOCGEN_TARGET=vuepress" }}--- {{ end }}

Language Tour

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

From 3dc4b805bb957c80e0317b2465adf21df279a5b8 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 07:55:24 +0100 Subject: [PATCH 107/142] website: description quoting bugfix --- gen/apis-md-doc.tmpl | 2 +- gen/blog-md-doc.tmpl | 2 +- gen/changelog-md-doc.tmpl | 2 +- gen/commands-md-doc.tmpl | 2 +- gen/events-md-doc.tmpl | 2 +- gen/integrations-md-doc.tmpl | 2 +- gen/mkarray-md-doc.tmpl | 2 +- gen/parser-md-doc.tmpl | 2 +- gen/root-md-doc.tmpl | 2 +- gen/types-md-doc.tmpl | 2 +- gen/userguide-md-doc.tmpl | 2 +- gen/variables-md-doc.tmpl | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index cd878138a..22a10be06 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index 50b52ca2a..98e36e81b 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index 0534d8acc..4c5ec33a4 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index 41c1f3fc3..f603237c0 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index 30fa25675..42f04bda3 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 7e5969849..851dc5820 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: "{{ quote .Summary }}" +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index 7c32530ec..e3537c855 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index d9bb63200..8ba64c5b9 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/root-md-doc.tmpl b/gen/root-md-doc.tmpl index 5d1d3e780..f63a26493 100644 --- a/gen/root-md-doc.tmpl +++ b/gen/root-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: "{{ quote .Summary }}" +description: {{ quote .Summary }} {{ end }}{{ md (include .Description) }}{{ if .Related }} ## See Also diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 4bdb0fa75..1f7ecd6f5 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index dfe641df2..cc4861bfe 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 3070612bf..01dd5056e 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,5 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }} -description: {{ .Summary }} +description: {{ quote .Summary }} --- {{ end }}# {{ md .Title }} From 9cddc80cdfd52f6423697433699edf861fbeb01d Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:01:23 +0100 Subject: [PATCH 108/142] website: frontmatter bugfix --- gen/apis-md-doc.tmpl | 2 +- gen/blog-md-doc.tmpl | 2 +- gen/changelog-md-doc.tmpl | 2 +- gen/commands-md-doc.tmpl | 2 +- gen/events-md-doc.tmpl | 2 +- gen/integrations-md-doc.tmpl | 2 +- gen/mkarray-md-doc.tmpl | 2 +- gen/parser-md-doc.tmpl | 2 +- gen/root-md-doc.tmpl | 2 +- gen/types-md-doc.tmpl | 2 +- gen/userguide-md-doc.tmpl | 2 +- gen/variables-md-doc.tmpl | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index 22a10be06..284e6de14 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index 98e36e81b..a4d8638eb 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index 4c5ec33a4..fe95824fb 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index f603237c0..57a00e85b 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index 42f04bda3..1b5d3c9a6 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 851dc5820..c03cd4d82 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index e3537c855..5f91ba705 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 8ba64c5b9..7a50f6820 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/root-md-doc.tmpl b/gen/root-md-doc.tmpl index f63a26493..c7af26a46 100644 --- a/gen/root-md-doc.tmpl +++ b/gen/root-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} {{ end }}{{ md (include .Description) }}{{ if .Related }} diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 1f7ecd6f5..746a420e4 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index cc4861bfe..e1b8c49cf 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 01dd5056e..656639c97 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,4 +1,4 @@ -{{ if env "DOCGEN_TARGET=vuepress" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- description: {{ quote .Summary }} --- From 92ec40e5496e016127dbe8d36ea3d7a2c7414d05 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:14:14 +0100 Subject: [PATCH 109/142] website: restore missing page icons --- docs/parser/c-style-fun.md | 2 +- docs/user-guide/operators-and-tokens.md | 2 +- docs/user-guide/strict-types.md | 2 +- gen/root/CONTRIBUTING.inc.md | 1 + gen/root/INSTALL.inc.md | 1 + gen/root/README_doc.yaml | 2 +- gen/root/compatibility.inc.md | 1 + gen/root/tour_doc.yaml | 2 +- 8 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/parser/c-style-fun.md b/docs/parser/c-style-fun.md index 5374f63e4..346025d59 100644 --- a/docs/parser/c-style-fun.md +++ b/docs/parser/c-style-fun.md @@ -106,7 +106,7 @@ It is 23 o' clock * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): - Getting started with Murex + Getting started with Murex: a quick tour of the next generation of shell scripting * [Open File (`open`)](../commands/open.md): Open a file with a preferred handler * [Output String (`echo`)](../commands/out.md): diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index e8772bfea..d3d78abc9 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -288,7 +288,7 @@ characters have special meanings when escaped. * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): - Getting started with Murex + Getting started with Murex: a quick tour of the next generation of shell scripting
diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index 7953b76e7..06358b040 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -53,7 +53,7 @@ changing this option will not cause accidental side-effects in other functions. * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Language Tour](../Murex/tour.md): - Getting started with Murex + Getting started with Murex: a quick tour of the next generation of shell scripting * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Variable and Config Scoping](../user-guide/scoping.md): diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index 46d4a3f76..6251e6d1d 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: handshake-angle {{ end }}

Contributing to Murex

Murex is community project. We gratefully accept contributions. diff --git a/gen/root/INSTALL.inc.md b/gen/root/INSTALL.inc.md index de27309fa..ff35e4b98 100644 --- a/gen/root/INSTALL.inc.md +++ b/gen/root/INSTALL.inc.md @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: download {{ end }}

Install Murex

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/README_doc.yaml b/gen/root/README_doc.yaml index f0b5e136d..6b741bc12 100644 --- a/gen/root/README_doc.yaml +++ b/gen/root/README_doc.yaml @@ -3,7 +3,7 @@ Murex CategoryID: Murex Summary: - A smarter shell and scripting environment with advanced features designed for safety and productivity + A smarter $SHELL and scripting environment with advanced features designed for safety and productivity. Murex is a modern shell Description: |- {{ include "gen/root/README.inc.md" }} Synonyms: diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index 9cf4342b4..d16b02262 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: recycle {{ end }}

Compatibility Commitment

Murex is committed to backwards compatibility. While we do want to continue to diff --git a/gen/root/tour_doc.yaml b/gen/root/tour_doc.yaml index 162531177..8296d112e 100644 --- a/gen/root/tour_doc.yaml +++ b/gen/root/tour_doc.yaml @@ -4,7 +4,7 @@ Language Tour CategoryID: Murex Summary: >- - Getting started with Murex + Getting started with Murex: a quick tour of the next generation of shell scripting Description: |- {{ include "gen/root/tour.inc.md" }} Synonyms: From 6ccc811698d064f1976196e522b319aab9517b44 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:20:56 +0100 Subject: [PATCH 110/142] website: restore missing page icons (correctly) --- CONTRIBUTING.md | 1 + INSTALL.md | 1 + compatibility.md | 1 + gen/root/CONTRIBUTING.inc.md | 2 +- gen/root/INSTALL.inc.md | 2 +- gen/root/compatibility.inc.md | 2 +- 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92feb78eb..ead8319fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,4 @@ +

Contributing to Murex

Murex is community project. We gratefully accept contributions. diff --git a/INSTALL.md b/INSTALL.md index 422a7fe01..83f59f83b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,3 +1,4 @@ +

Install Murex

Table of Contents

diff --git a/compatibility.md b/compatibility.md index 167708654..7e8228728 100644 --- a/compatibility.md +++ b/compatibility.md @@ -1,3 +1,4 @@ +

Compatibility Commitment

Murex is committed to backwards compatibility. While we do want to continue to diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index 6251e6d1d..102d49f29 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,5 +1,5 @@ +{{ if env "DOCGEN_TARGET=vuepress" }}icon: handshake-angle{{ end }} {{ if env "DOCGEN_TARGET=vuepress" }}--- -icon: handshake-angle {{ end }}

Contributing to Murex

Murex is community project. We gratefully accept contributions. diff --git a/gen/root/INSTALL.inc.md b/gen/root/INSTALL.inc.md index ff35e4b98..7ba55a506 100644 --- a/gen/root/INSTALL.inc.md +++ b/gen/root/INSTALL.inc.md @@ -1,5 +1,5 @@ +{{ if env "DOCGEN_TARGET=vuepress" }}icon: download{{ end }} {{ if env "DOCGEN_TARGET=vuepress" }}--- -icon: download {{ end }}

Install Murex

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index d16b02262..e2957a952 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,5 +1,5 @@ +{{ if env "DOCGEN_TARGET=vuepress" }}icon: recycle{{ end }} {{ if env "DOCGEN_TARGET=vuepress" }}--- -icon: recycle {{ end }}

Compatibility Commitment

Murex is committed to backwards compatibility. While we do want to continue to From 830b5473edad9849006e0c7c1c6c4ef898787db4 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:28:35 +0100 Subject: [PATCH 111/142] website: updated titles --- CONTRIBUTING.md | 3 ++- DOWNLOAD.md | 5 +++-- INSTALL.md | 5 +++-- compatibility.md | 7 ++++--- docs/changelog/v5.2.md | 4 ++-- docs/changelog/v5.3.md | 2 +- docs/changelog/v6.0.md | 2 +- docs/changelog/v6.1.md | 2 +- docs/changelog/v6.2.md | 2 +- docs/supported-platforms.md | 7 ++++--- docs/tour.md | 5 +++-- gen/root/CONTRIBUTING.inc.md | 4 ++-- gen/root/CONTRIBUTING_doc.yaml | 2 +- gen/root/DOWNLOAD.inc.md | 4 ++-- gen/root/DOWNLOAD_doc.yaml | 2 +- gen/root/INSTALL.inc.md | 4 ++-- gen/root/INSTALL_doc.yaml | 2 +- gen/root/compatibility.inc.md | 4 ++-- gen/root/supported-platforms.inc.md | 4 ++-- gen/root/tour.inc.md | 4 ++-- 20 files changed, 40 insertions(+), 34 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ead8319fd..0ced38ac7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,6 @@ -

Contributing to Murex

+ +

Murex is community project. We gratefully accept contributions. diff --git a/DOWNLOAD.md b/DOWNLOAD.md index 7069ef660..baaf3e8c0 100644 --- a/DOWNLOAD.md +++ b/DOWNLOAD.md @@ -1,4 +1,5 @@ -

Download Murex

+ +

[![Version](version.svg)](DOWNLOAD.md) @@ -160,7 +161,7 @@ following site: [docs.microsoft.com/en-us/windows/wsl/install-win10](https://doc * [Compatibility Commitment](/compatibility.md): Murex is committed to excellent backwards compatibility * [Install](/INSTALL.md): - Installation instructions + Installation Instructions * [Supported Platforms](docs//supported-platforms.md): Operating systems and CPU architectures supported by Murex diff --git a/INSTALL.md b/INSTALL.md index 83f59f83b..4b102b668 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,5 +1,6 @@ -

Install Murex

+ +

Table of Contents

@@ -135,7 +136,7 @@ pretty well. So the overall experience is a clean and readable terminal. * [Compatibility Commitment](/compatibility.md): Murex is committed to excellent backwards compatibility -* [Download](/DOWNLOAD.md): +* [Download Links](/DOWNLOAD.md): Murex download links * [Supported Platforms](docs//supported-platforms.md): Operating systems and CPU architectures supported by Murex diff --git a/compatibility.md b/compatibility.md index 7e8228728..c0ae43dcb 100644 --- a/compatibility.md +++ b/compatibility.md @@ -1,5 +1,6 @@ -

Compatibility Commitment

+ +

Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term @@ -85,10 +86,10 @@ Murex releases roughly follows [semantic versioning](https://semver.org/). ## See Also -* [Contributing](/CONTRIBUTING.md): +* [Contributing To The Project](/CONTRIBUTING.md): Guide to contributing to Murex * [Install](/INSTALL.md): - Installation instructions + Installation Instructions
diff --git a/docs/changelog/v5.2.md b/docs/changelog/v5.2.md index bcd227086..29f1e3017 100644 --- a/docs/changelog/v5.2.md +++ b/docs/changelog/v5.2.md @@ -80,7 +80,7 @@ Published: 18.11.2023 at 20:59 * [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [Contributing](../Murex/CONTRIBUTING.md): +* [Contributing To The Project](../Murex/CONTRIBUTING.md): Guide to contributing to Murex * [Count (`count`)](../commands/count.md): Count items in a map, list or array @@ -89,7 +89,7 @@ Published: 18.11.2023 at 20:59 * [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground * [Install](../Murex/INSTALL.md): - Installation instructions + Installation Instructions * [Job Control](../user-guide/job-control.md): How to manage jobs with Murex * [Terminal Hotkeys](../user-guide/terminal-keys.md): diff --git a/docs/changelog/v5.3.md b/docs/changelog/v5.3.md index 188600191..13c2d63c8 100644 --- a/docs/changelog/v5.3.md +++ b/docs/changelog/v5.3.md @@ -89,7 +89,7 @@ Published: 02.01.2024 at 15:45 ## See Also -* [Contributing](../Murex/CONTRIBUTING.md): +* [Contributing To The Project](../Murex/CONTRIBUTING.md): Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/changelog/v6.0.md b/docs/changelog/v6.0.md index 2dd38426c..155c9e53e 100644 --- a/docs/changelog/v6.0.md +++ b/docs/changelog/v6.0.md @@ -44,7 +44,7 @@ Published: 17.02.2024 at 20:47 ## See Also -* [Contributing](../Murex/CONTRIBUTING.md): +* [Contributing To The Project](../Murex/CONTRIBUTING.md): Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index fd0584517..9453e4d90 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -148,7 +148,7 @@ Published: 17.06.2024 at 22:54 Returns character sequences for any key pressed (ie sent from the terminal) * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints -* [Contributing](../Murex/CONTRIBUTING.md): +* [Contributing To The Project](../Murex/CONTRIBUTING.md): Guide to contributing to Murex * [Date And Time Conversion (`datetime`)](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index fcc5c4f60..04f45efee 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -86,7 +86,7 @@ Published: 19.07.2024 at 08:54 * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints -* [Contributing](../Murex/CONTRIBUTING.md): +* [Contributing To The Project](../Murex/CONTRIBUTING.md): Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value diff --git a/docs/supported-platforms.md b/docs/supported-platforms.md index 5ce5425f4..056511683 100644 --- a/docs/supported-platforms.md +++ b/docs/supported-platforms.md @@ -1,4 +1,5 @@ -

Supported Operating Systems

+ +

The following is a list of platforms Murex has been tested on and the level of support it has: @@ -94,10 +95,10 @@ Several CPU architectures are supported: ## See Also -* [Download](/DOWNLOAD.md): +* [Download Links](/DOWNLOAD.md): Murex download links * [Install](/INSTALL.md): - Installation instructions + Installation Instructions
diff --git a/docs/tour.md b/docs/tour.md index c0f7ef95b..b2aff3df8 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -1,4 +1,5 @@ -

Language Tour

+ +

Table of Contents

@@ -602,7 +603,7 @@ This can be invoked by pressing `Ctrl` + `z`. ([read more](/docs/user-guide/job- ## See Also * [Install](/INSTALL.md): - Installation instructions + Installation Instructions * [Operators And Tokens](/operators-and-tokens.md): A table of all supported operators and tokens diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index 102d49f29..8827d0130 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}icon: handshake-angle{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Contributing to Murex

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

Murex is community project. We gratefully accept contributions. diff --git a/gen/root/CONTRIBUTING_doc.yaml b/gen/root/CONTRIBUTING_doc.yaml index 185d2e786..8166bec39 100644 --- a/gen/root/CONTRIBUTING_doc.yaml +++ b/gen/root/CONTRIBUTING_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: CONTRIBUTING Title: >- - Contributing + Contributing To The Project CategoryID: Murex Summary: >- Guide to contributing to Murex diff --git a/gen/root/DOWNLOAD.inc.md b/gen/root/DOWNLOAD.inc.md index 8f58d4a34..2cace425a 100644 --- a/gen/root/DOWNLOAD.inc.md +++ b/gen/root/DOWNLOAD.inc.md @@ -1,5 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Download Murex

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

[![Version](version.svg)](DOWNLOAD.md) diff --git a/gen/root/DOWNLOAD_doc.yaml b/gen/root/DOWNLOAD_doc.yaml index 7eae13679..6dbb447a3 100644 --- a/gen/root/DOWNLOAD_doc.yaml +++ b/gen/root/DOWNLOAD_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: DOWNLOAD Title: >- - Download + Download Links CategoryID: Murex Summary: >- Murex download links diff --git a/gen/root/INSTALL.inc.md b/gen/root/INSTALL.inc.md index 7ba55a506..2cf6ea73d 100644 --- a/gen/root/INSTALL.inc.md +++ b/gen/root/INSTALL.inc.md @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}icon: download{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Install Murex

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/INSTALL_doc.yaml b/gen/root/INSTALL_doc.yaml index b7f17486c..3aed48f74 100644 --- a/gen/root/INSTALL_doc.yaml +++ b/gen/root/INSTALL_doc.yaml @@ -3,7 +3,7 @@ Install CategoryID: Murex Summary: >- - Installation instructions + Installation Instructions Description: |- {{ include "gen/root/INSTALL.inc.md" }} Synonyms: diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index e2957a952..adf2f79fe 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}icon: recycle{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Compatibility Commitment

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term diff --git a/gen/root/supported-platforms.inc.md b/gen/root/supported-platforms.inc.md index 8be47fc16..fa826bfc0 100644 --- a/gen/root/supported-platforms.inc.md +++ b/gen/root/supported-platforms.inc.md @@ -1,5 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Supported Operating Systems

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

The following is a list of platforms Murex has been tested on and the level of support it has: diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index 01e22bc52..e5a45e14e 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -1,5 +1,5 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}--- -{{ end }}

Language Tour

+{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} +

{{ .Title }}

{{ if env "DOCGEN_TARGET=" }}

Table of Contents

From f458a76654780612505374d6482c8b44edd16588 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:37:43 +0100 Subject: [PATCH 112/142] website: contribute page error --- CONTRIBUTING.md | 4 +--- compatibility.md | 6 ++---- docs/changelog/v5.2.md | 4 ++-- docs/changelog/v5.3.md | 4 ++-- docs/changelog/v6.0.md | 4 ++-- docs/changelog/v6.1.md | 4 ++-- docs/changelog/v6.2.md | 4 ++-- gen/root/CONTRIBUTING.inc.md | 11 +++++++---- gen/root/CONTRIBUTING_doc.yaml | 4 ++-- gen/root/compatibility.inc.md | 9 ++++++--- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ced38ac7..0a0a2d760 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,6 @@ - -

-Murex is community project. We gratefully accept contributions. +>

Table of Contents

diff --git a/compatibility.md b/compatibility.md index c0ae43dcb..da71e4dd2 100644 --- a/compatibility.md +++ b/compatibility.md @@ -1,5 +1,3 @@ - -

Murex is committed to backwards compatibility. While we do want to continue to @@ -86,8 +84,8 @@ Murex releases roughly follows [semantic versioning](https://semver.org/). ## See Also -* [Contributing To The Project](/CONTRIBUTING.md): - Guide to contributing to Murex +* [How To Contribute](/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Install](/INSTALL.md): Installation Instructions diff --git a/docs/changelog/v5.2.md b/docs/changelog/v5.2.md index 29f1e3017..8787c798b 100644 --- a/docs/changelog/v5.2.md +++ b/docs/changelog/v5.2.md @@ -80,14 +80,14 @@ Published: 18.11.2023 at 20:59 * [Background Process (`bg`)](../commands/bg.md): Run processes in the background -* [Contributing To The Project](../Murex/CONTRIBUTING.md): - Guide to contributing to Murex * [Count (`count`)](../commands/count.md): Count items in a map, list or array * [Debugging Mode (`debug`)](../commands/debug.md): Debugging information * [Foreground Process (`fg`)](../commands/fg.md): Sends a background process into the foreground +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Install](../Murex/INSTALL.md): Installation Instructions * [Job Control](../user-guide/job-control.md): diff --git a/docs/changelog/v5.3.md b/docs/changelog/v5.3.md index 13c2d63c8..c7c76d025 100644 --- a/docs/changelog/v5.3.md +++ b/docs/changelog/v5.3.md @@ -89,10 +89,10 @@ Published: 02.01.2024 at 15:45 ## See Also -* [Contributing To The Project](../Murex/CONTRIBUTING.md): - Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined * [Shell Configuration And Settings (`config`)](../commands/config.md): diff --git a/docs/changelog/v6.0.md b/docs/changelog/v6.0.md index 155c9e53e..83f2a8acf 100644 --- a/docs/changelog/v6.0.md +++ b/docs/changelog/v6.0.md @@ -44,10 +44,10 @@ Published: 17.02.2024 at 20:47 ## See Also -* [Contributing To The Project](../Murex/CONTRIBUTING.md): - Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined * [Shell Configuration And Settings (`config`)](../commands/config.md): diff --git a/docs/changelog/v6.1.md b/docs/changelog/v6.1.md index 9453e4d90..c12ada36b 100644 --- a/docs/changelog/v6.1.md +++ b/docs/changelog/v6.1.md @@ -148,8 +148,6 @@ Published: 17.06.2024 at 22:54 Returns character sequences for any key pressed (ie sent from the terminal) * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints -* [Contributing To The Project](../Murex/CONTRIBUTING.md): - Guide to contributing to Murex * [Date And Time Conversion (`datetime`)](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) * [Debugging Mode (`debug`)](../commands/debug.md): @@ -158,6 +156,8 @@ Published: 17.06.2024 at 22:54 Creates a handler function for `open` * [Get Request (`get`)](../commands/get.md): Makes a standard HTTP request and returns the result as a JSON object +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Man-Page Summary (`man-summary`)](../commands/man-summary.md): diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 04f45efee..55995b400 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -86,12 +86,12 @@ Published: 19.07.2024 at 08:54 * [ChatGPT](../integrations/chatgpt.md): How to enable ChatGPT hints -* [Contributing To The Project](../Murex/CONTRIBUTING.md): - Guide to contributing to Murex * [Define Environmental Variable (`export`)](../commands/export.md): Define an environmental variable and set it's value * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions * [Murex Package Management (`murex-package`)](../commands/murex-package.md): Murex's package manager * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index 8827d0130..3d06ceb05 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,8 +1,11 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}icon: handshake-angle{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+{{ if env "DOCGEN_TARGET=vuepress" }} +icon: handshake-angle +title: {{ quote .Title }} -Murex is community project. We gratefully accept contributions. +--- +{{ else }}

{{ .Title }}

{{ end }} + +> {{ .Summary }} {{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/CONTRIBUTING_doc.yaml b/gen/root/CONTRIBUTING_doc.yaml index 8166bec39..a11269ae4 100644 --- a/gen/root/CONTRIBUTING_doc.yaml +++ b/gen/root/CONTRIBUTING_doc.yaml @@ -1,9 +1,9 @@ - DocumentID: CONTRIBUTING Title: >- - Contributing To The Project + How To Contribute CategoryID: Murex Summary: >- - Guide to contributing to Murex + Murex is community project. We gratefully accept contributions Description: |- {{ include "gen/root/CONTRIBUTING.inc.md" }} Synonyms: diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index adf2f79fe..b53c55236 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,6 +1,9 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}icon: recycle{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+{{ if env "DOCGEN_TARGET=vuepress" }} +icon: recycle +title: {{ quote .Title }} + +--- +{{ else }}

{{ .Title }}

{{ end }} Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term From f44e88c1996ae16fe12ec1db2b5becdaf51064f5 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 08:41:01 +0100 Subject: [PATCH 113/142] website: compatibility debug --- CONTRIBUTING.md | 5 +++-- DOWNLOAD.md | 2 +- INSTALL.md | 3 +-- compatibility.md | 3 ++- docs/supported-platforms.md | 3 ++- docs/tour.md | 2 +- gen/root/CONTRIBUTING.inc.md | 7 ++++--- gen/root/DOWNLOAD.inc.md | 8 ++++++-- gen/root/INSTALL.inc.md | 10 +++++++--- gen/root/compatibility.inc.md | 5 +++-- gen/root/supported-platforms.inc.md | 3 ++- gen/root/tour.inc.md | 8 ++++++-- utils/docgen/api/functions.go | 3 +++ 13 files changed, 41 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a0a2d760..ef54d93d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,7 @@ -

-> +

How To Contribute

+ +> Murex is community project. We gratefully accept contributions

Table of Contents

diff --git a/DOWNLOAD.md b/DOWNLOAD.md index baaf3e8c0..3a21cf037 100644 --- a/DOWNLOAD.md +++ b/DOWNLOAD.md @@ -1,5 +1,5 @@ -

+

Download Links

[![Version](version.svg)](DOWNLOAD.md) diff --git a/INSTALL.md b/INSTALL.md index 4b102b668..4b03cae4b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,6 +1,5 @@ - -

+

Install

Table of Contents

diff --git a/compatibility.md b/compatibility.md index da71e4dd2..71c7032d9 100644 --- a/compatibility.md +++ b/compatibility.md @@ -1,4 +1,5 @@ -

+ +

Compatibility Commitment

Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term diff --git a/docs/supported-platforms.md b/docs/supported-platforms.md index 056511683..035b91607 100644 --- a/docs/supported-platforms.md +++ b/docs/supported-platforms.md @@ -1,5 +1,6 @@ -

+ +

Supported Platforms

The following is a list of platforms Murex has been tested on and the level of support it has: diff --git a/docs/tour.md b/docs/tour.md index b2aff3df8..6339d7428 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -1,5 +1,5 @@ -

+

Language Tour

Table of Contents

diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index 3d06ceb05..bdbb8e55b 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -1,11 +1,12 @@ +{{ $doc := doct "" "CONTRIBUTING" }} {{ if env "DOCGEN_TARGET=vuepress" }} icon: handshake-angle -title: {{ quote .Title }} +title: {{ quote $doc.Title }} --- -{{ else }}

{{ .Title }}

{{ end }} +{{ else }}

{{ $doc.Title }}

{{ end }} -> {{ .Summary }} +> {{ $doc.Summary }} {{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/DOWNLOAD.inc.md b/gen/root/DOWNLOAD.inc.md index 2cace425a..56e76cca4 100644 --- a/gen/root/DOWNLOAD.inc.md +++ b/gen/root/DOWNLOAD.inc.md @@ -1,5 +1,9 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+{{ $doc := doct "" "DOWNLOAD" }} +{{ if env "DOCGEN_TARGET=vuepress" }} +title: {{ quote $doc.Title }} + +--- +{{ else }}

{{ $doc.Title }}

{{ end }} [![Version](version.svg)](DOWNLOAD.md) diff --git a/gen/root/INSTALL.inc.md b/gen/root/INSTALL.inc.md index 2cf6ea73d..776bef8c1 100644 --- a/gen/root/INSTALL.inc.md +++ b/gen/root/INSTALL.inc.md @@ -1,6 +1,10 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}icon: download{{ end }} -{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+{{ $doc := doct "" "INSTALL" }} +{{ if env "DOCGEN_TARGET=vuepress" }} +icon: download +title: {{ quote $doc.Title }} + +--- +{{ else }}

{{ $doc.Title }}

{{ end }} {{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/gen/root/compatibility.inc.md b/gen/root/compatibility.inc.md index b53c55236..432800247 100644 --- a/gen/root/compatibility.inc.md +++ b/gen/root/compatibility.inc.md @@ -1,9 +1,10 @@ +{{ $doc := doct "" "compatibility" }} {{ if env "DOCGEN_TARGET=vuepress" }} icon: recycle -title: {{ quote .Title }} +title: {{ quote $doc.Title }} --- -{{ else }}

{{ .Title }}

{{ end }} +{{ else }}

{{ $doc.Title }}

{{ end }} Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term diff --git a/gen/root/supported-platforms.inc.md b/gen/root/supported-platforms.inc.md index fa826bfc0..dd7e70edf 100644 --- a/gen/root/supported-platforms.inc.md +++ b/gen/root/supported-platforms.inc.md @@ -1,5 +1,6 @@ +{{ $doc := doct "" "supported-platforms" }} {{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+

{{ $doc.Title }}

The following is a list of platforms Murex has been tested on and the level of support it has: diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index e5a45e14e..a9ab076cc 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -1,5 +1,9 @@ -{{ if env "DOCGEN_TARGET=vuepress" }}---{{ end }} -

{{ .Title }}

+{{ $doc := doct "" "tour" }} +{{ if env "DOCGEN_TARGET=vuepress" }} +title: {{ quote $doc.Title }} + +--- +{{ else }}

{{ $doc.Title }}

{{ end }} {{ if env "DOCGEN_TARGET=" }}

Table of Contents

diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 1cd74b4cf..6c0b38589 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -261,6 +261,9 @@ func funcTime(dt time.Time) string { // Takes: string (category, document ID) // Returns: document type func funcDocT(cat, doc string) *document { + if cat == "" { + cat = "???" + } return Documents.ByID("!!!", cat, doc) } From 64e8be9aa19f7352c3c6bfec3e9f4cd907afbea0 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 17:18:41 +0100 Subject: [PATCH 114/142] website: default document icons --- DOWNLOAD.md | 8 +- builtins/core/datatools/alter_doc.yaml | 4 +- builtins/core/element/element_doc.yaml | 2 +- builtins/core/index/index_doc.yaml | 1 + builtins/core/io/file_doc.yaml | 2 +- builtins/core/pipe/namedpipe_doc.yaml | 2 + builtins/core/ranges/ranges_doc.yaml | 1 + builtins/core/typemgmt/types_doc.yaml | 2 +- builtins/docs/summaries.go | 2 +- docs/changelog/v2.5.md | 2 +- docs/changelog/v6.2.md | 2 +- docs/commands/README.md | 2 +- docs/commands/alter.md | 2 +- docs/commands/config.md | 2 +- docs/commands/map.md | 2 +- docs/commands/msort.md | 2 +- docs/integrations/iterm2.md | 2 + docs/integrations/kitty.md | 2 +- docs/integrations/spellcheck.md | 2 +- docs/parser/README.md | 30 +-- docs/parser/add-with.md | 2 +- docs/parser/addition.md | 2 +- docs/parser/assign-or-merge.md | 4 +- docs/parser/divide-by.md | 2 +- docs/parser/division.md | 2 +- docs/parser/elvis.md | 2 +- docs/parser/expr-inlined.md | 2 +- docs/parser/lambda.md | 2 +- docs/parser/multiplication.md | 2 +- docs/parser/multiply-by.md | 2 +- docs/parser/null-coalescing.md | 2 +- docs/parser/range.md | 2 +- docs/parser/subtract-by.md | 2 +- docs/parser/subtraction.md | 2 +- docs/tour.md | 2 +- docs/user-guide/README.md | 4 +- docs/user-guide/operators-and-tokens.md | 26 +-- gen/apis-md-doc.tmpl | 1 + gen/blog-md-doc.tmpl | 1 + gen/changelog-md-doc.tmpl | 1 + gen/commands-md-doc.tmpl | 1 + gen/docgen.yaml | 48 ++++- gen/events-md-doc.tmpl | 1 + gen/expr/add-with-op_doc.yaml | 1 + gen/expr/addition-op_doc.yaml | 1 + gen/expr/assign-merge-op_doc.yaml | 1 + gen/expr/divide-by-op_doc.yaml | 1 + gen/expr/division-op_doc.yaml | 1 + gen/expr/elvis-op_doc.yaml | 1 + gen/expr/multiplication-op_doc.yaml | 1 + gen/expr/multiply-by-op_doc.yaml | 1 + gen/expr/null-coalescing-op_doc.yaml | 1 + gen/expr/subtract-by-op_doc.yaml | 1 + gen/expr/subtraction-op_doc.yaml | 1 + gen/includes/expr-operators-tokens.inc.md | 24 +-- gen/integrations-md-doc.tmpl | 1 + gen/integrations/iterm2_doc.yaml | 2 + gen/integrations/kitty_doc.yaml | 2 +- gen/mkarray-md-doc.tmpl | 1 + gen/parser-md-cat.inc.md | 6 + gen/parser-md-doc.tmpl | 1 + gen/parser-vue-cat.tmpl | 1 + gen/parser/c-style-functions_doc.yaml | 1 + gen/parser/codeblock_doc.yaml | 1 + gen/parser/create_array_doc.yaml | 1 + gen/parser/create_object_doc.yaml | 1 + gen/parser/expr-inlined_doc.yaml | 1 + gen/parser/lambda_doc.yaml | 1 + gen/parser/logical_ops_doc.yaml | 2 + gen/parser/pipes_doc.yaml | 4 + gen/parser/quotes_doc.yaml | 3 + gen/parser/variables_doc.yaml | 3 + gen/root/DOWNLOAD.inc.md | 8 +- gen/types-md-doc.tmpl | 1 + gen/user-guide/operators-tokens_doc.yaml | 2 +- gen/userguide-md-doc.tmpl | 1 + gen/variables-md-doc.tmpl | 1 + gen/vuepress/commands_generated.json | 158 ++++++++++++++- gen/vuepress/parser_generated.json | 228 ++++++++++++++++++++++ gen/vuepress/sidebar.ts | 5 +- images/screenshot-iterm2-open.png | Bin 0 -> 430415 bytes utils/docgen/api/functions.go | 5 +- 82 files changed, 583 insertions(+), 82 deletions(-) create mode 100644 gen/parser-vue-cat.tmpl create mode 100644 gen/vuepress/parser_generated.json create mode 100644 images/screenshot-iterm2-open.png diff --git a/DOWNLOAD.md b/DOWNLOAD.md index 3a21cf037..6a2069f39 100644 --- a/DOWNLOAD.md +++ b/DOWNLOAD.md @@ -26,9 +26,11 @@ ## Download Links -Below are the instructions to download a pre-compiled binary via HTTPS. If you -wish to install from source or use your preferred package manager, then please -refer to the [INSTALL](INSTALL.md) page for further instructions. +Below are the instructions to download a pre-compiled binary via HTTPS. + +If you wish to install from source or use your preferred package manager, then +please refer to the [INSTALL](INSTALL.md) +page for further instructions. ### Darwin (macOS) diff --git a/builtins/core/datatools/alter_doc.yaml b/builtins/core/datatools/alter_doc.yaml index 1a87ac845..8881e66ed 100644 --- a/builtins/core/datatools/alter_doc.yaml +++ b/builtins/core/datatools/alter_doc.yaml @@ -1,8 +1,8 @@ - DocumentID: alter Title: >+ - Alter Data Structure (`alter`) + Alter Data Structure (`alter` / `~>`) CategoryID: commands - SubCategoryIDs: [ commands.struct ] + SubCategoryIDs: [ commands.struct, parser.data ] Summary: >- Change a value within a structured data-type and pass that change along the pipeline without altering the original source input diff --git a/builtins/core/element/element_doc.yaml b/builtins/core/element/element_doc.yaml index d233ac695..6b9b6377c 100644 --- a/builtins/core/element/element_doc.yaml +++ b/builtins/core/element/element_doc.yaml @@ -2,7 +2,7 @@ Title: >+ Get Nested Element (`[[ Element ]]`) CategoryID: parser - SubCategoryIDs: [ commands.struct ] + SubCategoryIDs: [ commands.struct, parser.data ] Summary: >- Outputs an element from a nested structure Description: |- diff --git a/builtins/core/index/index_doc.yaml b/builtins/core/index/index_doc.yaml index ba0d9be86..1961b39d3 100644 --- a/builtins/core/index/index_doc.yaml +++ b/builtins/core/index/index_doc.yaml @@ -5,6 +5,7 @@ SubCategoryIDs: - commands.struct - commands.list + - parser.data Summary: >- Outputs an element from an array, map or table Description: |- diff --git a/builtins/core/io/file_doc.yaml b/builtins/core/io/file_doc.yaml index 0e4797025..d0276b91e 100644 --- a/builtins/core/io/file_doc.yaml +++ b/builtins/core/io/file_doc.yaml @@ -2,7 +2,7 @@ Title: >+ Truncate File (`>`) CategoryID: parser - SubCategoryIDs: [ commands.fs ] + SubCategoryIDs: [ commands.fs, parser.pipes ] Summary: >- Writes stdin to disk - overwriting contents if file already exists Description: |- diff --git a/builtins/core/pipe/namedpipe_doc.yaml b/builtins/core/pipe/namedpipe_doc.yaml index d7a7fccbc..904e31834 100644 --- a/builtins/core/pipe/namedpipe_doc.yaml +++ b/builtins/core/pipe/namedpipe_doc.yaml @@ -4,6 +4,7 @@ CategoryID: parser SubCategoryIDs: - commands.io + - parser.pipes Summary: >- Reads from a Murex named pipe Description: |- @@ -57,6 +58,7 @@ CategoryID: parser SubCategoryIDs: - commands.io + - parser.pipes Summary: >- Read the stdin belonging to the parent code block Description: |- diff --git a/builtins/core/ranges/ranges_doc.yaml b/builtins/core/ranges/ranges_doc.yaml index e673825b0..a7767468c 100644 --- a/builtins/core/ranges/ranges_doc.yaml +++ b/builtins/core/ranges/ranges_doc.yaml @@ -4,6 +4,7 @@ CategoryID: parser SubCategoryIDs: - commands.list + - parser.data Summary: >- Outputs a ranged subset of data from stdin Description: |- diff --git a/builtins/core/typemgmt/types_doc.yaml b/builtins/core/typemgmt/types_doc.yaml index 5dd1f3a66..2ab9c666d 100644 --- a/builtins/core/typemgmt/types_doc.yaml +++ b/builtins/core/typemgmt/types_doc.yaml @@ -312,7 +312,7 @@ Title: >+ Define Type (`cast`) CategoryID: commands - SubCategoryIDs: [ commands.lang ] + SubCategoryIDs: [ commands.lang, parser.data, parser.pipes ] Summary: >- Alters the data-type of the previous function without altering its output Description: |- diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 6d19733c7..5c8cd8cd4 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -366,7 +366,7 @@ func init() { "user-guide/job-control": "How to manage jobs with Murex", "user-guide/modules": "An introduction to Murex modules and packages", "user-guide/namedpipes": "A detailed breakdown of named pipes in Murex", - "user-guide/operators-and-tokens": "A table of all supported operators and tokens", + "user-guide/operators-and-tokens": "All supported operators and tokens", "user-guide/pipeline": "Overview of what a \"pipeline\" is", "user-guide/profile": "A breakdown of the different files loaded on start up", "user-guide/reserved-vars": "Special variables reserved by Murex", diff --git a/docs/changelog/v2.5.md b/docs/changelog/v2.5.md index 71d37cb3c..6f863cda0 100644 --- a/docs/changelog/v2.5.md +++ b/docs/changelog/v2.5.md @@ -56,7 +56,7 @@ Published: 12.02.2022 at 16:16 ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Count (`count`)](../commands/count.md): Count items in a map, list or array diff --git a/docs/changelog/v6.2.md b/docs/changelog/v6.2.md index 55995b400..a10482f2f 100644 --- a/docs/changelog/v6.2.md +++ b/docs/changelog/v6.2.md @@ -97,7 +97,7 @@ Published: 19.07.2024 at 08:54 * [Murex's Offline Documentation (`murex-docs`)](../commands/murex-docs.md): Displays the man pages for Murex builtins * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens
diff --git a/docs/commands/README.md b/docs/commands/README.md index c3629367d..3f9145594 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -202,7 +202,7 @@ Commands for working with numerical data. Commands for working with structured data such as maps, tables, arrays and other data formats that are present in documents such as CSV, JSON, YAML, TOML, Sexpr, CSV, etc. -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Count (`count`)](../commands/count.md): Count items in a map, list or array diff --git a/docs/commands/alter.md b/docs/commands/alter.md index f2d74fc79..0b69be8e1 100644 --- a/docs/commands/alter.md +++ b/docs/commands/alter.md @@ -1,4 +1,4 @@ -# Alter Data Structure (`alter`) +# Alter Data Structure (`alter` / `~>`) > Change a value within a structured data-type and pass that change along the pipeline without altering the original source input diff --git a/docs/commands/config.md b/docs/commands/config.md index 67ab40d4a..2206b9751 100644 --- a/docs/commands/config.md +++ b/docs/commands/config.md @@ -235,7 +235,7 @@ This is executed when `autocomplete` is setting a value (eg `set`, `default`, ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/commands/map.md b/docs/commands/map.md index 207766673..6f457db64 100644 --- a/docs/commands/map.md +++ b/docs/commands/map.md @@ -32,7 +32,7 @@ map { code-block } { code-block } -> ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/commands/msort.md b/docs/commands/msort.md index 9fa0568b0..c74dc9a14 100644 --- a/docs/commands/msort.md +++ b/docs/commands/msort.md @@ -54,7 +54,7 @@ output of `msort` into another builtin: ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/integrations/iterm2.md b/docs/integrations/iterm2.md index e90c3cca7..04c2a40bc 100644 --- a/docs/integrations/iterm2.md +++ b/docs/integrations/iterm2.md @@ -24,6 +24,8 @@ For example: open https://murex.rocks/git-autocomplete.png ``` +![opening an image in Kitty](https://nojs.murex.rocks/images/screenshot-iterm2-open.png) + ## See Also * [Define Handlers For "`open`" (`openagent`)](../commands/openagent.md): diff --git a/docs/integrations/kitty.md b/docs/integrations/kitty.md index a7e7fa35a..4263e19ed 100644 --- a/docs/integrations/kitty.md +++ b/docs/integrations/kitty.md @@ -7,7 +7,7 @@ Kitty it a cross platform terminal emulator. It supports several ANSI escape codes that are bespoke to Kitty. -Murex can detect if it is running on Kitty and utilise those exclusive ANSI +Murex can detect if it is running on Kitty and utilize those exclusive ANSI escape codes, so you don't have to remember different ways of working with different terminal emulators. diff --git a/docs/integrations/spellcheck.md b/docs/integrations/spellcheck.md index 6bcc8325f..eb4f28713 100644 --- a/docs/integrations/spellcheck.md +++ b/docs/integrations/spellcheck.md @@ -157,7 +157,7 @@ and what the package names are for `aspell` and its corresponding dictionaries. * [ANSI Constants](../user-guide/ansi.md): Infixed constants that return ANSI escape sequences -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/parser/README.md b/docs/parser/README.md index 3971bbd4f..a58a56605 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -1,5 +1,11 @@ # Parser Reference + +--- +title: Operators And Tokens +description: "All supported operators and tokens" +--- +

Table of Contents

@@ -201,17 +207,18 @@ Sigils are supported in both expressions and statements. Constants are supported in both expressions and statements. However `null`, `true`, `false` and _number_ will all be interpreted as strings in statements. -| Token | Name | Operation | -|---------------|----------------|----------------------------------------------------| -| `null` | Null | `null` (null / nil / void) type | -| `true` | True | `bool` (boolean) true | -| `false` | False | `bool` (boolean) false | -| number | Number | `num` (numeric) value | -| `'`string`'` | String Literal | `str` (string) literal value | -| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | -| `%(`string`)` | String Builder | Creates a nestable `str` (string) | -| `%[`array`]` | Array Builder | Creates a `json` (JSON) array (list) | -| `%{`map`}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | +| Token | Name | Operation | +|----------------|----------------|----------------------------------------------------| +| `null` | Null | `null` (null / nil / void) type | +| `true` | True | `bool` (boolean) true | +| `false` | False | `bool` (boolean) false | +| number | Number | `num` (numeric) value | +| `'`string`'` | String Literal | `str` (string) literal value | +| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | +| `{` code `}` | Code Block | `str` (string) value, surrounded by curly braces | +| `%(` string `)`| String Builder | Creates a nestable `str` (string) | +| `%[` array `]` | Array Builder | Creates a `json` (JSON) array (list) | +| `%{` map `}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | Read more: * Operators: ['string'](/docs/parser/single-quote.md), ["string"](/docs/parser/double-quote.md), [%(string)](/docs/parser/brace-quote.md), [%[array]](/docs/parser/create-array.md), [%{map}](/docs/parser/create-object.md) @@ -228,6 +235,7 @@ expression or statement. Because of this they are supported in both. | `@{`command parameters...`}` | Sub-shell (array) | expand a command line as an array | | `(`expression`)` | Sub-expression | Inline an expression (_statement_) | | `(`expression`)` | Sub-expression | Order of evaluation (_expression_) | +| `[{` code block `}]` | Lambda | Run operations across lists / maps | Read more: * [C-style functions](/docs/parser/c-style-fun.md), [sub-shells](/docs/tour.md#sub-shells), [sub-expressions](/docs/parser/expr-inlined.md) diff --git a/docs/parser/add-with.md b/docs/parser/add-with.md index d4d459444..561266933 100644 --- a/docs/parser/add-with.md +++ b/docs/parser/add-with.md @@ -48,7 +48,7 @@ value op value**, for example: * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): diff --git a/docs/parser/addition.md b/docs/parser/addition.md index af8300004..8be009323 100644 --- a/docs/parser/addition.md +++ b/docs/parser/addition.md @@ -66,7 +66,7 @@ Error in `expr` (0,1): cannot Add with string types * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): diff --git a/docs/parser/assign-or-merge.md b/docs/parser/assign-or-merge.md index dbef191d4..71aca56b7 100644 --- a/docs/parser/assign-or-merge.md +++ b/docs/parser/assign-or-merge.md @@ -90,7 +90,7 @@ builtin. ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators @@ -99,7 +99,7 @@ builtin. * [Globbing (`g`)](../commands/g.md): Glob pattern matching for file system objects (eg `*.txt`) * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [`%[]` Array Builder](../parser/create-array.md): Quickly generate arrays diff --git a/docs/parser/divide-by.md b/docs/parser/divide-by.md index 865e880fd..5bb8f4b3e 100644 --- a/docs/parser/divide-by.md +++ b/docs/parser/divide-by.md @@ -48,7 +48,7 @@ value op value**, for example: * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): diff --git a/docs/parser/division.md b/docs/parser/division.md index ef35db1af..f097f9c1a 100644 --- a/docs/parser/division.md +++ b/docs/parser/division.md @@ -61,7 +61,7 @@ Error in `expr` (0,1): cannot Add with string types * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): diff --git a/docs/parser/elvis.md b/docs/parser/elvis.md index a9db05611..ea66ed4a0 100644 --- a/docs/parser/elvis.md +++ b/docs/parser/elvis.md @@ -54,7 +54,7 @@ where it says: * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character * [Pipe Fail (`trypipe`)](../commands/trypipe.md): diff --git a/docs/parser/expr-inlined.md b/docs/parser/expr-inlined.md index 8096d8952..a1d044d51 100644 --- a/docs/parser/expr-inlined.md +++ b/docs/parser/expr-inlined.md @@ -26,7 +26,7 @@ that parameter will be treated like a string. * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Output String (`echo`)](../commands/out.md): Print a string to the stdout with a trailing new line character diff --git a/docs/parser/lambda.md b/docs/parser/lambda.md index ec7d0b80c..da2fb7a33 100644 --- a/docs/parser/lambda.md +++ b/docs/parser/lambda.md @@ -181,7 +181,7 @@ The following meta values are defined: ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Date And Time Conversion (`datetime`)](../commands/datetime.md): A date and/or time conversion tool (like `printf` but for date and time values) diff --git a/docs/parser/multiplication.md b/docs/parser/multiplication.md index d49ed0480..74d6485e9 100644 --- a/docs/parser/multiplication.md +++ b/docs/parser/multiplication.md @@ -61,7 +61,7 @@ Error in `expr` (0,1): cannot Add with string types * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): diff --git a/docs/parser/multiply-by.md b/docs/parser/multiply-by.md index 44f2700c0..4a33adc66 100644 --- a/docs/parser/multiply-by.md +++ b/docs/parser/multiply-by.md @@ -48,7 +48,7 @@ value op value**, for example: * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [`*` Multiplication Operator](../parser/multiplication.md): diff --git a/docs/parser/null-coalescing.md b/docs/parser/null-coalescing.md index dbcc04812..467995d63 100644 --- a/docs/parser/null-coalescing.md +++ b/docs/parser/null-coalescing.md @@ -61,7 +61,7 @@ The following extract was taken from [Wikipedia](https://en.wikipedia.org/wiki/N * [Is Value Null (`is-null`)](../commands/is-null.md): Checks if a variable is null or undefined * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Output String (`out`)](../commands/out.md): Print a string to the stdout with a trailing new line character * [Pipe Fail (`trypipe`)](../commands/trypipe.md): diff --git a/docs/parser/range.md b/docs/parser/range.md index edd0bc456..01f9bcec8 100644 --- a/docs/parser/range.md +++ b/docs/parser/range.md @@ -96,7 +96,7 @@ December ## See Also -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/parser/subtract-by.md b/docs/parser/subtract-by.md index 6d31ea6b7..fb36e1e3d 100644 --- a/docs/parser/subtract-by.md +++ b/docs/parser/subtract-by.md @@ -48,7 +48,7 @@ value op value**, for example: * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [`*=` Multiply By Operator](../parser/multiply-by.md): diff --git a/docs/parser/subtraction.md b/docs/parser/subtraction.md index cdeafb7a1..e0f07458b 100644 --- a/docs/parser/subtraction.md +++ b/docs/parser/subtraction.md @@ -61,7 +61,7 @@ Error in `expr` (0,1): cannot Add with string types * [Expressions (`expr`)](../commands/expr.md): Expressions: mathematical, string comparisons, logical operators * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings * [Strict Types In Expressions](../user-guide/strict-types.md): diff --git a/docs/tour.md b/docs/tour.md index 6339d7428..09208bae2 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -605,7 +605,7 @@ This can be invoked by pressing `Ctrl` + `z`. ([read more](/docs/user-guide/job- * [Install](/INSTALL.md): Installation Instructions * [Operators And Tokens](/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens
diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index e6dc16d26..9f2289fe2 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -48,7 +48,7 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. * [Named Pipes](../user-guide/namedpipes.md): A detailed breakdown of named pipes in Murex * [Operators And Tokens](../user-guide/operators-and-tokens.md): - A table of all supported operators and tokens + All supported operators and tokens * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is * [Profile Files](../user-guide/profile.md): @@ -159,7 +159,7 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Prefix a string to every item in a list * [Alias Pointer (`alias`)](../commands/alias.md): Create an alias for a command -* [Alter Data Structure (`alter`)](../commands/alter.md): +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): Change a value within a structured data-type and pass that change along the pipeline without altering the original source input * [Append To List (`append`)](../commands/append.md): Add data to the end of an array diff --git a/docs/user-guide/operators-and-tokens.md b/docs/user-guide/operators-and-tokens.md index d3d78abc9..7efa4af6b 100644 --- a/docs/user-guide/operators-and-tokens.md +++ b/docs/user-guide/operators-and-tokens.md @@ -1,6 +1,6 @@ # Operators And Tokens -> A table of all supported operators and tokens +> All supported operators and tokens

Table of Contents

@@ -203,17 +203,18 @@ Sigils are supported in both expressions and statements. Constants are supported in both expressions and statements. However `null`, `true`, `false` and _number_ will all be interpreted as strings in statements. -| Token | Name | Operation | -|---------------|----------------|----------------------------------------------------| -| `null` | Null | `null` (null / nil / void) type | -| `true` | True | `bool` (boolean) true | -| `false` | False | `bool` (boolean) false | -| number | Number | `num` (numeric) value | -| `'`string`'` | String Literal | `str` (string) literal value | -| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | -| `%(`string`)` | String Builder | Creates a nestable `str` (string) | -| `%[`array`]` | Array Builder | Creates a `json` (JSON) array (list) | -| `%{`map`}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | +| Token | Name | Operation | +|----------------|----------------|----------------------------------------------------| +| `null` | Null | `null` (null / nil / void) type | +| `true` | True | `bool` (boolean) true | +| `false` | False | `bool` (boolean) false | +| number | Number | `num` (numeric) value | +| `'`string`'` | String Literal | `str` (string) literal value | +| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | +| `{` code `}` | Code Block | `str` (string) value, surrounded by curly braces | +| `%(` string `)`| String Builder | Creates a nestable `str` (string) | +| `%[` array `]` | Array Builder | Creates a `json` (JSON) array (list) | +| `%{` map `}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | Read more: * Operators: ['string'](/docs/parser/single-quote.md), ["string"](/docs/parser/double-quote.md), [%(string)](/docs/parser/brace-quote.md), [%[array]](/docs/parser/create-array.md), [%{map}](/docs/parser/create-object.md) @@ -230,6 +231,7 @@ expression or statement. Because of this they are supported in both. | `@{`command parameters...`}` | Sub-shell (array) | expand a command line as an array | | `(`expression`)` | Sub-expression | Inline an expression (_statement_) | | `(`expression`)` | Sub-expression | Order of evaluation (_expression_) | +| `[{` code block `}]` | Lambda | Run operations across lists / maps | Read more: * [C-style functions](/docs/parser/c-style-fun.md), [sub-shells](/docs/tour.md#sub-shells), [sub-expressions](/docs/parser/expr-inlined.md) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index 284e6de14..7d8374d95 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index a4d8638eb..79438e3cb 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-lines description: {{ quote .Summary }} --- diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index fe95824fb..f9ab845ec 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-lines description: {{ quote .Summary }} --- diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index 57a00e85b..7ab723281 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 7c8b2c917..4aa1211cb 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -71,7 +71,7 @@ Categories: Commands to manage the Murex shell session. - ID: commands.esc Title: String Escaping / Character Codes - VueIcon: file-code + VueIcon: code Description: |- Commands to escape special characters in various different string formats. - ID: commands.proc @@ -143,6 +143,52 @@ Categories: CategoryTemplate: gen/murex-md-cat.tmpl DocumentTemplate: gen/parser-md-doc.tmpl + - OutputPath: gen/vuepress + CategoryFile: parser_generated.json + CategoryTemplate: gen/parser-vue-cat.tmpl + + SubCategories: + - ID: parser.modifiers + Title: Modifiers + VueIcon: angles-right + Description: + - ID: parser.data + Title: Data Manipulation + VueIcon: angles-right + Description: + #- ID: parser.comparators + # Title: Comparators + # VueIcon: angles-right + # Description: + - ID: parser.assignment + Title: Assignment + VueIcon: angles-right + Description: + - ID: parser.conditionals + Title: Conditionals + VueIcon: angles-right + Description: + - ID: parser.sigils + Title: Sigils + VueIcon: angles-right + Description: + - ID: parser.constants + Title: Constants + VueIcon: angles-right + Description: + - ID: parser.subshells + Title: Sub-Shells + VueIcon: angles-right + Description: + - ID: parser.boolean + Title: Boolean Operations + VueIcon: angles-right + Description: + - ID: parser.pipes + Title: Pipes + VueIcon: angles-right + Description: + # events: - ID: events Title: events diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index 1b5d3c9a6..b3afb701a 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/expr/add-with-op_doc.yaml b/gen/expr/add-with-op_doc.yaml index 116bcfb95..773b0b4ea 100644 --- a/gen/expr/add-with-op_doc.yaml +++ b/gen/expr/add-with-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `+=` Add With Operator CategoryID: parser + SubCategoryIDs: [ parser.assignment ] Summary: >- Adds the right hand value to a variable (expression) Description: |- diff --git a/gen/expr/addition-op_doc.yaml b/gen/expr/addition-op_doc.yaml index 253b1809d..e0662aa7b 100644 --- a/gen/expr/addition-op_doc.yaml +++ b/gen/expr/addition-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `+` Addition Operator CategoryID: parser + SubCategoryIDs: [ parser.modifiers ] Summary: >- Adds two numeric values together (expression) Description: |- diff --git a/gen/expr/assign-merge-op_doc.yaml b/gen/expr/assign-merge-op_doc.yaml index 9291f2fa4..075dc0920 100644 --- a/gen/expr/assign-merge-op_doc.yaml +++ b/gen/expr/assign-merge-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `<~` Assign Or Merge CategoryID: parser + SubCategoryIDs: [ parser.assignment, parser.data ] Summary: >- Merges the right hand value to a variable on the left hand side (expression) Description: |- diff --git a/gen/expr/divide-by-op_doc.yaml b/gen/expr/divide-by-op_doc.yaml index 4b09ccbbd..bfde53133 100644 --- a/gen/expr/divide-by-op_doc.yaml +++ b/gen/expr/divide-by-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `/=` Divide By Operator CategoryID: parser + SubCategoryIDs: [ parser.assignment ] Summary: >- Divides a variable by the right hand value (expression) Description: |- diff --git a/gen/expr/division-op_doc.yaml b/gen/expr/division-op_doc.yaml index b98f674af..8b510ce3e 100644 --- a/gen/expr/division-op_doc.yaml +++ b/gen/expr/division-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `/` Division Operator CategoryID: parser + SubCategoryIDs: [ parser.modifiers ] Summary: >- Divides one numeric value from another (expression) Description: |- diff --git a/gen/expr/elvis-op_doc.yaml b/gen/expr/elvis-op_doc.yaml index 06f325df6..49a3ca92b 100644 --- a/gen/expr/elvis-op_doc.yaml +++ b/gen/expr/elvis-op_doc.yaml @@ -1,6 +1,7 @@ - DocumentID: elvis Title: >- `?:` Elvis Operator + SubCategoryIDs: [ parser.conditionals ] CategoryID: parser Summary: >- Returns the right operand if the left operand is falsy (expression) diff --git a/gen/expr/multiplication-op_doc.yaml b/gen/expr/multiplication-op_doc.yaml index 766b6dc81..eff2dfbe1 100644 --- a/gen/expr/multiplication-op_doc.yaml +++ b/gen/expr/multiplication-op_doc.yaml @@ -1,6 +1,7 @@ - DocumentID: multiplication Title: >- `*` Multiplication Operator + SubCategoryIDs: [ parser.modifiers ] CategoryID: parser Summary: >- Multiplies one numeric value with another (expression) diff --git a/gen/expr/multiply-by-op_doc.yaml b/gen/expr/multiply-by-op_doc.yaml index 1c88e8f09..5363c9742 100644 --- a/gen/expr/multiply-by-op_doc.yaml +++ b/gen/expr/multiply-by-op_doc.yaml @@ -1,6 +1,7 @@ - DocumentID: multiply-by Title: >- `*=` Multiply By Operator + SubCategoryIDs: [ parser.assignment ] CategoryID: parser Summary: >- Multiplies a variable by the right hand value (expression) diff --git a/gen/expr/null-coalescing-op_doc.yaml b/gen/expr/null-coalescing-op_doc.yaml index 6432a254c..872f86c19 100644 --- a/gen/expr/null-coalescing-op_doc.yaml +++ b/gen/expr/null-coalescing-op_doc.yaml @@ -1,6 +1,7 @@ - DocumentID: null-coalescing Title: >- `??` Null Coalescing Operator + SubCategoryIDs: [ parser.conditionals ] CategoryID: parser Summary: >- Returns the right operand if the left operand is empty / undefined (expression) diff --git a/gen/expr/subtract-by-op_doc.yaml b/gen/expr/subtract-by-op_doc.yaml index 009b72ad3..40ab74ddf 100644 --- a/gen/expr/subtract-by-op_doc.yaml +++ b/gen/expr/subtract-by-op_doc.yaml @@ -1,6 +1,7 @@ - DocumentID: subtract-by Title: >- `-=` Subtract By Operator + SubCategoryIDs: [ parser.assignment ] CategoryID: parser Summary: >- Subtracts a variable by the right hand value (expression) diff --git a/gen/expr/subtraction-op_doc.yaml b/gen/expr/subtraction-op_doc.yaml index e0f704d62..8602f56a4 100644 --- a/gen/expr/subtraction-op_doc.yaml +++ b/gen/expr/subtraction-op_doc.yaml @@ -2,6 +2,7 @@ Title: >- `-` Subtraction Operator CategoryID: parser + SubCategoryIDs: [ parser.modifiers ] Summary: >- Subtracts one numeric value from another (expression) Description: |- diff --git a/gen/includes/expr-operators-tokens.inc.md b/gen/includes/expr-operators-tokens.inc.md index c66c37ac9..24cd46cd0 100644 --- a/gen/includes/expr-operators-tokens.inc.md +++ b/gen/includes/expr-operators-tokens.inc.md @@ -199,17 +199,18 @@ Sigils are supported in both expressions and statements. Constants are supported in both expressions and statements. However `null`, `true`, `false` and _number_ will all be interpreted as strings in statements. -| Token | Name | Operation | -|---------------|----------------|----------------------------------------------------| -| `null` | Null | `null` (null / nil / void) type | -| `true` | True | `bool` (boolean) true | -| `false` | False | `bool` (boolean) false | -| number | Number | `num` (numeric) value | -| `'`string`'` | String Literal | `str` (string) literal value | -| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | -| `%(`string`)` | String Builder | Creates a nestable `str` (string) | -| `%[`array`]` | Array Builder | Creates a `json` (JSON) array (list) | -| `%{`map`}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | +| Token | Name | Operation | +|----------------|----------------|----------------------------------------------------| +| `null` | Null | `null` (null / nil / void) type | +| `true` | True | `bool` (boolean) true | +| `false` | False | `bool` (boolean) false | +| number | Number | `num` (numeric) value | +| `'`string`'` | String Literal | `str` (string) literal value | +| `"`string`"` | Infix String | `str` (string) value, supports escaping & infixing | +| `{` code `}` | Code Block | `str` (string) value, surrounded by curly braces | +| `%(` string `)`| String Builder | Creates a nestable `str` (string) | +| `%[` array `]` | Array Builder | Creates a `json` (JSON) array (list) | +| `%{` map `}` | Object Builder | Creates a `json` (JSON) object (map / dictionary) | Read more: * Operators: {{link "'string'" "single-quote"}}, {{link "\"string\"" "double-quote"}}, {{link "%(string)" "brace-quote"}}, {{link "%[array]" "create-array"}}, {{link "%{map}" "create-object"}} @@ -226,6 +227,7 @@ expression or statement. Because of this they are supported in both. | `@{`command parameters...`}` | Sub-shell (array) | expand a command line as an array | | `(`expression`)` | Sub-expression | Inline an expression (_statement_) | | `(`expression`)` | Sub-expression | Order of evaluation (_expression_) | +| `[{` code block `}]` | Lambda | Run operations across lists / maps | Read more: * {{link "C-style functions" "c-style-fun"}}, {{bookmark "sub-shells" "tour" "sub-shells"}}, {{link "sub-expressions" "expr-inlined"}} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index c03cd4d82..84aec62bc 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-lines description: {{ quote .Summary }} --- diff --git a/gen/integrations/iterm2_doc.yaml b/gen/integrations/iterm2_doc.yaml index 06bc77b14..510edc4b6 100644 --- a/gen/integrations/iterm2_doc.yaml +++ b/gen/integrations/iterm2_doc.yaml @@ -26,6 +26,8 @@ ``` open https://murex.rocks/git-autocomplete.png ``` + + ![opening an image in Kitty](https://nojs.murex.rocks/images/screenshot-iterm2-open.png) Synonyms: Related: - open diff --git a/gen/integrations/kitty_doc.yaml b/gen/integrations/kitty_doc.yaml index b43ba3558..45d035948 100644 --- a/gen/integrations/kitty_doc.yaml +++ b/gen/integrations/kitty_doc.yaml @@ -10,7 +10,7 @@ Kitty it a cross platform terminal emulator. It supports several ANSI escape codes that are bespoke to Kitty. - Murex can detect if it is running on Kitty and utilise those exclusive ANSI + Murex can detect if it is running on Kitty and utilize those exclusive ANSI escape codes, so you don't have to remember different ways of working with different terminal emulators. diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index 5f91ba705..29d1e732a 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/parser-md-cat.inc.md b/gen/parser-md-cat.inc.md index 268419ce8..7c146568a 100644 --- a/gen/parser-md-cat.inc.md +++ b/gen/parser-md-cat.inc.md @@ -1,3 +1,9 @@ +{{ $doc := doct "" "operators-and-tokens" }} +--- +title: {{ $doc.Title }} +description: {{ quote $doc.Summary }} +--- + {{ fn (file "gen/includes/expr-operators-tokens.inc.md") }} ## Other Reference Material diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 7a50f6820..63206725a 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/parser-vue-cat.tmpl b/gen/parser-vue-cat.tmpl new file mode 100644 index 000000000..740e4b20d --- /dev/null +++ b/gen/parser-vue-cat.tmpl @@ -0,0 +1 @@ +{{ vuepressmenu "parser" }} \ No newline at end of file diff --git a/gen/parser/c-style-functions_doc.yaml b/gen/parser/c-style-functions_doc.yaml index 30fa30bed..5bb52e49c 100644 --- a/gen/parser/c-style-functions_doc.yaml +++ b/gen/parser/c-style-functions_doc.yaml @@ -2,6 +2,7 @@ Title: >- C-style functions CategoryID: parser + SubCategoryIDs: [ parser.subshells ] Summary: >- Inlined commands for expressions and statements Description: |- diff --git a/gen/parser/codeblock_doc.yaml b/gen/parser/codeblock_doc.yaml index e380e4487..fb6ff659c 100644 --- a/gen/parser/codeblock_doc.yaml +++ b/gen/parser/codeblock_doc.yaml @@ -2,6 +2,7 @@ Title: >- `{ Curly Brace }` CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Initiates or terminates a code block Description: |- diff --git a/gen/parser/create_array_doc.yaml b/gen/parser/create_array_doc.yaml index 5be47fae8..611889987 100644 --- a/gen/parser/create_array_doc.yaml +++ b/gen/parser/create_array_doc.yaml @@ -2,6 +2,7 @@ Title: >- `%[]` Array Builder CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Quickly generate arrays Description: |- diff --git a/gen/parser/create_object_doc.yaml b/gen/parser/create_object_doc.yaml index a5eef7155..a0fa091d5 100644 --- a/gen/parser/create_object_doc.yaml +++ b/gen/parser/create_object_doc.yaml @@ -2,6 +2,7 @@ Title: >- `%{}` Object Builder CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Quickly generate objects (dictionaries / maps) Description: |- diff --git a/gen/parser/expr-inlined_doc.yaml b/gen/parser/expr-inlined_doc.yaml index d9cc8bb76..14cc0eb7f 100644 --- a/gen/parser/expr-inlined_doc.yaml +++ b/gen/parser/expr-inlined_doc.yaml @@ -2,6 +2,7 @@ Title: >- ( expression ) CategoryID: parser + SubCategoryIDs: [ parser.subshells ] Summary: >- Inline expressions Description: |- diff --git a/gen/parser/lambda_doc.yaml b/gen/parser/lambda_doc.yaml index 19b68ca37..9d1c7ce90 100644 --- a/gen/parser/lambda_doc.yaml +++ b/gen/parser/lambda_doc.yaml @@ -2,6 +2,7 @@ Title: >- `[{ Lambda }]` CategoryID: parser + SubCategoryIDs: [ parser.subshells ] Summary: >- Iterate through structured data Description: |- diff --git a/gen/parser/logical_ops_doc.yaml b/gen/parser/logical_ops_doc.yaml index 872d88cdc..ae7413a8c 100644 --- a/gen/parser/logical_ops_doc.yaml +++ b/gen/parser/logical_ops_doc.yaml @@ -2,6 +2,7 @@ Title: >- `&&` And Logical Operator CategoryID: parser + SubCategoryIDs: [ parser.boolean ] Summary: >- Continues next operation if previous operation passes Description: |- @@ -56,6 +57,7 @@ Title: >- `||` Or Logical Operator CategoryID: parser + SubCategoryIDs: [ parser.boolean ] Summary: >- Continues next operation only if previous operation fails Description: |- diff --git a/gen/parser/pipes_doc.yaml b/gen/parser/pipes_doc.yaml index f43d94abe..1c7d331c7 100644 --- a/gen/parser/pipes_doc.yaml +++ b/gen/parser/pipes_doc.yaml @@ -2,6 +2,7 @@ Title: >- `->` Arrow Pipe CategoryID: parser + SubCategoryIDs: [ parser.pipes ] Summary: >- Pipes stdout from the left hand command to stdin of the right hand command Description: |- @@ -110,6 +111,7 @@ Title: >- `=>` Generic Pipe CategoryID: parser + SubCategoryIDs: [ parser.pipes ] Summary: >- Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command @@ -167,6 +169,7 @@ Title: >- `|` POSIX Pipe CategoryID: parser + SubCategoryIDs: [ parser.pipes ] Summary: >- Pipes stdout from the left hand command to stdin of the right hand command Description: |- @@ -224,6 +227,7 @@ Title: >- `>>` Append File CategoryID: parser + SubCategoryIDs: [ parser.pipes ] Summary: >- Writes stdin to disk - appending contents if file already exists Description: |- diff --git a/gen/parser/quotes_doc.yaml b/gen/parser/quotes_doc.yaml index 81b090f0a..138206b31 100644 --- a/gen/parser/quotes_doc.yaml +++ b/gen/parser/quotes_doc.yaml @@ -2,6 +2,7 @@ Title: >- `'Single Quote'` CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Initiates or terminates a string (variables not expanded) Description: |- @@ -43,6 +44,7 @@ Title: >- `"Double Quote"` CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Initiates or terminates a string (variables expanded) Description: |- @@ -85,6 +87,7 @@ Title: >- `%(Brace Quote)` CategoryID: parser + SubCategoryIDs: [ parser.constants ] Summary: >- Initiates or terminates a string (variables expanded) Description: |- diff --git a/gen/parser/variables_doc.yaml b/gen/parser/variables_doc.yaml index ee6e30725..2bcf81d61 100644 --- a/gen/parser/variables_doc.yaml +++ b/gen/parser/variables_doc.yaml @@ -2,6 +2,7 @@ Title: >- `$Scalar` Sigil (eg variables) CategoryID: parser + SubCategoryIDs: [ parser.sigils ] Summary: >- Expand values as a scalar Description: |- @@ -89,6 +90,7 @@ Title: >- `@Array` Sigil CategoryID: parser + SubCategoryIDs: [ parser.sigils ] Summary: >- Expand values as an array Description: |- @@ -132,6 +134,7 @@ Title: >- `~` Home Sigil CategoryID: parser + SubCategoryIDs: [ parser.sigils ] Summary: >- Home directory path variable Description: |- diff --git a/gen/root/DOWNLOAD.inc.md b/gen/root/DOWNLOAD.inc.md index 56e76cca4..4dbb8378c 100644 --- a/gen/root/DOWNLOAD.inc.md +++ b/gen/root/DOWNLOAD.inc.md @@ -30,9 +30,11 @@ title: {{ quote $doc.Title }} {{ end }} ## Download Links -Below are the instructions to download a pre-compiled binary via HTTPS. If you -wish to install from source or use your preferred package manager, then please -refer to the {{ if env "DOCGEN_TARGET=vuepress" }}[install](install.md){{ else }}[INSTALL](INSTALL.md){{ end }} page for further instructions. +Below are the instructions to download a pre-compiled binary via HTTPS. + +If you wish to install from source or use your preferred package manager, then +please refer to the {{ if env "DOCGEN_TARGET=vuepress" }}[install](install.md){{ else }}[INSTALL](INSTALL.md){{ end }} +page for further instructions. ### Darwin (macOS) diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 746a420e4..659ef7b9e 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/user-guide/operators-tokens_doc.yaml b/gen/user-guide/operators-tokens_doc.yaml index 88104744f..9284b8787 100644 --- a/gen/user-guide/operators-tokens_doc.yaml +++ b/gen/user-guide/operators-tokens_doc.yaml @@ -3,7 +3,7 @@ Operators And Tokens CategoryID: user-guide Summary: >- - A table of all supported operators and tokens + All supported operators and tokens Description: |- {{ include "gen/includes/expr-operators-tokens.inc.md" }} Synonyms: diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index e1b8c49cf..f8f35fd54 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-lines description: {{ quote .Summary }} --- diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 656639c97..babaddde1 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,4 +1,5 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- +icon: file-code description: {{ quote .Summary }} --- diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 23cf8afb4..e6dcde222 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -2,46 +2,57 @@ { "children": [ { + "icon": "file-code", "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" }, { + "icon": "file-code", "link": "commands/err.html", "text": "Error String (err)" }, { + "icon": "file-code", "link": "commands/pt.html", "text": "Get Pipe Status (pt)" }, { + "icon": "file-code", "link": "commands/out.html", "text": "Output String (out)" }, { + "icon": "file-code", "link": "commands/tout.html", "text": "Output With Type Annotation (tout)" }, { + "icon": "file-code", "link": "parser/namedpipe.html", "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { + "icon": "file-code", "link": "parser/stdin.html", "text": "Read From Stdin (\u003cstdin\u003e)" }, { + "icon": "file-code", "link": "commands/read.html", "text": "Read User Input (read)" }, { + "icon": "file-code", "link": "commands/tread.html", "text": "Read With Type (tread) (removed 7.x)" }, { + "icon": "file-code", "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" }, { + "icon": "file-code", "link": "parser/brace-quote-func.html", "text": "(brace quote)" } @@ -53,34 +64,42 @@ { "children": [ { + "icon": "file-code", "link": "commands/tmp.html", "text": "Create Temporary File (tmp)" }, { + "icon": "file-code", "link": "commands/g.html", "text": "Globbing (g)" }, { + "icon": "file-code", "link": "commands/f.html", "text": "List Filesystem Objects (f)" }, { + "icon": "file-code", "link": "commands/lockfile.html", "text": "Lock Files (lockfile)" }, { + "icon": "file-code", "link": "commands/open.html", "text": "Open File (open)" }, { + "icon": "file-code", "link": "commands/rx.html", "text": "Regex Matches (rx)" }, { + "icon": "file-code", "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" }, { + "icon": "file-code", "link": "parser/file-truncate.html", "text": "Truncate File (\u003e)" } @@ -92,42 +111,52 @@ { "children": [ { + "icon": "file-code", "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { + "icon": "file-code", "link": "commands/cd.html", "text": "Change Directory (cd)" }, { + "icon": "file-code", "link": "commands/type.html", "text": "Display Command Type (type)" }, { + "icon": "file-code", "link": "commands/expr.html", "text": "Expressions (expr)" }, { + "icon": "file-code", "link": "commands/false.html", "text": "False (false)" }, { + "icon": "file-code", "link": "commands/which.html", "text": "Location Of Command (which)" }, { + "icon": "file-code", "link": "commands/out.html", "text": "Output String (out)" }, { + "icon": "file-code", "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { + "icon": "file-code", "link": "commands/read.html", "text": "Read User Input (read)" }, { + "icon": "file-code", "link": "commands/true.html", "text": "True (true)" } @@ -139,82 +168,102 @@ { "children": [ { + "icon": "file-code", "link": "commands/prefix.html", "text": "Add Prefix (prefix)" }, { + "icon": "file-code", "link": "commands/suffix.html", "text": "Add Suffix (suffix)" }, { + "icon": "file-code", "link": "commands/append.html", "text": "Append To List (append)" }, { + "icon": "file-code", "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { + "icon": "file-code", "link": "commands/count.html", "text": "Count (count)" }, { + "icon": "file-code", "link": "commands/ja.html", "text": "Create JSON Array (ja)" }, { + "icon": "file-code", "link": "commands/ta.html", "text": "Create New Array (ta)" }, { + "icon": "file-code", "link": "parser/range.html", "text": "Filter By Range [ ..Range ]" }, { + "icon": "file-code", "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { + "icon": "file-code", "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { + "icon": "file-code", "link": "commands/mjoin.html", "text": "Join Array To String (mjoin)" }, { + "icon": "file-code", "link": "commands/left.html", "text": "Left Sub-String (left)" }, { + "icon": "file-code", "link": "commands/match.html", "text": "Match String (match)" }, { + "icon": "file-code", "link": "commands/prepend.html", "text": "Prepend To List (prepend)" }, { + "icon": "file-code", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { + "icon": "file-code", "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { + "icon": "file-code", "link": "commands/mtac.html", "text": "Reverse Array (mtac)" }, { + "icon": "file-code", "link": "commands/right.html", "text": "Right Sub-String (right)" }, { + "icon": "file-code", "link": "commands/msort.html", "text": "Sort Array (msort)" }, { + "icon": "file-code", "link": "commands/a.html", "text": "Stream New List (a)" } @@ -226,54 +275,67 @@ { "children": [ { + "icon": "file-code", "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { + "icon": "file-code", "link": "commands/datetime.html", "text": "Date And Time Conversion (datetime)" }, { + "icon": "file-code", "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { + "icon": "file-code", "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { + "icon": "file-code", "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { + "icon": "file-code", "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { + "icon": "file-code", "link": "commands/left.html", "text": "Left Sub-String (left)" }, { + "icon": "file-code", "link": "commands/pretty.html", "text": "Prettify JSON" }, { + "icon": "file-code", "link": "commands/escape.html", "text": "Quote String (escape)" }, { + "icon": "file-code", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { + "icon": "file-code", "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { + "icon": "file-code", "link": "commands/right.html", "text": "Right Sub-String (right)" }, { + "icon": "file-code", "link": "commands/jsplit.html", "text": "Split String (jsplit)" } @@ -285,14 +347,17 @@ { "children": [ { + "icon": "file-code", "link": "commands/expr.html", "text": "Expressions (expr)" }, { + "icon": "file-code", "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { + "icon": "file-code", "link": "commands/round.html", "text": "Round Number (round)" } @@ -304,42 +369,52 @@ { "children": [ { + "icon": "file-code", "link": "commands/alter.html", - "text": "Alter Data Structure (alter)" + "text": "Alter Data Structure (alter / ~\u003e)" }, { + "icon": "file-code", "link": "commands/count.html", "text": "Count (count)" }, { + "icon": "file-code", "link": "commands/2darray.html", "text": "Create 2d Array (2darray)" }, { + "icon": "file-code", "link": "commands/map.html", "text": "Create Map (map)" }, { + "icon": "file-code", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { + "icon": "file-code", "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { + "icon": "file-code", "link": "parser/element.html", "text": "Get Nested Element ([[ Element ]])" }, { + "icon": "file-code", "link": "commands/struct-keys.html", "text": "Print Map / Structure Keys (struct-keys)" }, { + "icon": "file-code", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { + "icon": "file-code", "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" } @@ -351,22 +426,27 @@ { "children": [ { + "icon": "file-code", "link": "commands/addheading.html", "text": "Add Heading (addheading)" }, { + "icon": "file-code", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { + "icon": "file-code", "link": "optional/select.html", "text": "Inline SQL (select)" }, { + "icon": "file-code", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { + "icon": "file-code", "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" } @@ -378,18 +458,22 @@ { "children": [ { + "icon": "file-code", "link": "commands/cpuarch.html", "text": "CPU Architecture (cpuarch)" }, { + "icon": "file-code", "link": "commands/cpucount.html", "text": "CPU Count (cpucount)" }, { + "icon": "file-code", "link": "commands/export.html", "text": "Define Environmental Variable (export)" }, { + "icon": "file-code", "link": "commands/os.html", "text": "Operating System (os)" } @@ -401,78 +485,97 @@ { "children": [ { + "icon": "file-code", "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { + "icon": "file-code", "link": "commands/history.html", "text": "Command Line History (history)" }, { + "icon": "file-code", "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" }, { + "icon": "file-code", "link": "commands/debug.html", "text": "Debugging Mode (debug)" }, { + "icon": "file-code", "link": "commands/openagent.html", "text": "Define Handlers For \"open\" (openagent)" }, { + "icon": "file-code", "link": "commands/method.html", "text": "Define Method Relationships (method)" }, { + "icon": "file-code", "link": "commands/fexec.html", "text": "Execute Shell Function or Builtin (fexec)" }, { + "icon": "file-code", "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { + "icon": "file-code", "link": "commands/event.html", "text": "Murex Event Subsystem (event)" }, { + "icon": "file-code", "link": "commands/murex-package.html", "text": "Murex Package Management (murex-package)" }, { + "icon": "file-code", "link": "commands/version.html", "text": "Murex Version (version)" }, { + "icon": "file-code", "link": "commands/private.html", "text": "Private Function (private)" }, { + "icon": "file-code", "link": "commands/function.html", "text": "Public Function (function)" }, { + "icon": "file-code", "link": "commands/murex-update-exe-list.html", "text": "Re-Scan $PATH For Executables" }, { + "icon": "file-code", "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" }, { + "icon": "file-code", "link": "commands/config.html", "text": "Shell Configuration And Settings (config)" }, { + "icon": "file-code", "link": "commands/runtime.html", "text": "Shell Runtime (runtime)" }, { + "icon": "file-code", "link": "commands/test.html", "text": "Shell Script Tests (test)" }, { + "icon": "file-code", "link": "commands/autocomplete.html", "text": "Tab Autocompletion (autocomplete)" } @@ -484,77 +587,94 @@ { "children": [ { + "icon": "file-code", "link": "commands/key-code.html", "text": "ASCII And ANSI Escape Sequences (key-code)" }, { + "icon": "file-code", "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { + "icon": "file-code", "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { + "icon": "file-code", "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { + "icon": "file-code", "link": "commands/escape.html", "text": "Quote String (escape)" } ], "collapsible": true, - "icon": "file-code", + "icon": "code", "text": "String Escaping / Character Codes" }, { "children": [ { + "icon": "file-code", "link": "commands/bg.html", "text": "Background Process (bg)" }, { + "icon": "file-code", "link": "commands/bexists.html", "text": "Check Builtin Exists (bexists)" }, { + "icon": "file-code", "link": "commands/fid-list.html", "text": "Display Running Functions (fid-list)" }, { + "icon": "file-code", "link": "commands/exec.html", "text": "Execute External Command (exec)" }, { + "icon": "file-code", "link": "commands/fg.html", "text": "Foreground Process (fg)" }, { + "icon": "file-code", "link": "commands/exitnum.html", "text": "Get Exit Code (exitnum)" }, { + "icon": "file-code", "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { + "icon": "file-code", "link": "commands/fid-killall.html", "text": "Kill All In Session (fid-killall)" }, { + "icon": "file-code", "link": "commands/fid-kill.html", "text": "Kill Function (fid-kill)" }, { + "icon": "file-code", "link": "commands/which.html", "text": "Location Of Command (which)" }, { + "icon": "file-code", "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { + "icon": "file-code", "link": "commands/signal.html", "text": "Send Signal IPC (signal)" } @@ -566,94 +686,117 @@ { "children": [ { + "icon": "file-code", "link": "commands/args.html", "text": "Define Function Arguments (args)" }, { + "icon": "file-code", "link": "commands/global.html", "text": "Define Global (global)" }, { + "icon": "file-code", "link": "commands/cast.html", "text": "Define Type (cast)" }, { + "icon": "file-code", "link": "commands/set.html", "text": "Define Variable (set)" }, { + "icon": "file-code", "link": "commands/break.html", "text": "Exit Block (break)" }, { + "icon": "file-code", "link": "commands/return.html", "text": "Exit Function (return)" }, { + "icon": "file-code", "link": "commands/exit.html", "text": "Exit Murex (exit)" }, { + "icon": "file-code", "link": "commands/expr.html", "text": "Expressions (expr)" }, { + "icon": "file-code", "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { + "icon": "file-code", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { + "icon": "file-code", "link": "commands/for.html", "text": "For Loop (for)" }, { + "icon": "file-code", "link": "commands/get-type.html", "text": "Get Data Type (get-type)" }, { + "icon": "file-code", "link": "commands/if.html", "text": "If Conditional (if)" }, { + "icon": "file-code", "link": "commands/is-null.html", "text": "Is Value Null (is-null)" }, { + "icon": "file-code", "link": "commands/and.html", "text": "Logic And Statements (and)" }, { + "icon": "file-code", "link": "commands/or.html", "text": "Logic Or Statements (or)" }, { + "icon": "file-code", "link": "commands/while.html", "text": "Loop While (while)" }, { + "icon": "file-code", "link": "commands/continue.html", "text": "Next Iteration (continue)" }, { + "icon": "file-code", "link": "commands/not-func.html", "text": "Not (!)" }, { + "icon": "file-code", "link": "commands/devnull.html", "text": "Null (null)" }, { + "icon": "file-code", "link": "commands/private.html", "text": "Private Function (private)" }, { + "icon": "file-code", "link": "commands/function.html", "text": "Public Function (function)" }, { + "icon": "file-code", "link": "commands/switch.html", "text": "Switch Conditional (switch)" } @@ -665,30 +808,37 @@ { "children": [ { + "icon": "file-code", "link": "commands/catch.html", "text": "Caught Error Block (catch)" }, { + "icon": "file-code", "link": "commands/unsafe.html", "text": "Disable Error Handling In Block (unsafe)" }, { + "icon": "file-code", "link": "commands/runmode.html", "text": "Function / Module Defaults (runmode)" }, { + "icon": "file-code", "link": "commands/trypipe.html", "text": "Pipe Fail (trypipe)" }, { + "icon": "file-code", "link": "commands/trypipeerr.html", "text": "Stderr Checking In Pipes (trypipeerr)" }, { + "icon": "file-code", "link": "commands/tryerr.html", "text": "Stderr Checking In TTY (tryerr)" }, { + "icon": "file-code", "link": "commands/try.html", "text": "Try Block (try)" } @@ -700,18 +850,22 @@ { "children": [ { + "icon": "file-code", "link": "commands/man-summary.html", "text": "Man-Page Summary (man-summary)" }, { + "icon": "file-code", "link": "commands/murex-docs.html", "text": "Murex's Offline Documentation (murex-docs)" }, { + "icon": "file-code", "link": "commands/man-get-flags.html", "text": "Parse Man-Page For Flags (man-get-flags)" }, { + "icon": "file-code", "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" } diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json new file mode 100644 index 000000000..da84111cd --- /dev/null +++ b/gen/vuepress/parser_generated.json @@ -0,0 +1,228 @@ +[ + { + "children": [ + { + "icon": "file-code", + "link": "parser/multiplication.html", + "text": "* Multiplication Operator" + }, + { + "icon": "file-code", + "link": "parser/addition.html", + "text": "+ Addition Operator" + }, + { + "icon": "file-code", + "link": "parser/subtraction.html", + "text": "- Subtraction Operator" + }, + { + "icon": "file-code", + "link": "parser/division.html", + "text": "/ Division Operator" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Modifiers" + }, + { + "children": [ + { + "icon": "file-code", + "link": "commands/alter.html", + "text": "Alter Data Structure (alter / ~\u003e)" + }, + { + "icon": "file-code", + "link": "parser/assign-or-merge.html", + "text": "\u003c~ Assign Or Merge" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Merge" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/multiply-by.html", + "text": "*= Multiply By Operator" + }, + { + "icon": "file-code", + "link": "parser/add-with.html", + "text": "+= Add With Operator" + }, + { + "icon": "file-code", + "link": "parser/subtract-by.html", + "text": "-= Subtract By Operator" + }, + { + "icon": "file-code", + "link": "parser/divide-by.html", + "text": "/= Divide By Operator" + }, + { + "icon": "file-code", + "link": "parser/assign-or-merge.html", + "text": "\u003c~ Assign Or Merge" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Assignment" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/elvis.html", + "text": "?: Elvis Operator" + }, + { + "icon": "file-code", + "link": "parser/null-coalescing.html", + "text": "?? Null Coalescing Operator" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Conditionals" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/scalar.html", + "text": "$Scalar Sigil (eg variables)" + }, + { + "icon": "file-code", + "link": "parser/array.html", + "text": "@Array Sigil" + }, + { + "icon": "file-code", + "link": "parser/tilde.html", + "text": "~ Home Sigil" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Sigils" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/double-quote.html", + "text": "\"Double Quote\"" + }, + { + "icon": "file-code", + "link": "parser/brace-quote.html", + "text": "%(Brace Quote)" + }, + { + "icon": "file-code", + "link": "parser/create-array.html", + "text": "%[] Array Builder" + }, + { + "icon": "file-code", + "link": "parser/create-object.html", + "text": "%{} Object Builder" + }, + { + "icon": "file-code", + "link": "parser/single-quote.html", + "text": "'Single Quote'" + }, + { + "icon": "file-code", + "link": "parser/curly-brace.html", + "text": "{ Curly Brace }" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Constants" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/expr-inlined.html", + "text": "( expression )" + }, + { + "icon": "file-code", + "link": "parser/c-style-fun.html", + "text": "C-style functions" + }, + { + "icon": "file-code", + "link": "parser/lambda.html", + "text": "[{ Lambda }]" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Sub-Shells" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/logical-and.html", + "text": "\u0026\u0026 And Logical Operator" + }, + { + "icon": "file-code", + "link": "parser/logical-or.html", + "text": "|| Or Logical Operator" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Boolean Operations" + }, + { + "children": [ + { + "icon": "file-code", + "link": "parser/pipe-arrow.html", + "text": "-\u003e Arrow Pipe" + }, + { + "icon": "file-code", + "link": "parser/pipe-generic.html", + "text": "=\u003e Generic Pipe" + }, + { + "icon": "file-code", + "link": "parser/file-append.html", + "text": "\u003e\u003e Append File" + }, + { + "icon": "file-code", + "link": "parser/pipe-posix.html", + "text": "| POSIX Pipe" + } + ], + "collapsible": true, + "icon": "angles-right", + "text": "Pipes" + }, + { + "link": "parser/equ.html", + "text": "= (arithmetic evaluation)" + }, + { + "link": "parser/pipe-err.html", + "text": "? stderr Pipe" + } +] \ No newline at end of file diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index bfb8c55c6..8c90d35ae 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -1,5 +1,6 @@ import { sidebar } from "vuepress-theme-hope"; import commandsMenu from "./commands_generated.json" +import parserMenu from "./parser_generated.json" export default sidebar({ "/": [ @@ -35,8 +36,8 @@ export default sidebar({ { text: "Operators And Tokens", icon: "hashtag", - prefix: "parser/", - children: "structure", + prefix: "/", + children: parserMenu, collapsible: true, }, { diff --git a/images/screenshot-iterm2-open.png b/images/screenshot-iterm2-open.png new file mode 100644 index 0000000000000000000000000000000000000000..79bfd87f953c424379af39651c42eb71a9ba38f9 GIT binary patch literal 430415 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

Xz*i)8uBJD7^K#k+JEYdpk1k^2MD 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

    OVNI0Y_VH~ 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
      TMmF?xaya+y*Vr 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 z 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�)1Ws2SY#>>-&@kopfptuV0 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

      C#*x7=D5%demP^vmLW9Fl}ci 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 literal 0 HcmV?d00001 diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 6c0b38589..c8ce2aac3 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -261,7 +261,7 @@ func funcTime(dt time.Time) string { // Takes: string (category, document ID) // Returns: document type func funcDocT(cat, doc string) *document { - if cat == "" { + if cat == "" || cat == "*" { cat = "???" } return Documents.ByID("!!!", cat, doc) @@ -375,12 +375,13 @@ func vuePressSubMenu(cat *category) []map[string]any { subMenu = append(subMenu, map[string]any{ "text": vueTitle(Documents[i].Title), "link": Documents[i].Hierarchy() + ".html", + "icon": "file-code", }) } } menu = append(menu, map[string]any{ "text": vueTitle(sub.Title), - "icon": sub.VueIcon, + "icon": "angles-right", //sub.VueIcon, "children": subMenu, "collapsible": true, }) From 95338b18361340545e86f0294943c3cccf0b05e2 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 19:12:06 +0100 Subject: [PATCH 115/142] website: icon override --- gen/vuepress/commands_generated.json | 30 ++++++++++---------- gen/vuepress/parser_generated.json | 42 +++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index e6dcde222..9c7ee0544 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -58,7 +58,7 @@ } ], "collapsible": true, - "icon": "arrows-turn-to-dots", + "icon": "angles-right", "text": "Input / Output Streams" }, { @@ -105,7 +105,7 @@ } ], "collapsible": true, - "icon": "floppy-disk", + "icon": "angles-right", "text": "Filesystem Operations" }, { @@ -162,7 +162,7 @@ } ], "collapsible": true, - "icon": "server", + "icon": "angles-right", "text": "Defined by POSIX" }, { @@ -269,7 +269,7 @@ } ], "collapsible": true, - "icon": "rectangle-list", + "icon": "angles-right", "text": "List / Array Editing" }, { @@ -341,7 +341,7 @@ } ], "collapsible": true, - "icon": "quote-left", + "icon": "angles-right", "text": "String Manipulation" }, { @@ -363,7 +363,7 @@ } ], "collapsible": true, - "icon": "square-root-variable", + "icon": "angles-right", "text": "Numeric / Math Tools" }, { @@ -420,7 +420,7 @@ } ], "collapsible": true, - "icon": "sitemap", + "icon": "angles-right", "text": "Structured Data Management" }, { @@ -452,7 +452,7 @@ } ], "collapsible": true, - "icon": "table", + "icon": "angles-right", "text": "Table Management" }, { @@ -479,7 +479,7 @@ } ], "collapsible": true, - "icon": "microchip", + "icon": "angles-right", "text": "System Inspection" }, { @@ -581,7 +581,7 @@ } ], "collapsible": true, - "icon": "gear", + "icon": "angles-right", "text": "Shell / Murex Management" }, { @@ -613,7 +613,7 @@ } ], "collapsible": true, - "icon": "code", + "icon": "angles-right", "text": "String Escaping / Character Codes" }, { @@ -680,7 +680,7 @@ } ], "collapsible": true, - "icon": "robot", + "icon": "angles-right", "text": "Process Management" }, { @@ -802,7 +802,7 @@ } ], "collapsible": true, - "icon": "language", + "icon": "angles-right", "text": "Language And Scripting" }, { @@ -844,7 +844,7 @@ } ], "collapsible": true, - "icon": "bomb", + "icon": "angles-right", "text": "Error Handling" }, { @@ -871,7 +871,7 @@ } ], "collapsible": true, - "icon": "lightbulb", + "icon": "angles-right", "text": "Help and Hint Tools" }, { diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json index da84111cd..d9d6e0105 100644 --- a/gen/vuepress/parser_generated.json +++ b/gen/vuepress/parser_generated.json @@ -33,6 +33,26 @@ "link": "commands/alter.html", "text": "Alter Data Structure (alter / ~\u003e)" }, + { + "icon": "file-code", + "link": "commands/cast.html", + "text": "Define Type (cast)" + }, + { + "icon": "file-code", + "link": "parser/range.html", + "text": "Filter By Range [ ..Range ]" + }, + { + "icon": "file-code", + "link": "parser/item-index.html", + "text": "Get Item ([ Index ])" + }, + { + "icon": "file-code", + "link": "parser/element.html", + "text": "Get Nested Element ([[ Element ]])" + }, { "icon": "file-code", "link": "parser/assign-or-merge.html", @@ -41,7 +61,7 @@ ], "collapsible": true, "icon": "angles-right", - "text": "Merge" + "text": "Data Manipulation" }, { "children": [ @@ -192,6 +212,26 @@ }, { "children": [ + { + "icon": "file-code", + "link": "commands/cast.html", + "text": "Define Type (cast)" + }, + { + "icon": "file-code", + "link": "parser/namedpipe.html", + "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" + }, + { + "icon": "file-code", + "link": "parser/stdin.html", + "text": "Read From Stdin (\u003cstdin\u003e)" + }, + { + "icon": "file-code", + "link": "parser/file-truncate.html", + "text": "Truncate File (\u003e)" + }, { "icon": "file-code", "link": "parser/pipe-arrow.html", From 94126d7d023361d0391658db5501e73fb659c168 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Thu, 12 Sep 2024 22:09:40 +0100 Subject: [PATCH 116/142] post merge fix up --- app/app.go | 6 +++--- builtins/core/lists/match_doc.yaml | 9 ++++++--- docs/commands/regexp.md | 1 + go.mod | 5 +++++ go.sum | 13 +++++++++++-- version.svg | 2 +- 6 files changed, 27 insertions(+), 9 deletions(-) diff --git a/app/app.go b/app/app.go index 86770d5cc..e82fb2795 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4000 - Branch = "863/job-control" - BuildDate = "2024-09-10 22:44:49" + Revision = 4003 + Branch = "develop" + BuildDate = "2024-09-12 22:09:42" ) // Copyright is the copyright owner string diff --git a/builtins/core/lists/match_doc.yaml b/builtins/core/lists/match_doc.yaml index 781ff8ab3..463f947c7 100644 --- a/builtins/core/lists/match_doc.yaml +++ b/builtins/core/lists/match_doc.yaml @@ -1,7 +1,9 @@ - DocumentID: match Title: >+ - `match` + Match String (`match`) CategoryID: commands + SubCategoryIDs: + - commands.list Summary: >- Match an exact value in an array Description: |- @@ -64,7 +66,8 @@ Synonyms: - match - "!match" - - list.string + - list.str + - "!list.str" Related: - a - ja @@ -79,4 +82,4 @@ - msort - pretty - map - - regexp + - regexp \ No newline at end of file diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 8acba6da4..7e6541985 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -27,6 +27,7 @@ function separator pattern [ separator parameter2 ] * _pattern_: regexp pattern + * _parameter2_: any extra operations to perform. For example a string to replace matched patterns when using the regexp substitution function diff --git a/go.mod b/go.mod index 1f44d3255..163e1a199 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,8 @@ require ( github.com/mattn/go-sqlite3 v1.14.16 github.com/pelletier/go-toml v1.9.5 github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee + golang.org/x/sys v0.20.0 + golang.org/x/text v0.16.0 gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.25.0 ) @@ -30,6 +32,9 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/stretchr/testify v1.8.2 // indirect golang.org/x/image v0.18.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect lukechampine.com/uint128 v1.2.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect modernc.org/ccgo/v3 v3.16.13 // indirect diff --git a/go.sum b/go.sum index e511e4e7a..3b6efec66 100644 --- a/go.sum +++ b/go.sum @@ -60,13 +60,22 @@ golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/version.svg b/version.svg index 06933b080..aad777e0d 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.3200Version6.3.3200 \ No newline at end of file +Version: 6.3.4003Version6.3.4003 From d0f3063e291e8d7cde4f325d0a98190235b83308 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 13 Sep 2024 18:29:35 +0100 Subject: [PATCH 117/142] job-control: check for stop state --- app/app.go | 4 +- shell/signal_handler/sigfns/sigfns_unix.go | 43 +++++++++++++++++----- version.svg | 2 +- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/app/app.go b/app/app.go index e82fb2795..7a62d39c9 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4003 + Revision = 4024 Branch = "develop" - BuildDate = "2024-09-12 22:09:42" + BuildDate = "2024-09-13 18:29:35" ) // Copyright is the copyright owner string diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index e8f97e517..3657eba03 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -12,7 +12,6 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/humannumbers" - "golang.org/x/sys/unix" ) func Sigtstp(_ bool) { @@ -53,14 +52,36 @@ func Sigchld(interactive bool) { } p := lang.ForegroundProc.Get() - //debug.Logf("!!! Sigchld(fid: %d)->session.UnixIsSession(fid: %d, pid: %d): %s %s", lang.ShellProcess.Id, p.Id, os.Getpid()) //, p, p.Parameters.StringAll()) if p.Id == lang.ShellProcess.Id { // Child already exited so we can ignore this signal return } - //debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d) == %v", p.SystemProcess.Pid(), p.SystemProcess.State()) - if p.SystemProcess.State() == nil { + var ( + status syscall.WaitStatus + pid = p.SystemProcess.Pid() + ) + + if pid == -1 { + return + } + + wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG|syscall.WUNTRACED, nil) + if err != nil { + debug.Logf("!!! error in syscall.Wait4(pid: %d, &status, syscall.WNOHANG|syscall.WUNTRACED, nil):\n!!! %v", + pid, err) + } + + if wpid == 0 { + return + } + + switch { + case status.Stopped(): + returnFromSigtstp(p) + } + + /*if p.SystemProcess.State() == nil { sid, err := unix.Getsid(p.SystemProcess.Pid()) if err != nil { debug.Logf("!!! Sigchld()->unix.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) @@ -72,21 +93,23 @@ func Sigchld(interactive bool) { return } + // on macOS, Sigchld seems to get called multiple times when a process + // is stopped. This is likely a bug in Murex, but the following line + // code avoids any side effects regardless of the root cause. if p.State.Get() == state.Stopped { return } - //debug.Log("!!! calling returnFromSigtstp(p)") - returnFromSigtstp(p) - //debug.Log("!!! returned from returnFromSigtstp(p)") + if err = p.SystemProcess.Signal(syscall.Signal(0)); err != nil { + returnFromSigtstp(p) + } return } if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { - //debug.Logf("!!! Sigchld()->p.SystemProcess.State(pid: %d).Sys().(syscall.WaitStatus).Exited() == true", os.Getpid()) - return - } + return // TODO: eventually we should have a clean up of old PIDs + }*/ } func stopStatus(p *lang.Process) { diff --git a/version.svg b/version.svg index aad777e0d..3e9931a42 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4003Version6.3.4003 +Version: 6.3.4024Version6.3.4024 From 1b852fa45a8c78d97f0259d3078ad853cc87ad85 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 13 Sep 2024 21:57:19 +0100 Subject: [PATCH 118/142] wip: execute as --- CONTRIBUTING.md | 20 +++++++++----- app/app.go | 4 +-- builtins/core/lists/regexp_doc.yaml | 9 ++++--- docs/commands/regexp.md | 9 ++++--- flags.go | 2 +- gen/root/CONTRIBUTING.inc.md | 20 +++++++++----- integrations/helix-editor_posix.mx | 4 +-- main.go | 41 ++++++++++++++++++++++++++--- version.svg | 2 +- 9 files changed, 80 insertions(+), 31 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef54d93d4..c5315f47d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -39,11 +39,17 @@ please do raise a pull request. All documentation is written in markdown. Even the website is HTML generated from the original markdown documents. And all markdown documents are themselves generated from files with the extension `_doc.yaml`. These template files are -the backbone of the documentation's pseudo-CMS. +the backbone of the documentation's static site CMS. -If you are unsure where to find a document, you can either `grep` the source -repository for a known phrase, or ask in the [Github discussions](https://github.com/lmorg/murex/discussions) -group. +Each generated markdown file has a footer with a link to the YAML file that it +was generated from. + +You can compile the markdown files by running `go generate` from the root of +the project directory: + +``` +go generate ./... +``` ### Writing Integrations @@ -57,7 +63,7 @@ aliases or functions defined. One of the core tenets of Murex is that it's out-of-the-box experience should already be excellent and any customization that happens after is for personalization rather than because the default experience is lacking in some -way. So Murex has made it very easy for you to contribute. +way. So Murex has made it very easy for you to contribute: In the root of the project resides the [integrations directory](https://github.com/lmorg/murex/tree/master/integrations). Each file in there is compiled into Murex, assuming the following condition is @@ -82,8 +88,8 @@ These can be raised on our [Github issue tracker](github.com/lmorg/murex/issues) ### Committing Code Murex is written in a language called Go. Not a lot of Murex's code is well -documented however that was is document can be found in the [API section](/docs/apis) of the -user guide. +documented however the stuff that has been documented can be found in the +[API section](/docs/apis) of the user guide. ### Blogging diff --git a/app/app.go b/app/app.go index e82fb2795..37c3dd0bb 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4003 + Revision = 4007 Branch = "develop" - BuildDate = "2024-09-12 22:09:42" + BuildDate = "2024-09-13 21:57:22" ) // Copyright is the copyright owner string diff --git a/builtins/core/lists/regexp_doc.yaml b/builtins/core/lists/regexp_doc.yaml index 5f14480fe..53573b987 100644 --- a/builtins/core/lists/regexp_doc.yaml +++ b/builtins/core/lists/regexp_doc.yaml @@ -29,7 +29,6 @@ * _pattern_: regexp pattern - * _parameter2_: any extra operations to perform. For example a string to replace matched patterns when using the regexp substitution function Examples: |- @@ -180,9 +179,11 @@ x{n,}? n or more x, prefer fewer x{n}? exactly n x - Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject - forms that create a minimum or maximum repetition count above 1000. Unlimited - repetitions are not subject to this restriction. + #### Implementation restriction + + The counting forms `x{n,m}`, `x{n,}`, and `x{n}` reject forms that create a + minimum or maximum repetition count above 1000. Unlimited repetitions are not + subject to this restriction. ### Grouping diff --git a/docs/commands/regexp.md b/docs/commands/regexp.md index 7e6541985..596170f5d 100644 --- a/docs/commands/regexp.md +++ b/docs/commands/regexp.md @@ -27,7 +27,6 @@ function separator pattern [ separator parameter2 ] * _pattern_: regexp pattern - * _parameter2_: any extra operations to perform. For example a string to replace matched patterns when using the regexp substitution function @@ -184,9 +183,11 @@ Murex regex expressions are based on [Go's stdlib regexp library](https://pkg.go x{n,}? n or more x, prefer fewer x{n}? exactly n x -Implementation restriction: The counting forms x{n,m}, x{n,}, and x{n} reject -forms that create a minimum or maximum repetition count above 1000. Unlimited -repetitions are not subject to this restriction. +#### Implementation restriction + +The counting forms `x{n,m}`, `x{n,}`, and `x{n}` reject forms that create a +minimum or maximum repetition count above 1000. Unlimited repetitions are not +subject to this restriction. ### Grouping diff --git a/flags.go b/flags.go index 976521b91..229cab756 100644 --- a/flags.go +++ b/flags.go @@ -33,7 +33,7 @@ var ( func readFlags() { flag.BoolVar(&fInteractive, "i", false, "Start interactive shell after -c execution") flag.StringVar(&fCommand, "c", "", "Run code block (str)") - flag.BoolVar(&fExecute, "execute", false, "Execute a command from tokenized parameters (argv[])") + flag.BoolVar(&fExecute, "execute-as", false, "Execute a command from tokenized parameters (argv[])") flag.BoolVar(&fCreateSession, "setsid", false, "Set session ID: POSIX compatibility for job control (this will break support for some of Murex's job control features)") flag.BoolVar(&fLoadMods, "load-modules", false, "Load modules and profile when in non-interactive mode ") diff --git a/gen/root/CONTRIBUTING.inc.md b/gen/root/CONTRIBUTING.inc.md index bdbb8e55b..6cfa6bbe7 100644 --- a/gen/root/CONTRIBUTING.inc.md +++ b/gen/root/CONTRIBUTING.inc.md @@ -44,11 +44,17 @@ please do raise a pull request. All documentation is written in markdown. Even the website is HTML generated from the original markdown documents. And all markdown documents are themselves generated from files with the extension `_doc.yaml`. These template files are -the backbone of the documentation's pseudo-CMS. +the backbone of the documentation's static site CMS. -If you are unsure where to find a document, you can either `grep` the source -repository for a known phrase, or ask in the [Github discussions](https://github.com/lmorg/murex/discussions) -group. +Each generated markdown file has a footer with a link to the YAML file that it +was generated from. + +You can compile the markdown files by running `go generate` from the root of +the project directory: + +``` +go generate ./... +``` ### Writing Integrations @@ -62,7 +68,7 @@ aliases or functions defined. One of the core tenets of Murex is that it's out-of-the-box experience should already be excellent and any customization that happens after is for personalization rather than because the default experience is lacking in some -way. So Murex has made it very easy for you to contribute. +way. So Murex has made it very easy for you to contribute: In the root of the project resides the [integrations directory](https://github.com/lmorg/murex/tree/master/integrations). Each file in there is compiled into Murex, assuming the following condition is @@ -87,8 +93,8 @@ These can be raised on our [Github issue tracker](github.com/lmorg/murex/issues) ### Committing Code Murex is written in a language called Go. Not a lot of Murex's code is well -documented however that was is document can be found in the [API section]({{if env "DOCGEN_TARGET="}}/docs{{end}}/apis) of the -user guide. +documented however the stuff that has been documented can be found in the +[API section]({{if env "DOCGEN_TARGET="}}/docs{{end}}/apis) of the user guide. ### Blogging diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 2d7635f5a..24fed601c 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -1,11 +1,11 @@ if { which helix } then { summary helix "Helix: a post-modern text editor" - alias helix=exec $MUREX_EXE -quiet -setsid -execute exec helix + alias helix=exec $MUREX_EXE -quiet -setsid -execute-as exec helix } if { which hx } then { summary hx "Helix: a post-modern text editor" - alias hx=exec $MUREX_EXE -setsid -quiet -execute exec hx + alias hx=exec $MUREX_EXE -setsid -quiet -execute exec hx } diff --git a/main.go b/main.go index 9ecc3c9ec..f85d4f016 100644 --- a/main.go +++ b/main.go @@ -35,9 +35,7 @@ func main() { runCommandString(fCommand) case fExecute: - argv := flag.Args() - cmdLine := argvToCmdLineStr(argv) - runCommandString(cmdLine) + executeAs(flag.Args()) case len(fSource) > 0: runSource(fSource[0]) @@ -120,6 +118,43 @@ func runCommandString(commandString string) { } } +func executeAs(argv []string) { + lang.InitEnv() + + // default config + defaults.Config(lang.ShellProcess.Config, fInteractive) + registerSignalHandlers(fInteractive) + + // compiled profile + defaultProfile() + + // load modules and profile + if fLoadMods { + profile.Execute(profile.F_PRELOAD | profile.F_MODULES | profile.F_PROFILE) + } + + // read block from command line parameters + term.OutSetDataTypeIPC() + + err := lang.ShellProcess.Config.Set("proc", "force-tty", true, lang.ShellProcess.FileRef) + if err != nil { + panic(err) + } + + lang.ShellProcess.Name.Set(argv[0]) + lang.ShellProcess.Parameters.DefineParsed(argv[1:]) + + err = lang.External(lang.ShellProcess) + if err != nil { + _, err = os.Stdout.WriteString(err.Error()) + if err != nil { + panic(err) + } + } + + lang.Exit(lang.ShellProcess.ExitNum) +} + func runSource(filename string) { lang.InitEnv() diff --git a/version.svg b/version.svg index aad777e0d..0dd24a67d 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4003Version6.3.4003 +Version: 6.3.4007Version6.3.4007 From b268545230ad4106e88a0f075210c3090eccaddd Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 13 Sep 2024 23:21:04 +0100 Subject: [PATCH 119/142] #863 job-control: rewrite working on macOS --- app/app.go | 4 +- main.go | 7 ++- shell/signal_handler/sigfns/sigfns_unix.go | 68 +++++++++++++++++----- version.svg | 2 +- 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/app/app.go b/app/app.go index c15f74738..b034a67b2 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4104 + Revision = 4123 Branch = "develop" - BuildDate = "2024-09-13 22:00:01" + BuildDate = "2024-09-13 23:21:21" ) // Copyright is the copyright owner string diff --git a/main.go b/main.go index f85d4f016..8bb5d1eed 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,8 @@ func main() { runCommandString(fCommand) case fExecute: - executeAs(flag.Args()) + //executeAs(flag.Args()) + runCommandString(argvToCmdLineStr(flag.Args())) case len(fSource) > 0: runSource(fSource[0]) @@ -118,7 +119,7 @@ func runCommandString(commandString string) { } } -func executeAs(argv []string) { +/*func executeAs(argv []string) { lang.InitEnv() // default config @@ -153,7 +154,7 @@ func executeAs(argv []string) { } lang.Exit(lang.ShellProcess.ExitNum) -} +}*/ func runSource(filename string) { lang.InitEnv() diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 3657eba03..e00f2f489 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -12,6 +12,7 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/humannumbers" + "golang.org/x/sys/unix" ) func Sigtstp(_ bool) { @@ -52,20 +53,47 @@ func Sigchld(interactive bool) { } p := lang.ForegroundProc.Get() - if p.Id == lang.ShellProcess.Id { + /*if p.Id == lang.ShellProcess.Id { // Child already exited so we can ignore this signal return + }*/ + + pid := p.SystemProcess.Pid() + if pid == -1 { + // Not a system process + return } - var ( - status syscall.WaitStatus - pid = p.SystemProcess.Pid() - ) + SigchldDarwin(p, pid) + /*if runtime.GOOS == "linux" { + SigchldLinux(p, pid) + return + } - if pid == -1 { + SigchildBsd(p, pid)*/ +} + +func SigchldLinux(p *lang.Process, pid int) { + var status syscall.WaitStatus + + wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG|syscall.WUNTRACED, nil) + if err != nil { + debug.Logf("!!! error in syscall.Wait4(pid: %d, &status, syscall.WNOHANG|syscall.WUNTRACED, nil):\n!!! %v", + pid, err) + } + + if wpid == 0 { return } + if status.Stopped() { + returnFromSigtstp(p) + } +} + +func SigchldDarwin(p *lang.Process, pid int) { + var status syscall.WaitStatus + wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG|syscall.WUNTRACED, nil) if err != nil { debug.Logf("!!! error in syscall.Wait4(pid: %d, &status, syscall.WNOHANG|syscall.WUNTRACED, nil):\n!!! %v", @@ -78,18 +106,30 @@ func Sigchld(interactive bool) { switch { case status.Stopped(): + //returnFromSigtstp(p) + case status.Continued(): returnFromSigtstp(p) + case status.Signaled(): + //panic("sig") + case status.CoreDump(): + //panic("dump") + case status.Exited(): + //panic("exit") + default: + //panic("foobar") } +} - /*if p.SystemProcess.State() == nil { - sid, err := unix.Getsid(p.SystemProcess.Pid()) +func SigchildBsd(p *lang.Process, pid int) { + if p.SystemProcess.State() == nil { + sid, err := unix.Getsid(pid) if err != nil { - debug.Logf("!!! Sigchld()->unix.Getsid(p.SystemProcess.Pid: %d) failed: %s", p.SystemProcess.Pid(), err.Error()) + debug.Logf("!!! Sigchld()->unix.Getsid(p.SystemProcess.Pid: %d) failed: %s", pid, err.Error()) return } - debug.Logf("!!! unix.Getsid(p.SystemProcess.Pid: %d) == %d", p.SystemProcess.Pid(), sid) - if sid != p.SystemProcess.Pid() { + debug.Logf("!!! unix.Getsid(p.SystemProcess.Pid: %d) == %d", pid, sid) + if sid != pid { return } @@ -100,14 +140,12 @@ func Sigchld(interactive bool) { return } - if err = p.SystemProcess.Signal(syscall.Signal(0)); err != nil { - returnFromSigtstp(p) - } + returnFromSigtstp(p) return } - if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { + /*if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { return // TODO: eventually we should have a clean up of old PIDs }*/ } diff --git a/version.svg b/version.svg index dca4d6e70..c1f9f182c 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4104Version6.3.4104 +Version: 6.3.4123Version6.3.4123 From 4003776afa2593a113d618d883d6bb9b06177053 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 13 Sep 2024 23:28:06 +0100 Subject: [PATCH 120/142] #863 job-control working on Linux --- app/app.go | 4 +- integrations/helix-editor_posix.mx | 2 +- shell/signal_handler/sigfns/sigfns_unix.go | 49 ++-------------------- version.svg | 2 +- 4 files changed, 8 insertions(+), 49 deletions(-) diff --git a/app/app.go b/app/app.go index b034a67b2..169e4a5ce 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4123 + Revision = 4127 Branch = "develop" - BuildDate = "2024-09-13 23:21:21" + BuildDate = "2024-09-13 23:28:07" ) // Copyright is the copyright owner string diff --git a/integrations/helix-editor_posix.mx b/integrations/helix-editor_posix.mx index 24fed601c..e5c01c997 100644 --- a/integrations/helix-editor_posix.mx +++ b/integrations/helix-editor_posix.mx @@ -1,7 +1,7 @@ if { which helix } then { summary helix "Helix: a post-modern text editor" - alias helix=exec $MUREX_EXE -quiet -setsid -execute-as exec helix + alias helix=exec $MUREX_EXE -quiet -setsid -execute exec helix } if { which hx } then { diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index e00f2f489..5660c555c 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -5,6 +5,7 @@ package sigfns import ( "fmt" + "runtime" "syscall" "github.com/lmorg/murex/debug" @@ -12,7 +13,6 @@ import ( "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/humannumbers" - "golang.org/x/sys/unix" ) func Sigtstp(_ bool) { @@ -64,13 +64,12 @@ func Sigchld(interactive bool) { return } - SigchldDarwin(p, pid) - /*if runtime.GOOS == "linux" { + if runtime.GOOS == "linux" { SigchldLinux(p, pid) return } - SigchildBsd(p, pid)*/ + SigchildBsd(p, pid) } func SigchldLinux(p *lang.Process, pid int) { @@ -91,7 +90,7 @@ func SigchldLinux(p *lang.Process, pid int) { } } -func SigchldDarwin(p *lang.Process, pid int) { +func SigchildBsd(p *lang.Process, pid int) { var status syscall.WaitStatus wpid, err := syscall.Wait4(pid, &status, syscall.WNOHANG|syscall.WUNTRACED, nil) @@ -105,49 +104,9 @@ func SigchldDarwin(p *lang.Process, pid int) { } switch { - case status.Stopped(): - //returnFromSigtstp(p) case status.Continued(): returnFromSigtstp(p) - case status.Signaled(): - //panic("sig") - case status.CoreDump(): - //panic("dump") - case status.Exited(): - //panic("exit") - default: - //panic("foobar") - } -} - -func SigchildBsd(p *lang.Process, pid int) { - if p.SystemProcess.State() == nil { - sid, err := unix.Getsid(pid) - if err != nil { - debug.Logf("!!! Sigchld()->unix.Getsid(p.SystemProcess.Pid: %d) failed: %s", pid, err.Error()) - return - } - - debug.Logf("!!! unix.Getsid(p.SystemProcess.Pid: %d) == %d", pid, sid) - if sid != pid { - return - } - - // on macOS, Sigchld seems to get called multiple times when a process - // is stopped. This is likely a bug in Murex, but the following line - // code avoids any side effects regardless of the root cause. - if p.State.Get() == state.Stopped { - return - } - - returnFromSigtstp(p) - - return } - - /*if p.SystemProcess.State().Sys().(syscall.WaitStatus).Exited() { - return // TODO: eventually we should have a clean up of old PIDs - }*/ } func stopStatus(p *lang.Process) { diff --git a/version.svg b/version.svg index c1f9f182c..21dde7c94 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4123Version6.3.4123 +Version: 6.3.4127Version6.3.4127 From fb7b79566a58fd8716b0073fc53956dbd8512fcd Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Fri, 13 Sep 2024 23:59:25 +0100 Subject: [PATCH 121/142] #863 job-control: clean up --- app/app.go | 4 +-- lang/process/sysproc.go | 4 ++- main.go | 38 ---------------------- shell/signal_handler/sigfns/sigfns_unix.go | 8 ++--- version.svg | 2 +- 5 files changed, 8 insertions(+), 48 deletions(-) diff --git a/app/app.go b/app/app.go index 169e4a5ce..0e7d674d6 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4127 + Revision = 4129 Branch = "develop" - BuildDate = "2024-09-13 23:28:07" + BuildDate = "2024-09-13 23:59:28" ) // Copyright is the copyright owner string diff --git a/lang/process/sysproc.go b/lang/process/sysproc.go index 279fde434..266a93ed4 100644 --- a/lang/process/sysproc.go +++ b/lang/process/sysproc.go @@ -61,6 +61,8 @@ func (sp *SystemProcess) Kill() error { return errNotDefined } +const NOT_A_SYSTEM_PROCESS = -1 + func (sp *SystemProcess) Pid() int { sp.mutex.Lock() defer sp.mutex.Unlock() @@ -68,7 +70,7 @@ func (sp *SystemProcess) Pid() int { if sp.inheritance != nil { return sp.inheritance.Pid() } - return -1 + return NOT_A_SYSTEM_PROCESS } func (sp *SystemProcess) ExitNum() int { diff --git a/main.go b/main.go index 8bb5d1eed..10edbd082 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,6 @@ func main() { runCommandString(fCommand) case fExecute: - //executeAs(flag.Args()) runCommandString(argvToCmdLineStr(flag.Args())) case len(fSource) > 0: @@ -119,43 +118,6 @@ func runCommandString(commandString string) { } } -/*func executeAs(argv []string) { - lang.InitEnv() - - // default config - defaults.Config(lang.ShellProcess.Config, fInteractive) - registerSignalHandlers(fInteractive) - - // compiled profile - defaultProfile() - - // load modules and profile - if fLoadMods { - profile.Execute(profile.F_PRELOAD | profile.F_MODULES | profile.F_PROFILE) - } - - // read block from command line parameters - term.OutSetDataTypeIPC() - - err := lang.ShellProcess.Config.Set("proc", "force-tty", true, lang.ShellProcess.FileRef) - if err != nil { - panic(err) - } - - lang.ShellProcess.Name.Set(argv[0]) - lang.ShellProcess.Parameters.DefineParsed(argv[1:]) - - err = lang.External(lang.ShellProcess) - if err != nil { - _, err = os.Stdout.WriteString(err.Error()) - if err != nil { - panic(err) - } - } - - lang.Exit(lang.ShellProcess.ExitNum) -}*/ - func runSource(filename string) { lang.InitEnv() diff --git a/shell/signal_handler/sigfns/sigfns_unix.go b/shell/signal_handler/sigfns/sigfns_unix.go index 5660c555c..9a0fc5f3a 100644 --- a/shell/signal_handler/sigfns/sigfns_unix.go +++ b/shell/signal_handler/sigfns/sigfns_unix.go @@ -10,6 +10,7 @@ import ( "github.com/lmorg/murex/debug" "github.com/lmorg/murex/lang" + "github.com/lmorg/murex/lang/process" "github.com/lmorg/murex/lang/state" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/humannumbers" @@ -53,14 +54,9 @@ func Sigchld(interactive bool) { } p := lang.ForegroundProc.Get() - /*if p.Id == lang.ShellProcess.Id { - // Child already exited so we can ignore this signal - return - }*/ pid := p.SystemProcess.Pid() - if pid == -1 { - // Not a system process + if pid == process.NOT_A_SYSTEM_PROCESS { return } diff --git a/version.svg b/version.svg index 21dde7c94..cc3afc843 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4127Version6.3.4127 +Version: 6.3.4129Version6.3.4129 From 2bf6817918d1c72d195c4c62eb69d9f623a62fc6 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 09:53:44 +0100 Subject: [PATCH 122/142] website: use folders instead of arrows --- app/app.go | 4 +- gen/vuepress/commands_generated.json | 338 +++++++++++++-------------- gen/vuepress/parser_generated.json | 96 ++++---- utils/docgen/api/functions.go | 4 +- version.svg | 2 +- 5 files changed, 222 insertions(+), 222 deletions(-) diff --git a/app/app.go b/app/app.go index 0e7d674d6..659154524 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4129 + Revision = 4131 Branch = "develop" - BuildDate = "2024-09-13 23:59:28" + BuildDate = "2024-09-15 09:53:46" ) // Copyright is the copyright owner string diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 9c7ee0544..39b71fc2d 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -2,876 +2,876 @@ { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/err.html", "text": "Error String (err)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/pt.html", "text": "Get Pipe Status (pt)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/out.html", "text": "Output String (out)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tout.html", "text": "Output With Type Annotation (tout)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/namedpipe.html", "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/stdin.html", "text": "Read From Stdin (\u003cstdin\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/read.html", "text": "Read User Input (read)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tread.html", "text": "Read With Type (tread) (removed 7.x)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/brace-quote-func.html", "text": "(brace quote)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Input / Output Streams" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tmp.html", "text": "Create Temporary File (tmp)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/g.html", "text": "Globbing (g)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/f.html", "text": "List Filesystem Objects (f)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/lockfile.html", "text": "Lock Files (lockfile)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/open.html", "text": "Open File (open)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/rx.html", "text": "Regex Matches (rx)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/open-image.html", "text": "Render Image In Terminal (open-image)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/file-truncate.html", "text": "Truncate File (\u003e)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Filesystem Operations" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cd.html", "text": "Change Directory (cd)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/type.html", "text": "Display Command Type (type)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/expr.html", "text": "Expressions (expr)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/false.html", "text": "False (false)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/which.html", "text": "Location Of Command (which)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/out.html", "text": "Output String (out)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/read.html", "text": "Read User Input (read)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/true.html", "text": "True (true)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Defined by POSIX" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/prefix.html", "text": "Add Prefix (prefix)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/suffix.html", "text": "Add Suffix (suffix)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/append.html", "text": "Append To List (append)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/count.html", "text": "Count (count)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/ja.html", "text": "Create JSON Array (ja)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/ta.html", "text": "Create New Array (ta)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/range.html", "text": "Filter By Range [ ..Range ]" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/mjoin.html", "text": "Join Array To String (mjoin)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/left.html", "text": "Left Sub-String (left)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/match.html", "text": "Match String (match)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/prepend.html", "text": "Prepend To List (prepend)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/mtac.html", "text": "Reverse Array (mtac)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/right.html", "text": "Right Sub-String (right)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/msort.html", "text": "Sort Array (msort)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/a.html", "text": "Stream New List (a)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "List / Array Editing" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/list.case.html", "text": "Change Text Case (list.case)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/datetime.html", "text": "Date And Time Conversion (datetime)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/left.html", "text": "Left Sub-String (left)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/pretty.html", "text": "Prettify JSON" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/escape.html", "text": "Quote String (escape)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/regexp.html", "text": "Regex Operations (regexp)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/right.html", "text": "Right Sub-String (right)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/jsplit.html", "text": "Split String (jsplit)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "String Manipulation" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/expr.html", "text": "Expressions (expr)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/rand.html", "text": "Generate Random Sequence (rand)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/round.html", "text": "Round Number (round)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Numeric / Math Tools" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/alter.html", "text": "Alter Data Structure (alter / ~\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/count.html", "text": "Count (count)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/2darray.html", "text": "Create 2d Array (2darray)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/map.html", "text": "Create Map (map)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/element.html", "text": "Get Nested Element ([[ Element ]])" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/struct-keys.html", "text": "Print Map / Structure Keys (struct-keys)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Structured Data Management" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/addheading.html", "text": "Add Heading (addheading)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "optional/select.html", "text": "Inline SQL (select)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/format.html", "text": "Reformat Data type (format)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tabulate.html", "text": "Transformation Tools (tabulate)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Table Management" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cpuarch.html", "text": "CPU Architecture (cpuarch)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cpucount.html", "text": "CPU Count (cpucount)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/export.html", "text": "Define Environmental Variable (export)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/os.html", "text": "Operating System (os)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "System Inspection" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/alias.html", "text": "Alias Pointer (alias)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/history.html", "text": "Command Line History (history)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/pipe.html", "text": "Create Named Pipe (pipe)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/debug.html", "text": "Debugging Mode (debug)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/openagent.html", "text": "Define Handlers For \"open\" (openagent)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/method.html", "text": "Define Method Relationships (method)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/fexec.html", "text": "Execute Shell Function or Builtin (fexec)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/event.html", "text": "Murex Event Subsystem (event)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/murex-package.html", "text": "Murex Package Management (murex-package)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/version.html", "text": "Murex Version (version)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/private.html", "text": "Private Function (private)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/function.html", "text": "Public Function (function)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/murex-update-exe-list.html", "text": "Re-Scan $PATH For Executables" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/config.html", "text": "Shell Configuration And Settings (config)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/runtime.html", "text": "Shell Runtime (runtime)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/test.html", "text": "Shell Script Tests (test)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/autocomplete.html", "text": "Tab Autocompletion (autocomplete)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Shell / Murex Management" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/key-code.html", "text": "ASCII And ANSI Escape Sequences (key-code)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/esccli.html", "text": "Escape Command Line String (esccli)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/eschtml.html", "text": "Escape HTML (eschtml)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/escurl.html", "text": "Escape URL (escurl)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/escape.html", "text": "Quote String (escape)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "String Escaping / Character Codes" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/bg.html", "text": "Background Process (bg)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/bexists.html", "text": "Check Builtin Exists (bexists)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/fid-list.html", "text": "Display Running Functions (fid-list)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/exec.html", "text": "Execute External Command (exec)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/fg.html", "text": "Foreground Process (fg)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/exitnum.html", "text": "Get Exit Code (exitnum)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/source.html", "text": "Include / Evaluate Murex Code (source)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/fid-killall.html", "text": "Kill All In Session (fid-killall)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/fid-kill.html", "text": "Kill Function (fid-kill)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/which.html", "text": "Location Of Command (which)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/time.html", "text": "Processes Execution Time (time)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/signal.html", "text": "Send Signal IPC (signal)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Process Management" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/args.html", "text": "Define Function Arguments (args)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/global.html", "text": "Define Global (global)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cast.html", "text": "Define Type (cast)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/set.html", "text": "Define Variable (set)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/break.html", "text": "Exit Block (break)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/return.html", "text": "Exit Function (return)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/exit.html", "text": "Exit Murex (exit)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/expr.html", "text": "Expressions (expr)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/foreach.html", "text": "For Each In List (foreach)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/formap.html", "text": "For Each In Map (formap)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/for.html", "text": "For Loop (for)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/get-type.html", "text": "Get Data Type (get-type)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/if.html", "text": "If Conditional (if)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/is-null.html", "text": "Is Value Null (is-null)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/and.html", "text": "Logic And Statements (and)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/or.html", "text": "Logic Or Statements (or)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/while.html", "text": "Loop While (while)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/continue.html", "text": "Next Iteration (continue)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/not-func.html", "text": "Not (!)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/devnull.html", "text": "Null (null)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/private.html", "text": "Private Function (private)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/function.html", "text": "Public Function (function)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/switch.html", "text": "Switch Conditional (switch)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Language And Scripting" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/catch.html", "text": "Caught Error Block (catch)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/unsafe.html", "text": "Disable Error Handling In Block (unsafe)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/runmode.html", "text": "Function / Module Defaults (runmode)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/trypipe.html", "text": "Pipe Fail (trypipe)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/trypipeerr.html", "text": "Stderr Checking In Pipes (trypipeerr)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/tryerr.html", "text": "Stderr Checking In TTY (tryerr)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/try.html", "text": "Try Block (try)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Error Handling" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/man-summary.html", "text": "Man-Page Summary (man-summary)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/murex-docs.html", "text": "Murex's Offline Documentation (murex-docs)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/man-get-flags.html", "text": "Parse Man-Page For Flags (man-get-flags)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/summary.html", "text": "Set Command Summary Hint (summary)" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Help and Hint Tools" }, { diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json index d9d6e0105..7b2d69cfe 100644 --- a/gen/vuepress/parser_generated.json +++ b/gen/vuepress/parser_generated.json @@ -2,259 +2,259 @@ { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/multiplication.html", "text": "* Multiplication Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/addition.html", "text": "+ Addition Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/subtraction.html", "text": "- Subtraction Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/division.html", "text": "/ Division Operator" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Modifiers" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/alter.html", "text": "Alter Data Structure (alter / ~\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cast.html", "text": "Define Type (cast)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/range.html", "text": "Filter By Range [ ..Range ]" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/item-index.html", "text": "Get Item ([ Index ])" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/element.html", "text": "Get Nested Element ([[ Element ]])" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/assign-or-merge.html", "text": "\u003c~ Assign Or Merge" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Data Manipulation" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/multiply-by.html", "text": "*= Multiply By Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/add-with.html", "text": "+= Add With Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/subtract-by.html", "text": "-= Subtract By Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/divide-by.html", "text": "/= Divide By Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/assign-or-merge.html", "text": "\u003c~ Assign Or Merge" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Assignment" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/elvis.html", "text": "?: Elvis Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/null-coalescing.html", "text": "?? Null Coalescing Operator" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Conditionals" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/scalar.html", "text": "$Scalar Sigil (eg variables)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/array.html", "text": "@Array Sigil" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/tilde.html", "text": "~ Home Sigil" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Sigils" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/double-quote.html", "text": "\"Double Quote\"" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/brace-quote.html", "text": "%(Brace Quote)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/create-array.html", "text": "%[] Array Builder" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/create-object.html", "text": "%{} Object Builder" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/single-quote.html", "text": "'Single Quote'" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/curly-brace.html", "text": "{ Curly Brace }" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Constants" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/expr-inlined.html", "text": "( expression )" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/c-style-fun.html", "text": "C-style functions" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/lambda.html", "text": "[{ Lambda }]" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Sub-Shells" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "parser/logical-and.html", "text": "\u0026\u0026 And Logical Operator" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/logical-or.html", "text": "|| Or Logical Operator" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Boolean Operations" }, { "children": [ { - "icon": "file-code", + "icon": "file-lines", "link": "commands/cast.html", "text": "Define Type (cast)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/namedpipe.html", "text": "Read / Write To A Named Pipe (\u003cpipe\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/stdin.html", "text": "Read From Stdin (\u003cstdin\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/file-truncate.html", "text": "Truncate File (\u003e)" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/pipe-arrow.html", "text": "-\u003e Arrow Pipe" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/pipe-generic.html", "text": "=\u003e Generic Pipe" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/file-append.html", "text": "\u003e\u003e Append File" }, { - "icon": "file-code", + "icon": "file-lines", "link": "parser/pipe-posix.html", "text": "| POSIX Pipe" } ], "collapsible": true, - "icon": "angles-right", + "icon": "folder-open", "text": "Pipes" }, { diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index c8ce2aac3..2a063f96b 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -375,13 +375,13 @@ func vuePressSubMenu(cat *category) []map[string]any { subMenu = append(subMenu, map[string]any{ "text": vueTitle(Documents[i].Title), "link": Documents[i].Hierarchy() + ".html", - "icon": "file-code", + "icon": "file-lines", }) } } menu = append(menu, map[string]any{ "text": vueTitle(sub.Title), - "icon": "angles-right", //sub.VueIcon, + "icon": "folder-open", //"angles-right", //sub.VueIcon, "children": subMenu, "collapsible": true, }) diff --git a/version.svg b/version.svg index cc3afc843..86ba0077f 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4129Version6.3.4129 +Version: 6.3.4131Version6.3.4131 From c26ee3a16dbd92d8c08ae4d6ad3d67fe46507b98 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 11:42:35 +0100 Subject: [PATCH 123/142] add *_local.* to git ignore --- .gitignore | 2 +- app/app.go | 4 ++-- debug/{vlock.go => vmutex.go} | 10 +++++----- version.svg | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename debug/{vlock.go => vmutex.go} (66%) diff --git a/.gitignore b/.gitignore index d0924791f..1be431cae 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,7 @@ wasm_exec.js *.test *.prof *.pprof -/debug/logfile.go +*local.* debug.log diff --git a/app/app.go b/app/app.go index 659154524..1b1aafa04 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4131 + Revision = 4133 Branch = "develop" - BuildDate = "2024-09-15 09:53:46" + BuildDate = "2024-09-15 11:42:38" ) // Copyright is the copyright owner string diff --git a/debug/vlock.go b/debug/vmutex.go similarity index 66% rename from debug/vlock.go rename to debug/vmutex.go index 8a6e31b43..4e112fe3c 100644 --- a/debug/vlock.go +++ b/debug/vmutex.go @@ -6,21 +6,21 @@ import ( "sync" ) -// BadMutex is only used to test deadlocks and shouldn't be used in release code. -type VLock struct { +// VMutex is a verbose mutex used to test deadlocks and shouldn't be used in release code. +type VMutex struct { m sync.Mutex } // Lock is a wrapper around a mutex Lock() to help locate deadlocks -func (v *VLock) Lock() { +func (v *VMutex) Lock() { _, file1, line1, _ := runtime.Caller(1) _, file2, line2, _ := runtime.Caller(2) Log(fmt.Sprintf("( LOCK ) %s:%d, %s:%d, ", file1, line1, file2, line2)) v.m.Lock() } -// Lock is a wrapper around a mutex Unlock() to help locate deadlocks -func (v *VLock) Unlock() { +// Unlock is a wrapper around a mutex Unlock() to help locate deadlocks +func (v *VMutex) Unlock() { _, file1, line1, _ := runtime.Caller(1) _, file2, line2, _ := runtime.Caller(2) Log(fmt.Sprintf("(UNLOCK) %s:%d, %s:%d, ", file1, line1, file2, line2)) diff --git a/version.svg b/version.svg index 86ba0077f..d241ea7c3 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4131Version6.3.4131 +Version: 6.3.4133Version6.3.4133 From 819f973f72c665b411251714d7645d6e98b0397b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 11:43:00 +0100 Subject: [PATCH 124/142] missing release after os.FindProcess --- app/app.go | 4 ++-- builtins/events/onSignalReceived/signal_posix.go | 9 +++++++++ version.svg | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index 1b1aafa04..9ab5185ba 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4133 + Revision = 4134 Branch = "develop" - BuildDate = "2024-09-15 11:42:38" + BuildDate = "2024-09-15 11:43:02" ) // Copyright is the copyright owner string diff --git a/builtins/events/onSignalReceived/signal_posix.go b/builtins/events/onSignalReceived/signal_posix.go index 98357de6d..82548db06 100644 --- a/builtins/events/onSignalReceived/signal_posix.go +++ b/builtins/events/onSignalReceived/signal_posix.go @@ -33,9 +33,18 @@ func cmdSendSignal(p *lang.Process) error { } proc, err := os.FindProcess(pid) + defer release(proc) if err != nil { return err } return proc.Signal(interrupts[sig]) } + +func release(proc *os.Process) { + err := proc.Release() + if err != nil { + msg := fmt.Sprintf("!!! Cannot release process: %s", err.Error()) + lang.ShellProcess.Stderr.Writeln([]byte(msg)) + } +} diff --git a/version.svg b/version.svg index d241ea7c3..4c91f0eb7 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4133Version6.3.4133 +Version: 6.3.4134Version6.3.4134 From 320af57f701c4564f8abf3647344aab9d798e2ad Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 12:04:12 +0100 Subject: [PATCH 125/142] website: experimenting with tags --- app/app.go | 4 ++-- gen/changelog-md-cat.tmpl | 3 +++ gen/userguide-md-doc.tmpl | 1 + utils/docgen/api/functions.go | 2 +- version.svg | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/app.go b/app/app.go index 9ab5185ba..943dcce0a 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4134 + Revision = 4135 Branch = "develop" - BuildDate = "2024-09-15 11:43:02" + BuildDate = "2024-09-15 12:04:14" ) // Copyright is the copyright owner string diff --git a/gen/changelog-md-cat.tmpl b/gen/changelog-md-cat.tmpl index ec4816d15..adaefd34e 100644 --- a/gen/changelog-md-cat.tmpl +++ b/gen/changelog-md-cat.tmpl @@ -4,6 +4,9 @@ index: false icon: laptop-code category: - Murex + - changelog +tags: [ changelog ] +tag: [ changelog ] --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index f8f35fd54..740e0290f 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,5 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines +tags: [ user-guide ] description: {{ quote .Summary }} --- diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 2a063f96b..782740e32 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -381,7 +381,7 @@ func vuePressSubMenu(cat *category) []map[string]any { } menu = append(menu, map[string]any{ "text": vueTitle(sub.Title), - "icon": "folder-open", //"angles-right", //sub.VueIcon, + "icon": "folder-closed", //"angles-right", //sub.VueIcon, "children": subMenu, "collapsible": true, }) diff --git a/version.svg b/version.svg index 4c91f0eb7..358848769 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4134Version6.3.4134 +Version: 6.3.4135Version6.3.4135 From caf99ae406aade31afdc0b5c7a4b17a6fae6d460 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 14:02:51 +0100 Subject: [PATCH 126/142] website: update templates --- app/app.go | 4 ++-- docs/parser/README.md | 7 +------ gen/apis-md-doc.tmpl | 1 + gen/blog-md-cat.tmpl | 4 ++-- gen/blog-md-doc.tmpl | 1 + gen/changelog-md-cat.tmpl | 11 ++++------ gen/changelog-md-doc.tmpl | 1 + gen/commands-md-cat.tmpl | 6 +++--- gen/commands-md-doc.tmpl | 1 + gen/docgen.yaml | 2 +- gen/events-md-cat.tmpl | 8 +++++++- gen/events-md-doc.tmpl | 1 + gen/integrations-md-doc.tmpl | 1 + gen/mkarray-md-doc.tmpl | 1 + gen/murex-md-cat.tmpl | 6 +++--- gen/parser-md-cat.inc.md | 6 ------ gen/parser-md-cat.tmpl | 17 ++++++++++++++++ gen/parser-md-doc.tmpl | 1 + gen/types-md-doc.tmpl | 1 + gen/userguide-md-doc.tmpl | 2 +- gen/variables-md-cat.tmpl | 7 ++++++- gen/variables-md-doc.tmpl | 1 + gen/vuepress/commands_generated.json | 30 ++++++++++++++-------------- gen/vuepress/parser_generated.json | 18 ++++++++--------- version.svg | 2 +- 25 files changed, 82 insertions(+), 58 deletions(-) create mode 100644 gen/parser-md-cat.tmpl diff --git a/app/app.go b/app/app.go index 943dcce0a..cdf3dbe5f 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4135 + Revision = 4136 Branch = "develop" - BuildDate = "2024-09-15 12:04:14" + BuildDate = "2024-09-15 14:02:53" ) // Copyright is the copyright owner string diff --git a/docs/parser/README.md b/docs/parser/README.md index a58a56605..35536535d 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -1,10 +1,5 @@ -# Parser Reference - ---- -title: Operators And Tokens -description: "All supported operators and tokens" ---- +# Operators And Tokens

      Table of Contents

      diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index 7d8374d95..2571bcde2 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/blog-md-cat.tmpl b/gen/blog-md-cat.tmpl index 53b864fd1..2f7858690 100644 --- a/gen/blog-md-cat.tmpl +++ b/gen/blog-md-cat.tmpl @@ -1,9 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ .Title }} +description: {{ quote .Description }} index: false icon: comment -category: - - Murex +category: [ {{ .ID }} ] --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index 79438e3cb..793f9dddf 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/changelog-md-cat.tmpl b/gen/changelog-md-cat.tmpl index adaefd34e..3855c3bbf 100644 --- a/gen/changelog-md-cat.tmpl +++ b/gen/changelog-md-cat.tmpl @@ -1,12 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- -title: {{ md .Title }} -index: false +index: true +title: {{ .Title }} +description: {{ quote .Description }} icon: laptop-code -category: - - Murex - - changelog -tags: [ changelog ] -tag: [ changelog ] +category: [ {{ .ID }} ] --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index f9ab845ec..95b72e8a4 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index 8928d3d84..ebdcd0b2f 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -1,8 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- -title: {{ md .Title }} index: true -category: - - {{ .ID }} +title: {{ .Title }} +description: {{ quote .Description }} +category: [[ .ID ]] --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index 7ab723281..cfacfe5dd 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 4aa1211cb..a889c30f3 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -140,7 +140,7 @@ Categories: - OutputPath: docs/parser CategoryFile: README.md OutputExt: .md - CategoryTemplate: gen/murex-md-cat.tmpl + CategoryTemplate: gen/parser-md-cat.tmpl DocumentTemplate: gen/parser-md-doc.tmpl - OutputPath: gen/vuepress diff --git a/gen/events-md-cat.tmpl b/gen/events-md-cat.tmpl index 519fbb708..bc41efb74 100644 --- a/gen/events-md-cat.tmpl +++ b/gen/events-md-cat.tmpl @@ -1,3 +1,9 @@ -{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- +index: true +title: {{ .Title }} +description: {{ quote .Description }} +category: [ {{ .ID }} ] +--- +{{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index b3afb701a..166f57375 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 84aec62bc..6878d2b04 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index 29d1e732a..7dec7fdb1 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/murex-md-cat.tmpl b/gen/murex-md-cat.tmpl index 25b90cd5a..bde770f0b 100644 --- a/gen/murex-md-cat.tmpl +++ b/gen/murex-md-cat.tmpl @@ -1,8 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- -title: {{ md .Title }} index: true -category: - - {{ md .ID }} +title: {{ md .Title }} +description: {{ quote .Description }} +category: [[ {{ md .ID }} ]] --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/parser-md-cat.inc.md b/gen/parser-md-cat.inc.md index 7c146568a..268419ce8 100644 --- a/gen/parser-md-cat.inc.md +++ b/gen/parser-md-cat.inc.md @@ -1,9 +1,3 @@ -{{ $doc := doct "" "operators-and-tokens" }} ---- -title: {{ $doc.Title }} -description: {{ quote $doc.Summary }} ---- - {{ fn (file "gen/includes/expr-operators-tokens.inc.md") }} ## Other Reference Material diff --git a/gen/parser-md-cat.tmpl b/gen/parser-md-cat.tmpl new file mode 100644 index 000000000..32600e939 --- /dev/null +++ b/gen/parser-md-cat.tmpl @@ -0,0 +1,17 @@ +{{ $doc := doct "" "operators-and-tokens" }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- +title: {{ md $doc.Title }} +description: {{ quote $doc.Summary }} +index: true +category: [ {{ md .ID }} ] +--- + +{{ end }}# {{ md $doc.Title }}{{ if .Description }} + +{{ md (include .Description) }}{{ end }} + +## Pages + +{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 63206725a..ccdbdf296 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 659ef7b9e..d7b683aa5 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index 740e0290f..11130e925 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines -tags: [ user-guide ] description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/variables-md-cat.tmpl b/gen/variables-md-cat.tmpl index 519fbb708..84c1e14de 100644 --- a/gen/variables-md-cat.tmpl +++ b/gen/variables-md-cat.tmpl @@ -1,3 +1,8 @@ -{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +{{ if env "DOCGEN_TARGET=vuepress" }}--- +index: true +description: {{ quote .Description }} +category: [ {{ .ID }} ] +--- +{{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index babaddde1..2cc63fa53 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: [ {{ .CategoryID }} ] --- {{ end }}# {{ md .Title }} diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 39b71fc2d..381165622 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -58,7 +58,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Input / Output Streams" }, { @@ -105,7 +105,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Filesystem Operations" }, { @@ -162,7 +162,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Defined by POSIX" }, { @@ -269,7 +269,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "List / Array Editing" }, { @@ -341,7 +341,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "String Manipulation" }, { @@ -363,7 +363,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Numeric / Math Tools" }, { @@ -420,7 +420,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Structured Data Management" }, { @@ -452,7 +452,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Table Management" }, { @@ -479,7 +479,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "System Inspection" }, { @@ -581,7 +581,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Shell / Murex Management" }, { @@ -613,7 +613,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "String Escaping / Character Codes" }, { @@ -680,7 +680,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Process Management" }, { @@ -802,7 +802,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Language And Scripting" }, { @@ -844,7 +844,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Error Handling" }, { @@ -871,7 +871,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Help and Hint Tools" }, { diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json index 7b2d69cfe..949784d21 100644 --- a/gen/vuepress/parser_generated.json +++ b/gen/vuepress/parser_generated.json @@ -23,7 +23,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Modifiers" }, { @@ -60,7 +60,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Data Manipulation" }, { @@ -92,7 +92,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Assignment" }, { @@ -109,7 +109,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Conditionals" }, { @@ -131,7 +131,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Sigils" }, { @@ -168,7 +168,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Constants" }, { @@ -190,7 +190,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Sub-Shells" }, { @@ -207,7 +207,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Boolean Operations" }, { @@ -254,7 +254,7 @@ } ], "collapsible": true, - "icon": "folder-open", + "icon": "folder-closed", "text": "Pipes" }, { diff --git a/version.svg b/version.svg index 358848769..cee9e38dc 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4135Version6.3.4135 +Version: 6.3.4136Version6.3.4136 From 315d73c28d7dfccfee903c7f4d351576ba8e469a Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 14:29:12 +0100 Subject: [PATCH 127/142] website: update templates --- app/app.go | 4 ++-- docs/user-guide/README.md | 1 + gen/apis-md-doc.tmpl | 2 +- gen/blog-md-cat.tmpl | 4 ++-- gen/blog-md-doc.tmpl | 2 +- gen/changelog-md-doc.tmpl | 2 +- gen/commands-md-doc.tmpl | 2 +- gen/docgen.yaml | 1 + gen/events-md-doc.tmpl | 2 +- gen/integrations-md-doc.tmpl | 2 +- gen/mkarray-md-doc.tmpl | 2 +- gen/parser-md-doc.tmpl | 2 +- gen/types-md-doc.tmpl | 2 +- gen/userguide-md-cat.tmpl.md | 4 ++-- gen/userguide-md-doc.tmpl | 2 +- gen/variables-md-doc.tmpl | 2 +- version.svg | 2 +- 17 files changed, 20 insertions(+), 18 deletions(-) diff --git a/app/app.go b/app/app.go index cdf3dbe5f..a27f06234 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4136 + Revision = 4137 Branch = "develop" - BuildDate = "2024-09-15 14:02:53" + BuildDate = "2024-09-15 14:29:16" ) // Copyright is the copyright owner string diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 9f2289fe2..d702873df 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -7,6 +7,7 @@ shell and Murex's numerous features.
      +- [category: \[ user-guide \]](#category---md-id--) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index 2571bcde2..a1cc765d2 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/blog-md-cat.tmpl b/gen/blog-md-cat.tmpl index 2f7858690..660ba68fc 100644 --- a/gen/blog-md-cat.tmpl +++ b/gen/blog-md-cat.tmpl @@ -1,9 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ .Title }} description: {{ quote .Description }} -index: false +index: true icon: comment -category: [ {{ .ID }} ] +category: {{ .ID }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index 793f9dddf..a88c369a9 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index 95b72e8a4..4b6e788cf 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index cfacfe5dd..64ab49472 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/docgen.yaml b/gen/docgen.yaml index a889c30f3..a544361a3 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -253,6 +253,7 @@ Categories: CategoryTemplate: gen/userguide-md-cat.tmpl.md DocumentTemplate: gen/userguide-md-doc.tmpl + # integrations - ID: integrations Title: Integrations Description: diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index 166f57375..c272f6fc4 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 6878d2b04..7cca3ff92 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index 7dec7fdb1..b83e36c7f 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index ccdbdf296..26e9c7ff2 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index d7b683aa5..ab07a9ad6 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index 1fbc15d38..24c3475e8 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -1,8 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ md .Title }} index: true -category: - - {{ md .ID }} +category: [ {{ md .ID }} ] --- {{ end }}

      {{ md .Title }}

      {{ if .Description }} @@ -13,6 +12,7 @@ category:
      +- [category: \[ {{ md .ID }} \]](#category---md-id--) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index 11130e925..7bc690ea8 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 2cc63fa53..bac0a969d 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: [ {{ .CategoryID }} ] +category: {{ .CategoryID }} --- {{ end }}# {{ md .Title }} diff --git a/version.svg b/version.svg index cee9e38dc..9af11d571 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4136Version6.3.4136 +Version: 6.3.4137Version6.3.4137 From 2e890847939c7f1f74d38919bb7eef58c5b5b06f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 14:33:26 +0100 Subject: [PATCH 128/142] website: update templates --- app/app.go | 4 ++-- docs/user-guide/README.md | 2 +- gen/changelog-md-cat.tmpl | 2 +- gen/commands-md-cat.tmpl | 2 +- gen/events-md-cat.tmpl | 2 +- gen/murex-md-cat.tmpl | 2 +- gen/parser-md-cat.tmpl | 2 +- gen/userguide-md-cat.tmpl.md | 4 ++-- gen/variables-md-cat.tmpl | 2 +- version.svg | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/app.go b/app/app.go index a27f06234..58eb06696 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4137 + Revision = 4138 Branch = "develop" - BuildDate = "2024-09-15 14:29:16" + BuildDate = "2024-09-15 14:33:29" ) // Copyright is the copyright owner string diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index d702873df..82dea5f52 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -7,7 +7,7 @@ shell and Murex's numerous features.
      -- [category: \[ user-guide \]](#category---md-id--) +- [category: user-guide](#category--id-) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/changelog-md-cat.tmpl b/gen/changelog-md-cat.tmpl index 3855c3bbf..172984128 100644 --- a/gen/changelog-md-cat.tmpl +++ b/gen/changelog-md-cat.tmpl @@ -3,7 +3,7 @@ index: true title: {{ .Title }} description: {{ quote .Description }} icon: laptop-code -category: [ {{ .ID }} ] +category: {{ .ID }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index ebdcd0b2f..7e44a0008 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -2,7 +2,7 @@ index: true title: {{ .Title }} description: {{ quote .Description }} -category: [[ .ID ]] +category: {{ .ID }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/events-md-cat.tmpl b/gen/events-md-cat.tmpl index bc41efb74..ba7a105fa 100644 --- a/gen/events-md-cat.tmpl +++ b/gen/events-md-cat.tmpl @@ -2,7 +2,7 @@ index: true title: {{ .Title }} description: {{ quote .Description }} -category: [ {{ .ID }} ] +category: {{ .ID }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): diff --git a/gen/murex-md-cat.tmpl b/gen/murex-md-cat.tmpl index bde770f0b..7fc6bc0f2 100644 --- a/gen/murex-md-cat.tmpl +++ b/gen/murex-md-cat.tmpl @@ -2,7 +2,7 @@ index: true title: {{ md .Title }} description: {{ quote .Description }} -category: [[ {{ md .ID }} ]] +category: {{ .ID }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/parser-md-cat.tmpl b/gen/parser-md-cat.tmpl index 32600e939..d65b22659 100644 --- a/gen/parser-md-cat.tmpl +++ b/gen/parser-md-cat.tmpl @@ -3,7 +3,7 @@ title: {{ md $doc.Title }} description: {{ quote $doc.Summary }} index: true -category: [ {{ md .ID }} ] +category: {{ .ID }} --- {{ end }}# {{ md $doc.Title }}{{ if .Description }} diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index 24c3475e8..4bda02bb3 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ md .Title }} index: true -category: [ {{ md .ID }} ] +category: {{ .ID }} --- {{ end }}

      {{ md .Title }}

      {{ if .Description }} @@ -12,7 +12,7 @@ category: [ {{ md .ID }} ]
      -- [category: \[ {{ md .ID }} \]](#category---md-id--) +- [category: {{ .ID }}](#category--id-) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/variables-md-cat.tmpl b/gen/variables-md-cat.tmpl index 84c1e14de..3e8fd2410 100644 --- a/gen/variables-md-cat.tmpl +++ b/gen/variables-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true description: {{ quote .Description }} -category: [ {{ .ID }} ] +category: {{ .ID }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): diff --git a/version.svg b/version.svg index 9af11d571..8dff8ce39 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4137Version6.3.4137 +Version: 6.3.4138Version6.3.4138 From 93a105d06bae57893fb1043861514f8866032e48 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 15:20:51 +0100 Subject: [PATCH 129/142] website: menu names and icons --- app/app.go | 4 ++-- docs/commands/README.md | 2 +- gen/commands-md-cat.tmpl | 1 + gen/docgen.yaml | 2 +- gen/vuepress/navbar.ts | 4 ++-- gen/vuepress/sidebar.ts | 4 ++-- version.svg | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/app.go b/app/app.go index 58eb06696..3e0b07c64 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4138 + Revision = 4139 Branch = "develop" - BuildDate = "2024-09-15 14:33:29" + BuildDate = "2024-09-15 15:20:54" ) // Copyright is the copyright owner string diff --git a/docs/commands/README.md b/docs/commands/README.md index 3f9145594..9fba1b304 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -1,4 +1,4 @@ -# Command Reference +# Builtin Commands This section is a glossary of Murex builtin commands. diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index 7e44a0008..84708f119 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -2,6 +2,7 @@ index: true title: {{ .Title }} description: {{ quote .Description }} +icon: cubes category: {{ .ID }} --- diff --git a/gen/docgen.yaml b/gen/docgen.yaml index a544361a3..06d51f97f 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -13,7 +13,7 @@ Categories: DocumentTemplate: gen/root-md-doc.tmpl - ID: commands - Title: Command Reference + Title: Builtin Commands Description: |- {{ include "gen/commands-md-cat.inc.md" }} diff --git a/gen/vuepress/navbar.ts b/gen/vuepress/navbar.ts index 6e6b9932c..42a62968a 100644 --- a/gen/vuepress/navbar.ts +++ b/gen/vuepress/navbar.ts @@ -16,8 +16,8 @@ export default navbar([ { text: "User Guide", link: "user-guide/", icon: "book" }, { text: "Integrations", link: "integrations/", icon: "puzzle-piece" }, { text: "Operators And Tokens", link: "parser/", icon: "hashtag" }, - { text: "Builtins", link: "commands/", icon: "cubes" }, - { text: "Variables", link: "variables/", icon: "dollar" }, + { text: "Builtins Commands", link: "commands/", icon: "cubes" }, + { text: "Special Variables", link: "variables/", icon: "dollar" }, { text: "Data Types", link: "types/", icon: "file-contract" }, { text: "Events", link: "events/", icon: "bolt" }, { text: "Blog", link: "blog/", icon: "comment" }, diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index 8c90d35ae..78f1786c0 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -41,7 +41,7 @@ export default sidebar({ collapsible: true, }, { - text: "Builtins", + text: "Builtin Commands", icon: "cubes", prefix: "/", children: commandsMenu, @@ -55,7 +55,7 @@ export default sidebar({ collapsible: true, }, { - text: "Variables", + text: "Spacial Variables", icon: "dollar", prefix: "variables/", children: "structure", diff --git a/version.svg b/version.svg index 8dff8ce39..4d6a76eec 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4138Version6.3.4138 +Version: 6.3.4139Version6.3.4139 From faccb7a23c6a0b25300e67062a9e29104df40404 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 15:26:46 +0100 Subject: [PATCH 130/142] website: menu names and icons --- app/app.go | 4 ++-- gen/userguide-md-cat.tmpl.md | 2 ++ version.svg | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/app.go b/app/app.go index 3e0b07c64..7218aeb1f 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4139 + Revision = 4140 Branch = "develop" - BuildDate = "2024-09-15 15:20:54" + BuildDate = "2024-09-15 15:26:48" ) // Copyright is the copyright owner string diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index 4bda02bb3..7ad20b59c 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -1,6 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ md .Title }} +description: {{ quote .Description }} index: true +icon: book category: {{ .ID }} --- diff --git a/version.svg b/version.svg index 4d6a76eec..1ca64c5f3 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4139Version6.3.4139 +Version: 6.3.4140Version6.3.4140 From 043534ea59fb731a4981455a0f8cfe70008918f9 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 15:44:44 +0100 Subject: [PATCH 131/142] website: menu names and icons --- app/app.go | 4 ++-- docs/parser/README.md | 1 - gen/parser-md-cat.tmpl | 5 ++--- version.svg | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/app.go b/app/app.go index 7218aeb1f..d79d25b01 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4140 + Revision = 4141 Branch = "develop" - BuildDate = "2024-09-15 15:26:48" + BuildDate = "2024-09-15 15:44:46" ) // Copyright is the copyright owner string diff --git a/docs/parser/README.md b/docs/parser/README.md index 35536535d..a1ece903e 100644 --- a/docs/parser/README.md +++ b/docs/parser/README.md @@ -1,4 +1,3 @@ - # Operators And Tokens

      Table of Contents

      diff --git a/gen/parser-md-cat.tmpl b/gen/parser-md-cat.tmpl index d65b22659..f179613e3 100644 --- a/gen/parser-md-cat.tmpl +++ b/gen/parser-md-cat.tmpl @@ -1,6 +1,5 @@ -{{ $doc := doct "" "operators-and-tokens" }} -{{ if env "DOCGEN_TARGET=vuepress" }}--- -title: {{ md $doc.Title }} +{{ $doc := doct "" "operators-and-tokens" }}{{ if env "DOCGEN_TARGET=vuepress" }}--- +title: {{ $doc.Title }} description: {{ quote $doc.Summary }} index: true category: {{ .ID }} diff --git a/version.svg b/version.svg index 1ca64c5f3..0b9b1537e 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4140Version6.3.4140 +Version: 6.3.4141Version6.3.4141 From 8b89d9647520d76f8ec5ddd7fbfedc9589059b65 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 16:30:11 +0100 Subject: [PATCH 132/142] website: subcategories for variables --- app/app.go | 4 ++-- docs/variables/argv.md | 2 +- docs/variables/columns.md | 2 +- docs/variables/hostname.md | 2 +- docs/variables/murex_argv.md | 2 ++ docs/variables/murex_exe.md | 2 +- docs/variables/numeric.md | 2 +- docs/variables/params.md | 2 +- docs/variables/self.md | 4 ++-- docs/variables/shell.md | 9 +++++---- gen/docgen.yaml | 22 ++++++++++++++++++++++ gen/includes/this-is-a-reserved-var.inc.md | 1 + gen/variables-md-doc.tmpl | 2 +- gen/variables/ARGV_doc.yaml | 3 ++- gen/variables/COLUMNS_doc.yaml | 3 ++- gen/variables/EVENT_RETURN_doc.yaml | 1 + gen/variables/HOSTNAME_doc.yaml | 3 ++- gen/variables/MUREX_ARGV_doc.yaml | 3 +++ gen/variables/MUREX_EXE_doc.yaml | 3 ++- gen/variables/PARAMS_doc.yaml | 3 ++- gen/variables/PWDHIST_doc.yaml | 1 + gen/variables/PWD_doc.yaml | 1 + gen/variables/SELF_doc.yaml | 5 +++-- gen/variables/SHELL_doc.yaml | 10 ++++++---- gen/variables/meta-values_doc.yaml | 1 + gen/variables/numeric_doc.yaml | 3 ++- gen/vuepress/sidebar.ts | 2 +- version.svg | 2 +- 28 files changed, 71 insertions(+), 29 deletions(-) create mode 100644 gen/includes/this-is-a-reserved-var.inc.md diff --git a/app/app.go b/app/app.go index d79d25b01..298297b53 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4141 + Revision = 4146 Branch = "develop" - BuildDate = "2024-09-15 15:44:46" + BuildDate = "2024-09-15 16:45:35" ) // Copyright is the copyright owner string diff --git a/docs/variables/argv.md b/docs/variables/argv.md index 3dbf506f4..6e6140ac4 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -9,7 +9,7 @@ scope. eg `function`, `private`, `autocomplete` or shell script. Unlike `$PARAMS`, `$ARGV` includes the function name. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Examples diff --git a/docs/variables/columns.md b/docs/variables/columns.md index a168cc054..1642493a0 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -10,7 +10,7 @@ Some characters might be more than or less than 1 (one) cell in width, such as Chinese logograms and zero-width joiners. Whereas one ASCII character is the same width as one terminal cell. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Other Reserved Variables diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index 418ac4539..ee51079e7 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -7,7 +7,7 @@ `HOSTNAME` returns the hostname of the machine (host / server / virtual machine / et al) that Murex is running from. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Other Reserved Variables diff --git a/docs/variables/murex_argv.md b/docs/variables/murex_argv.md index d4b650ef7..474d4c543 100644 --- a/docs/variables/murex_argv.md +++ b/docs/variables/murex_argv.md @@ -7,6 +7,8 @@ `MUREX_ARGV` returns an array of the command name and parameters passed to the current running Murex shell +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + ## Examples ``` diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index 489d55fcb..8ceca553b 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -8,7 +8,7 @@ holds the full path to the running shell. The reason for defining a reserved variable is so that the shell path cannot be overridden. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Other Reserved Variables diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index b50fb848f..f83375973 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -6,7 +6,7 @@ Variables named `0` and above are the equivalent index value of `@ARGV`. -These are reserved variable so they cannot be changed. +These are [reserved variables](/docs/user-guide/reserved-vars.md) so they cannot be changed. ## Examples diff --git a/docs/variables/params.md b/docs/variables/params.md index 4293fa134..e7235d7fa 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -9,7 +9,7 @@ eg `function`, `private`, `autocomplete` or shell script. Unlike `$ARGV`, `$PARAMS` does not include the function name. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Examples diff --git a/docs/variables/self.md b/docs/variables/self.md index b8d37df37..56a9d620b 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -13,9 +13,9 @@ config are persistent within. In Murex, a variable declared inside an `if` or `foreach` block will be persistent outside of their blocks as long as you're still inside the same function. -Please see scoping document (link below) for more information on scoping. +Please read the [scoping document](/docs/user-guide/scoping.md) for more information on scoping. -This is a reserved variable so it cannot be changed. +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. ## Examples diff --git a/docs/variables/shell.md b/docs/variables/shell.md index caa61b445..db951f367 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -7,10 +7,11 @@ `SHELL` is an environmental variable containing the full path to the current shell -- which in our case is Murex. -This variable is set by Murex to conform to standards however, being an -environmental variable, it can be overwritten via `export`. Thus you are -recommended to use `MUREX_EXE`, which is a reserved variable, if you require -precision. +This variable is set by Murex to conform to POSIX standards. However, being an +environmental variable, it can be overwritten via `export`. + +For Murex specific code, you are recommended to use `MUREX_EXE`, which is a +reserved variable, and thus read only, if you require precision and safety. ## Other Reserved Variables diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 06d51f97f..eedd518f9 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -225,6 +225,28 @@ Categories: CategoryTemplate: gen/variables-md-cat.tmpl DocumentTemplate: gen/variables-md-doc.tmpl + SubCategories: + - ID: vars.env + Title: Environmental Variables + VueIcon: arrows-turn-to-dots + Description: |- + Environmental variables are variables held at an operating system level and thus will get passed between running processes. + - ID: vars.scoped + Title: Scoped Variables + VueIcon: arrows-turn-to-dots + Description: |- + Scoped variables are defined within a specific function's scope. These might be reserved variables but they might also be used to provide structured returns from a particular scope. + - ID: vars.posix + Title: Defined by POSIX + VueIcon: arrows-turn-to-dots + Description: |- + These are variables defined by POSIX. In general they will be environmental variables, however in some cases Murex will follow the naming convention described in POSIX but return a reserved variable instead. + - ID: vars.reserved + Title: Reserved Variables + VueIcon: arrows-turn-to-dots + Description: |- + Reserved variables are read only values that are dynamically generated at the point of querying. They behave a little more like functions than variables, albeit the convenience of being called like a variable. + # pipes: # apis: diff --git a/gen/includes/this-is-a-reserved-var.inc.md b/gen/includes/this-is-a-reserved-var.inc.md new file mode 100644 index 000000000..886d3392c --- /dev/null +++ b/gen/includes/this-is-a-reserved-var.inc.md @@ -0,0 +1 @@ +This is a {{link "reserved variable" "reserved-vars"}} so it cannot be changed. diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index bac0a969d..65b837b0a 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -10,7 +10,7 @@ category: {{ .CategoryID }} ## Description -{{ md (include .Description) }}{{ if .Usage }} +{{ md (fn (include .Description)) }}{{ if .Usage }} ## Usage diff --git a/gen/variables/ARGV_doc.yaml b/gen/variables/ARGV_doc.yaml index 7b93a5b67..c61dc2d2f 100644 --- a/gen/variables/ARGV_doc.yaml +++ b/gen/variables/ARGV_doc.yaml @@ -2,6 +2,7 @@ Title: >- `ARGV` (json) CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.scoped ] Summary: >- Array of the command name and parameters within a given scope @@ -11,7 +12,7 @@ Unlike `$PARAMS`, `$ARGV` includes the function name. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Examples: |- ``` » function example { $ARGV } diff --git a/gen/variables/COLUMNS_doc.yaml b/gen/variables/COLUMNS_doc.yaml index 7711a8183..4342165f1 100644 --- a/gen/variables/COLUMNS_doc.yaml +++ b/gen/variables/COLUMNS_doc.yaml @@ -2,6 +2,7 @@ Title: >- `COLUMNS` (int) CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.posix ] Summary: >- Character width of terminal Description: |- @@ -11,7 +12,7 @@ as Chinese logograms and zero-width joiners. Whereas one ASCII character is the same width as one terminal cell. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Synonyms: - columns - COLUMNS diff --git a/gen/variables/EVENT_RETURN_doc.yaml b/gen/variables/EVENT_RETURN_doc.yaml index ef6438bf5..9f3e49391 100644 --- a/gen/variables/EVENT_RETURN_doc.yaml +++ b/gen/variables/EVENT_RETURN_doc.yaml @@ -2,6 +2,7 @@ Title: >- `EVENT_RETURN` (json) CategoryID: variables + SubCategoryIDs: [ vars.scoped ] Summary: >- Return values for events Description: |- diff --git a/gen/variables/HOSTNAME_doc.yaml b/gen/variables/HOSTNAME_doc.yaml index 91defd79d..e55f03fb9 100644 --- a/gen/variables/HOSTNAME_doc.yaml +++ b/gen/variables/HOSTNAME_doc.yaml @@ -2,13 +2,14 @@ Title: >- `HOSTNAME` (str) CategoryID: variables + SubCategoryIDs: [ vars.reserved ] Summary: >- Hostname of the current machine Description: |- `HOSTNAME` returns the hostname of the machine (host / server / virtual machine / et al) that Murex is running from. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Synonyms: - hostname - HOSTNAME diff --git a/gen/variables/MUREX_ARGV_doc.yaml b/gen/variables/MUREX_ARGV_doc.yaml index 6b6b2601c..a4df62ff5 100644 --- a/gen/variables/MUREX_ARGV_doc.yaml +++ b/gen/variables/MUREX_ARGV_doc.yaml @@ -2,11 +2,14 @@ Title: >- `MUREX_ARGV` (json) CategoryID: variables + SubCategoryIDs: [ vars.reserved ] Summary: >- Array of the command name and parameters passed to the current shell Description: |- `MUREX_ARGV` returns an array of the command name and parameters passed to the current running Murex shell + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Examples: |- ``` » murex -trypipe -c '$MUREX_ARGV' diff --git a/gen/variables/MUREX_EXE_doc.yaml b/gen/variables/MUREX_EXE_doc.yaml index 56eedf795..bb66145a0 100644 --- a/gen/variables/MUREX_EXE_doc.yaml +++ b/gen/variables/MUREX_EXE_doc.yaml @@ -2,6 +2,7 @@ Title: >- `MUREX_EXE` (path) CategoryID: variables + SubCategoryIDs: [ vars.reserved ] Summary: >- Absolute path to running shell Description: |- @@ -9,7 +10,7 @@ holds the full path to the running shell. The reason for defining a reserved variable is so that the shell path cannot be overridden. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Synonyms: - murex_exe - MUREX_EXE diff --git a/gen/variables/PARAMS_doc.yaml b/gen/variables/PARAMS_doc.yaml index 42a27b76b..228faf8a5 100644 --- a/gen/variables/PARAMS_doc.yaml +++ b/gen/variables/PARAMS_doc.yaml @@ -2,6 +2,7 @@ Title: >- `PARAMS` (json) CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.scoped ] Summary: >- Array of the parameters within a given scope Description: |- @@ -10,7 +11,7 @@ Unlike `$ARGV`, `$PARAMS` does not include the function name. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Examples: |- ``` » function example { $PARAMS } diff --git a/gen/variables/PWDHIST_doc.yaml b/gen/variables/PWDHIST_doc.yaml index baa74f07a..0034a6102 100644 --- a/gen/variables/PWDHIST_doc.yaml +++ b/gen/variables/PWDHIST_doc.yaml @@ -2,6 +2,7 @@ Title: >- `PWDHIST` (json) CategoryID: variables + SubCategoryIDs: [ vars.env ] Summary: >- History of each change to the sessions working directory Description: |- diff --git a/gen/variables/PWD_doc.yaml b/gen/variables/PWD_doc.yaml index ecabe0c7b..d708c984e 100644 --- a/gen/variables/PWD_doc.yaml +++ b/gen/variables/PWD_doc.yaml @@ -2,6 +2,7 @@ Title: >- `PWD` (path) CategoryID: variables + SubCategoryIDs: [ vars.posix, vars.env ] Summary: >- Current working directory Description: |- diff --git a/gen/variables/SELF_doc.yaml b/gen/variables/SELF_doc.yaml index 74a505579..9177d90ff 100644 --- a/gen/variables/SELF_doc.yaml +++ b/gen/variables/SELF_doc.yaml @@ -2,6 +2,7 @@ Title: >- `SELF` (json) CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.scoped ] Summary: >- Meta information about the running scope. Description: |- @@ -14,9 +15,9 @@ `foreach` block will be persistent outside of their blocks as long as you're still inside the same function. - Please see scoping document (link below) for more information on scoping. + Please read the {{link "scoping document" "scoping"}} for more information on scoping. - This is a reserved variable so it cannot be changed. + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Examples: |- ``` » function example { $SELF } diff --git a/gen/variables/SHELL_doc.yaml b/gen/variables/SHELL_doc.yaml index ed50d1ce8..cc8da84a4 100644 --- a/gen/variables/SHELL_doc.yaml +++ b/gen/variables/SHELL_doc.yaml @@ -2,16 +2,18 @@ Title: >- `SHELL` (str) CategoryID: variables + SubCategoryIDs: [ vars.posix, vars.env ] Summary: >- Path of current shell Description: |- `SHELL` is an environmental variable containing the full path to the current shell -- which in our case is Murex. - This variable is set by Murex to conform to standards however, being an - environmental variable, it can be overwritten via `export`. Thus you are - recommended to use `MUREX_EXE`, which is a reserved variable, if you require - precision. + This variable is set by Murex to conform to POSIX standards. However, being an + environmental variable, it can be overwritten via `export`. + + For Murex specific code, you are recommended to use `MUREX_EXE`, which is a + reserved variable, and thus read only, if you require precision and safety. Examples: Synonyms: - shell diff --git a/gen/variables/meta-values_doc.yaml b/gen/variables/meta-values_doc.yaml index 6b7e52486..dd50a0a1a 100644 --- a/gen/variables/meta-values_doc.yaml +++ b/gen/variables/meta-values_doc.yaml @@ -2,6 +2,7 @@ Title: >- `$.`, Meta Values (json) CategoryID: variables + SubCategoryIDs: [ vars.scoped ] Summary: >- State information for iteration blocks Description: |- diff --git a/gen/variables/numeric_doc.yaml b/gen/variables/numeric_doc.yaml index d0a17be37..f56d101bf 100644 --- a/gen/variables/numeric_doc.yaml +++ b/gen/variables/numeric_doc.yaml @@ -2,12 +2,13 @@ Title: >- Numeric (str) CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.scoped ] Summary: >- Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above Description: |- Variables named `0` and above are the equivalent index value of `@ARGV`. - These are reserved variable so they cannot be changed. + These are {{link "reserved variables" "reserved-vars"}} so they cannot be changed. Examples: |- ``` » function example { out $0 $2 } diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index 78f1786c0..a108e0bc4 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -55,7 +55,7 @@ export default sidebar({ collapsible: true, }, { - text: "Spacial Variables", + text: "Special Variables", icon: "dollar", prefix: "variables/", children: "structure", diff --git a/version.svg b/version.svg index 0b9b1537e..69dd2e080 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4141Version6.3.4141 +Version: 6.3.4146Version6.3.4146 From 54d1e5e65ac7b72fd5edc4c253f7a934c60f4be7 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 17:46:43 +0100 Subject: [PATCH 133/142] website: integrations readme --- app/app.go | 4 +- builtins/docs/summaries.go | 2062 +++++++++-------- docs/integrations/README.md | 63 + docs/integrations/chatgpt.md | 21 +- docs/integrations/cheatsh.md | 21 +- docs/integrations/direnv.md | 21 +- docs/integrations/iterm2.md | 21 +- docs/integrations/kitty.md | 21 +- docs/integrations/make.md | 21 +- docs/integrations/man-pages.md | 21 +- docs/integrations/spellcheck.md | 21 +- docs/integrations/terminology.md | 21 +- docs/integrations/yarn.md | 21 +- docs/user-guide/integrations.md | 32 +- gen/docgen.yaml | 10 +- .../autogenerated.integrations.inc.md | 20 - gen/integrations-md-cat.tmpl | 17 + gen/integrations-md-cat.tmpl.md | 3 - gen/integrations-md-doc.tmpl | 4 +- ...array-md-cat.tmpl => mkarray-inc-cat.tmpl} | 0 gen/user-guide/integrations.inc.md | 21 + gen/user-guide/integrations_doc.yaml | 18 +- version.svg | 2 +- 23 files changed, 1269 insertions(+), 1197 deletions(-) create mode 100644 docs/integrations/README.md delete mode 100644 gen/includes/autogenerated.integrations.inc.md create mode 100644 gen/integrations-md-cat.tmpl delete mode 100644 gen/integrations-md-cat.tmpl.md rename gen/{mkarray-md-cat.tmpl => mkarray-inc-cat.tmpl} (100%) create mode 100644 gen/user-guide/integrations.inc.md diff --git a/app/app.go b/app/app.go index 298297b53..2924f7350 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4146 + Revision = 4170 Branch = "develop" - BuildDate = "2024-09-15 16:45:35" + BuildDate = "2024-09-15 18:02:38" ) // Copyright is the copyright owner string diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 5c8cd8cd4..d38bca4d2 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -5,1049 +5,1059 @@ package docs func init() { Summary = map[string]string{ - - "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "addheading": "Adds headings to a table", - "prefix": "Prefix a string to every item in a list", - "suffix": "Prefix a string to every item in a list", - "alias": "Create an alias for a command", - "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "append": "Add data to the end of an array", - "bg": "Run processes in the background", - "cpuarch": "Output the hosts CPU architecture", - "cpucount": "Output the number of CPU cores available on your host", - "catch": "Handles the exception code raised by `try` or `trypipe`", - "cd": "Change (working) directory", - "list.case": "Changes the character case of a string or all elements in an array", - "bexists": "Check which builtins exist", - "history": "Outputs murex's command history", - "count": "Count items in a map, list or array", - "2darray": "Create a 2D JSON array from multiple input sources", - "ja": "A sophisticated yet simply way to build a JSON array", - "map": "Creates a map from two data sources", - "pipe": "Manage Murex named pipes", - "ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "tmp": "Create a temporary file and write to it", - "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "debug": "Debugging information", - "export": "Define an environmental variable and set it's value", - "args": "Command line flag parser for Murex shell scripting", - "global": "Define a global variable and set it's value", - "openagent": "Creates a handler function for `open`", - "method": "Define a methods supported data-types", - "cast": "Alters the data-type of the previous function without altering its output", - "set": "Define a variable (typically local) and set it's value", - "unsafe": "Execute a block of code, always returning a zero exit number", - "type": "Command type (function, builtin, alias, etc)", - "fid-list": "Lists all running functions within the current Murex session", - "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "err": "Print a line to the stderr", - "esccli": "Escapes an array so output is valid shell code", - "eschtml": "Encode or decodes text for HTML", - "escurl": "Encode or decodes text for the URL", - "exec": "Runs an executable", - "fexec": "Execute a command or function, bypassing the usual order of precedence.", - "break": "Terminate execution of a block within your processes scope", - "return": "Exits current function scope", - "exit": "Exit murex", - "expr": "Expressions: mathematical, string comparisons, logical operators", - "false": "Returns a `false` value", - "foreach": "Iterate through an array", - "formap": "Iterate through a map or other collection of data", - "for": "A more familiar iteration loop to existing developers", - "fg": "Sends a background process into the foreground", - "runmode": "Alter the scheduler's behaviour at higher scoping level", - "rand": "Random field generator", - "get-type": "Returns the data-type of a variable or pipe", - "exitnum": "Output the exit number of the previous process", - "pt": "Pipe telemetry. Writes data-types and bytes written", - "get": "Makes a standard HTTP request and returns the result as a JSON object", - "g": "Glob pattern matching for file system objects (eg `*.txt`)", - "if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "source": "Import Murex code from another file or code block", - "is-null": "Checks if a variable is null or undefined", - "mjoin": "Joins a list or array into a single string", - "fid-killall": "Terminate all running Murex functions in current session", - "fid-kill": "Terminate a running Murex function", - "left": "Left substring every item in a list", - "f": "Lists or filters file system objects (eg files)", - "which": "Locate command origin", - "lockfile": "Create and manage lock files", - "and": "Returns `true` or `false` depending on whether multiple conditions are met", - "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "while": "Loop until condition false", - "man-summary": "Outputs a man page summary of a command", - "match": "Match an exact value in an array", - "event": "Event driven programming for shell scripts", - "murex-package": "Murex's package manager", - "version": "Get Murex version", - "murex-docs": "Displays the man pages for Murex builtins", - "continue": "Terminate process of a block within a caller function", - "not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "devnull": "null function. Similar to /dev/null", - "open": "Open a file with a preferred handler", - "os": "Output the auto-detected OS name", - "out": "Print a string to the stdout with a trailing new line character", - "tout": "Print a string to the stdout and set it's data-type", - "man-get-flags": "Parses man page files for command line flags", - "trypipe": "Checks for non-zero exits of each function in a pipeline", - "post": "HTTP POST request with a JSON-parsable return", - "prepend": "Add data to the start of an array", - "pretty": "Prettifies JSON to make it human readable", - "struct-keys": "Outputs all the keys in a structure as a file path", - "private": "Define a private function block", - "time": "Returns the execution run time of a command or block", - "function": "Define a function block", - "escape": "Escape or unescape input", + + + "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "addheading": "Adds headings to a table", + "prefix": "Prefix a string to every item in a list", + "suffix": "Prefix a string to every item in a list", + "alias": "Create an alias for a command", + "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "append": "Add data to the end of an array", + "bg": "Run processes in the background", + "cpuarch": "Output the hosts CPU architecture", + "cpucount": "Output the number of CPU cores available on your host", + "catch": "Handles the exception code raised by `try` or `trypipe`", + "cd": "Change (working) directory", + "list.case": "Changes the character case of a string or all elements in an array", + "bexists": "Check which builtins exist", + "history": "Outputs murex's command history", + "count": "Count items in a map, list or array", + "2darray": "Create a 2D JSON array from multiple input sources", + "ja": "A sophisticated yet simply way to build a JSON array", + "map": "Creates a map from two data sources", + "pipe": "Manage Murex named pipes", + "ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "tmp": "Create a temporary file and write to it", + "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "debug": "Debugging information", + "export": "Define an environmental variable and set it's value", + "args": "Command line flag parser for Murex shell scripting", + "global": "Define a global variable and set it's value", + "openagent": "Creates a handler function for `open`", + "method": "Define a methods supported data-types", + "cast": "Alters the data-type of the previous function without altering its output", + "set": "Define a variable (typically local) and set it's value", + "unsafe": "Execute a block of code, always returning a zero exit number", + "type": "Command type (function, builtin, alias, etc)", + "fid-list": "Lists all running functions within the current Murex session", + "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "err": "Print a line to the stderr", + "esccli": "Escapes an array so output is valid shell code", + "eschtml": "Encode or decodes text for HTML", + "escurl": "Encode or decodes text for the URL", + "exec": "Runs an executable", + "fexec": "Execute a command or function, bypassing the usual order of precedence.", + "break": "Terminate execution of a block within your processes scope", + "return": "Exits current function scope", + "exit": "Exit murex", + "expr": "Expressions: mathematical, string comparisons, logical operators", + "false": "Returns a `false` value", + "foreach": "Iterate through an array", + "formap": "Iterate through a map or other collection of data", + "for": "A more familiar iteration loop to existing developers", + "fg": "Sends a background process into the foreground", + "runmode": "Alter the scheduler's behaviour at higher scoping level", + "rand": "Random field generator", + "get-type": "Returns the data-type of a variable or pipe", + "exitnum": "Output the exit number of the previous process", + "pt": "Pipe telemetry. Writes data-types and bytes written", + "get": "Makes a standard HTTP request and returns the result as a JSON object", + "g": "Glob pattern matching for file system objects (eg `*.txt`)", + "if": "Conditional statement to execute different blocks of code depending on the result of the condition", + "source": "Import Murex code from another file or code block", + "is-null": "Checks if a variable is null or undefined", + "mjoin": "Joins a list or array into a single string", + "fid-killall": "Terminate all running Murex functions in current session", + "fid-kill": "Terminate a running Murex function", + "left": "Left substring every item in a list", + "f": "Lists or filters file system objects (eg files)", + "which": "Locate command origin", + "lockfile": "Create and manage lock files", + "and": "Returns `true` or `false` depending on whether multiple conditions are met", + "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "while": "Loop until condition false", + "man-summary": "Outputs a man page summary of a command", + "match": "Match an exact value in an array", + "event": "Event driven programming for shell scripts", + "murex-package": "Murex's package manager", + "version": "Get Murex version", + "murex-docs": "Displays the man pages for Murex builtins", + "continue": "Terminate process of a block within a caller function", + "not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "devnull": "null function. Similar to /dev/null", + "open": "Open a file with a preferred handler", + "os": "Output the auto-detected OS name", + "out": "Print a string to the stdout with a trailing new line character", + "tout": "Print a string to the stdout and set it's data-type", + "man-get-flags": "Parses man page files for command line flags", + "trypipe": "Checks for non-zero exits of each function in a pipeline", + "post": "HTTP POST request with a JSON-parsable return", + "prepend": "Add data to the start of an array", + "pretty": "Prettifies JSON to make it human readable", + "struct-keys": "Outputs all the keys in a structure as a file path", + "private": "Define a private function block", + "time": "Returns the execution run time of a command or block", + "function": "Define a function block", + "escape": "Escape or unescape input", "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", - "read": "`read` a line of input from the user and store as a variable", - "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", - "format": "Reformat one data-type into another data-type", - "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "regexp": "Regexp tools for arrays / lists of strings", - "open-image": "Renders bitmap image data on your terminal", - "mtac": "Reverse the order of an array", - "right": "Right substring every item in a list", - "round": "Round a number by a user defined precision", - "signal": "Sends a signal RPC", - "summary": "Defines a summary help text for a command", - "config": "Query or define Murex runtime settings", - "runtime": "Returns runtime information on the internal state of Murex", - "test": "Murex's test framework - define tests, run tests and debug shell scripts", - "msort": "Sorts an array - data type agnostic", - "jsplit": "Splits stdin into a JSON array based on a regex parameter", - "trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "tryerr": "Handles errors inside a block of code", - "a": "A sophisticated yet simple way to stream an array or list (mkarray)", - "switch": "Blocks of cascading conditionals", - "autocomplete": "Set definitions for tab-completion in the command line", - "tabulate": "Table transformation tools", - "true": "Returns a `true` value", - "try": "Handles non-zero exits inside a block of code", - "die": "Terminate murex with an exit number of 1 (deprecated)", - "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "murex-parser": "Runs the Murex parser against a block of code", + "read": "`read` a line of input from the user and store as a variable", + "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "format": "Reformat one data-type into another data-type", + "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "regexp": "Regexp tools for arrays / lists of strings", + "open-image": "Renders bitmap image data on your terminal", + "mtac": "Reverse the order of an array", + "right": "Right substring every item in a list", + "round": "Round a number by a user defined precision", + "signal": "Sends a signal RPC", + "summary": "Defines a summary help text for a command", + "config": "Query or define Murex runtime settings", + "runtime": "Returns runtime information on the internal state of Murex", + "test": "Murex's test framework - define tests, run tests and debug shell scripts", + "msort": "Sorts an array - data type agnostic", + "jsplit": "Splits stdin into a JSON array based on a regex parameter", + "trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "tryerr": "Handles errors inside a block of code", + "a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "switch": "Blocks of cascading conditionals", + "autocomplete": "Set definitions for tab-completion in the command line", + "tabulate": "Table transformation tools", + "true": "Returns a `true` value", + "try": "Handles non-zero exits inside a block of code", + "die": "Terminate murex with an exit number of 1 (deprecated)", + "let": "Evaluate a mathematical function and assign to variable (deprecated)", + "murex-parser": "Runs the Murex parser against a block of code", + "select": "Inlining SQL into shell pipelines", - "bz2": "Decompress a bz2 file", + "bz2": "Decompress a bz2 file", "base64": "Encode or decode a base64 string", - "gz": "Compress or decompress a gzip file", - "qr": "Creates a QR code from stdin", - "sleep": "Suspends the shell for a number of seconds", + "gz": "Compress or decompress a gzip file", + "qr": "Creates a QR code from stdin", + "sleep": "Suspends the shell for a number of seconds", - "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "commands/addheading": "Adds headings to a table", - "commands/prefix": "Prefix a string to every item in a list", - "commands/suffix": "Prefix a string to every item in a list", - "commands/alias": "Create an alias for a command", - "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "commands/append": "Add data to the end of an array", - "commands/bg": "Run processes in the background", - "commands/cpuarch": "Output the hosts CPU architecture", - "commands/cpucount": "Output the number of CPU cores available on your host", - "commands/catch": "Handles the exception code raised by `try` or `trypipe`", - "commands/cd": "Change (working) directory", - "commands/list.case": "Changes the character case of a string or all elements in an array", - "commands/bexists": "Check which builtins exist", - "commands/history": "Outputs murex's command history", - "commands/count": "Count items in a map, list or array", - "commands/2darray": "Create a 2D JSON array from multiple input sources", - "commands/ja": "A sophisticated yet simply way to build a JSON array", - "commands/map": "Creates a map from two data sources", - "commands/pipe": "Manage Murex named pipes", - "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "commands/tmp": "Create a temporary file and write to it", - "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "commands/debug": "Debugging information", - "commands/export": "Define an environmental variable and set it's value", - "commands/args": "Command line flag parser for Murex shell scripting", - "commands/global": "Define a global variable and set it's value", - "commands/openagent": "Creates a handler function for `open`", - "commands/method": "Define a methods supported data-types", - "commands/cast": "Alters the data-type of the previous function without altering its output", - "commands/set": "Define a variable (typically local) and set it's value", - "commands/unsafe": "Execute a block of code, always returning a zero exit number", - "commands/type": "Command type (function, builtin, alias, etc)", - "commands/fid-list": "Lists all running functions within the current Murex session", - "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "commands/err": "Print a line to the stderr", - "commands/esccli": "Escapes an array so output is valid shell code", - "commands/eschtml": "Encode or decodes text for HTML", - "commands/escurl": "Encode or decodes text for the URL", - "commands/exec": "Runs an executable", - "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", - "commands/break": "Terminate execution of a block within your processes scope", - "commands/return": "Exits current function scope", - "commands/exit": "Exit murex", - "commands/expr": "Expressions: mathematical, string comparisons, logical operators", - "commands/false": "Returns a `false` value", - "commands/foreach": "Iterate through an array", - "commands/formap": "Iterate through a map or other collection of data", - "commands/for": "A more familiar iteration loop to existing developers", - "commands/fg": "Sends a background process into the foreground", - "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", - "commands/rand": "Random field generator", - "commands/get-type": "Returns the data-type of a variable or pipe", - "commands/exitnum": "Output the exit number of the previous process", - "commands/pt": "Pipe telemetry. Writes data-types and bytes written", - "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", - "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", - "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "commands/source": "Import Murex code from another file or code block", - "commands/is-null": "Checks if a variable is null or undefined", - "commands/mjoin": "Joins a list or array into a single string", - "commands/fid-killall": "Terminate all running Murex functions in current session", - "commands/fid-kill": "Terminate a running Murex function", - "commands/left": "Left substring every item in a list", - "commands/f": "Lists or filters file system objects (eg files)", - "commands/which": "Locate command origin", - "commands/lockfile": "Create and manage lock files", - "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", - "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "commands/while": "Loop until condition false", - "commands/man-summary": "Outputs a man page summary of a command", - "commands/match": "Match an exact value in an array", - "commands/event": "Event driven programming for shell scripts", - "commands/murex-package": "Murex's package manager", - "commands/version": "Get Murex version", - "commands/murex-docs": "Displays the man pages for Murex builtins", - "commands/continue": "Terminate process of a block within a caller function", - "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "commands/devnull": "null function. Similar to /dev/null", - "commands/open": "Open a file with a preferred handler", - "commands/os": "Output the auto-detected OS name", - "commands/out": "Print a string to the stdout with a trailing new line character", - "commands/tout": "Print a string to the stdout and set it's data-type", - "commands/man-get-flags": "Parses man page files for command line flags", - "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", - "commands/post": "HTTP POST request with a JSON-parsable return", - "commands/prepend": "Add data to the start of an array", - "commands/pretty": "Prettifies JSON to make it human readable", - "commands/struct-keys": "Outputs all the keys in a structure as a file path", - "commands/private": "Define a private function block", - "commands/time": "Returns the execution run time of a command or block", - "commands/function": "Define a function block", - "commands/escape": "Escape or unescape input", - "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", - "commands/read": "`read` a line of input from the user and store as a variable", - "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", - "commands/format": "Reformat one data-type into another data-type", - "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "commands/regexp": "Regexp tools for arrays / lists of strings", - "commands/open-image": "Renders bitmap image data on your terminal", - "commands/mtac": "Reverse the order of an array", - "commands/right": "Right substring every item in a list", - "commands/round": "Round a number by a user defined precision", - "commands/signal": "Sends a signal RPC", - "commands/summary": "Defines a summary help text for a command", - "commands/config": "Query or define Murex runtime settings", - "commands/runtime": "Returns runtime information on the internal state of Murex", - "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", - "commands/msort": "Sorts an array - data type agnostic", - "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", - "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "commands/tryerr": "Handles errors inside a block of code", - "commands/a": "A sophisticated yet simple way to stream an array or list (mkarray)", - "commands/switch": "Blocks of cascading conditionals", - "commands/autocomplete": "Set definitions for tab-completion in the command line", - "commands/tabulate": "Table transformation tools", - "commands/true": "Returns a `true` value", - "commands/try": "Handles non-zero exits inside a block of code", - "commands/die": "Terminate murex with an exit number of 1 (deprecated)", - "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/murex-parser": "Runs the Murex parser against a block of code", - "mkarray/date": "Create arrays of dates", - "mkarray/character": "Making character arrays (a to z)", - "mkarray/decimal": "Create arrays of decimal integers", - "mkarray/non-decimal": "Create arrays of integers from non-decimal number bases", - "mkarray/special": "Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc)", - "optional/select": "Inlining SQL into shell pipelines", - "optional/bz2": "Decompress a bz2 file", - "optional/base64": "Encode or decode a base64 string", - "optional/gz": "Compress or decompress a gzip file", - "optional/qr": "Creates a QR code from stdin", - "optional/sleep": "Suspends the shell for a number of seconds", - "parser/expr-inlined": "Inline expressions", - "parser/c-style-fun": "Inlined commands for expressions and statements", - "parser/range": "Outputs a ranged subset of data from stdin", - "parser/item-index": "Outputs an element from an array, map or table", - "parser/element": "Outputs an element from a nested structure", - "parser/namedpipe": "Reads from a Murex named pipe", - "parser/stdin": "Read the stdin belonging to the parent code block", - "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", - "parser/double-quote": "Initiates or terminates a string (variables expanded)", - "parser/scalar": "Expand values as a scalar", - "parser/brace-quote": "Initiates or terminates a string (variables expanded)", - "parser/create-array": "Quickly generate arrays", - "parser/create-object": "Quickly generate objects (dictionaries / maps)", - "parser/logical-and": "Continues next operation if previous operation passes", - "parser/single-quote": "Initiates or terminates a string (variables not expanded)", - "parser/brace-quote-func": "Write a string to the stdout without new line (deprecated)", - "parser/multiply-by": "Multiplies a variable by the right hand value (expression)", - "parser/multiplication": "Multiplies one numeric value with another (expression)", - "parser/add-with": "Adds the right hand value to a variable (expression)", - "parser/addition": "Adds two numeric values together (expression)", - "parser/subtract-by": "Subtracts a variable by the right hand value (expression)", - "parser/pipe-arrow": "Pipes stdout from the left hand command to stdin of the right hand command", - "parser/subtraction": "Subtracts one numeric value from another (expression)", - "parser/divide-by": "Divides a variable by the right hand value (expression)", - "parser/division": "Divides one numeric value from another (expression)", - "parser/assign-or-merge": "Merges the right hand value to a variable on the left hand side (expression)", - "parser/pipe-generic": "Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command", - "parser/equ": "Evaluate a mathematical function (deprecated)", - "parser/file-append": "Writes stdin to disk - appending contents if file already exists", - "parser/elvis": "Returns the right operand if the left operand is falsy (expression)", - "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined (expression)", - "parser/pipe-err": "Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED)", - "parser/array": "Expand values as an array", - "parser/lambda": "Iterate through structured data", - "parser/curly-brace": "Initiates or terminates a code block", - "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", - "parser/logical-or": "Continues next operation only if previous operation fails", - "parser/tilde": "Home directory path variable", - "events/oncommandcompletion": "Trigger an event upon a command's completion", - "events/onfilesystemchange": "Add a filesystem watch", - "events/onkeypress": "Custom definable key bindings and macros", - "events/onpreview": "Full screen previews for files and command documentation", - "events/onprompt": "Events triggered by changes in state of the interactive shell", - "events/onsecondselapsed": "Events triggered by time intervals", - "events/onsignalreceived": "Trap OS signals", - "types/generic": "generic (primitive)", - "types/bool": "Boolean (primitive)", - "types/commonlog": "Apache httpd \"common\" log format", - "types/csv": "CSV files (and other character delimited tables)", - "types/float": "Floating point number (primitive)", - "types/hcl": "HashiCorp Configuration Language (HCL)", - "types/int": "Whole number (primitive)", - "types/json": "JavaScript Object Notation (JSON)", - "types/jsonc": "Concatenated JSON", - "types/jsonl": "JSON Lines", - "types/num": "Floating point number (primitive)", - "types/path": "Structured object for working with file and directory paths", - "types/paths": "Structured array for working with `$PATH` style data", - "types/str": "string (primitive)", - "types/toml": "Tom's Obvious, Minimal Language (TOML)", - "types/yaml": "YAML Ain't Markup Language (YAML)", - "types/mxjson": "Murex-flavoured JSON (deprecated)", - "variables/numeric": "Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above", - "variables/meta-values": "State information for iteration blocks", - "variables/argv": "Array of the command name and parameters within a given scope", - "variables/columns": "Character width of terminal", - "variables/event_return": "Return values for events", - "variables/hostname": "Hostname of the current machine", - "variables/murex_argv": "Array of the command name and parameters passed to the current shell", - "variables/murex_exe": "Absolute path to running shell", - "variables/params": "Array of the parameters within a given scope", - "variables/pwdhist": "History of each change to the sessions working directory", - "variables/pwd": "Current working directory", - "variables/self": "Meta information about the running scope.", - "variables/shell": "Path of current shell", - "apis/Marshal": "Converts structured memory into a structured file format (eg for stdio)", - "apis/ReadArray": "Read from a data type one array element at a time", - "apis/ReadArrayWithType": "Read from a data type one array element at a time and return the elements contents and data type", - "apis/ReadIndex": "Data type handler for the index, `[`, builtin", - "apis/ReadMap": "Treat data type as a key/value structure and read its contents", - "apis/ReadNotIndex": "Data type handler for the bang-prefixed index, `![`, builtin", - "apis/Unmarshal": "Converts a structured file format into structured memory", - "apis/WriteArray": "Write a data type, one array element at a time", - "apis/lang.ArrayTemplate": "Unmarshals a data type into a Go struct and returns the results as an array", + + "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "commands/addheading": "Adds headings to a table", + "commands/prefix": "Prefix a string to every item in a list", + "commands/suffix": "Prefix a string to every item in a list", + "commands/alias": "Create an alias for a command", + "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "commands/append": "Add data to the end of an array", + "commands/bg": "Run processes in the background", + "commands/cpuarch": "Output the hosts CPU architecture", + "commands/cpucount": "Output the number of CPU cores available on your host", + "commands/catch": "Handles the exception code raised by `try` or `trypipe`", + "commands/cd": "Change (working) directory", + "commands/list.case": "Changes the character case of a string or all elements in an array", + "commands/bexists": "Check which builtins exist", + "commands/history": "Outputs murex's command history", + "commands/count": "Count items in a map, list or array", + "commands/2darray": "Create a 2D JSON array from multiple input sources", + "commands/ja": "A sophisticated yet simply way to build a JSON array", + "commands/map": "Creates a map from two data sources", + "commands/pipe": "Manage Murex named pipes", + "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "commands/tmp": "Create a temporary file and write to it", + "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "commands/debug": "Debugging information", + "commands/export": "Define an environmental variable and set it's value", + "commands/args": "Command line flag parser for Murex shell scripting", + "commands/global": "Define a global variable and set it's value", + "commands/openagent": "Creates a handler function for `open`", + "commands/method": "Define a methods supported data-types", + "commands/cast": "Alters the data-type of the previous function without altering its output", + "commands/set": "Define a variable (typically local) and set it's value", + "commands/unsafe": "Execute a block of code, always returning a zero exit number", + "commands/type": "Command type (function, builtin, alias, etc)", + "commands/fid-list": "Lists all running functions within the current Murex session", + "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "commands/err": "Print a line to the stderr", + "commands/esccli": "Escapes an array so output is valid shell code", + "commands/eschtml": "Encode or decodes text for HTML", + "commands/escurl": "Encode or decodes text for the URL", + "commands/exec": "Runs an executable", + "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", + "commands/break": "Terminate execution of a block within your processes scope", + "commands/return": "Exits current function scope", + "commands/exit": "Exit murex", + "commands/expr": "Expressions: mathematical, string comparisons, logical operators", + "commands/false": "Returns a `false` value", + "commands/foreach": "Iterate through an array", + "commands/formap": "Iterate through a map or other collection of data", + "commands/for": "A more familiar iteration loop to existing developers", + "commands/fg": "Sends a background process into the foreground", + "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", + "commands/rand": "Random field generator", + "commands/get-type": "Returns the data-type of a variable or pipe", + "commands/exitnum": "Output the exit number of the previous process", + "commands/pt": "Pipe telemetry. Writes data-types and bytes written", + "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", + "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", + "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", + "commands/source": "Import Murex code from another file or code block", + "commands/is-null": "Checks if a variable is null or undefined", + "commands/mjoin": "Joins a list or array into a single string", + "commands/fid-killall": "Terminate all running Murex functions in current session", + "commands/fid-kill": "Terminate a running Murex function", + "commands/left": "Left substring every item in a list", + "commands/f": "Lists or filters file system objects (eg files)", + "commands/which": "Locate command origin", + "commands/lockfile": "Create and manage lock files", + "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", + "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "commands/while": "Loop until condition false", + "commands/man-summary": "Outputs a man page summary of a command", + "commands/match": "Match an exact value in an array", + "commands/event": "Event driven programming for shell scripts", + "commands/murex-package": "Murex's package manager", + "commands/version": "Get Murex version", + "commands/murex-docs": "Displays the man pages for Murex builtins", + "commands/continue": "Terminate process of a block within a caller function", + "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "commands/devnull": "null function. Similar to /dev/null", + "commands/open": "Open a file with a preferred handler", + "commands/os": "Output the auto-detected OS name", + "commands/out": "Print a string to the stdout with a trailing new line character", + "commands/tout": "Print a string to the stdout and set it's data-type", + "commands/man-get-flags": "Parses man page files for command line flags", + "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", + "commands/post": "HTTP POST request with a JSON-parsable return", + "commands/prepend": "Add data to the start of an array", + "commands/pretty": "Prettifies JSON to make it human readable", + "commands/struct-keys": "Outputs all the keys in a structure as a file path", + "commands/private": "Define a private function block", + "commands/time": "Returns the execution run time of a command or block", + "commands/function": "Define a function block", + "commands/escape": "Escape or unescape input", + "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "commands/read": "`read` a line of input from the user and store as a variable", + "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "commands/format": "Reformat one data-type into another data-type", + "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "commands/regexp": "Regexp tools for arrays / lists of strings", + "commands/open-image": "Renders bitmap image data on your terminal", + "commands/mtac": "Reverse the order of an array", + "commands/right": "Right substring every item in a list", + "commands/round": "Round a number by a user defined precision", + "commands/signal": "Sends a signal RPC", + "commands/summary": "Defines a summary help text for a command", + "commands/config": "Query or define Murex runtime settings", + "commands/runtime": "Returns runtime information on the internal state of Murex", + "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", + "commands/msort": "Sorts an array - data type agnostic", + "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", + "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "commands/tryerr": "Handles errors inside a block of code", + "commands/a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "commands/switch": "Blocks of cascading conditionals", + "commands/autocomplete": "Set definitions for tab-completion in the command line", + "commands/tabulate": "Table transformation tools", + "commands/true": "Returns a `true` value", + "commands/try": "Handles non-zero exits inside a block of code", + "commands/die": "Terminate murex with an exit number of 1 (deprecated)", + "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", + "commands/murex-parser": "Runs the Murex parser against a block of code", + "mkarray/date": "Create arrays of dates", + "mkarray/character": "Making character arrays (a to z)", + "mkarray/decimal": "Create arrays of decimal integers", + "mkarray/non-decimal": "Create arrays of integers from non-decimal number bases", + "mkarray/special": "Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc)", + "optional/select": "Inlining SQL into shell pipelines", + "optional/bz2": "Decompress a bz2 file", + "optional/base64": "Encode or decode a base64 string", + "optional/gz": "Compress or decompress a gzip file", + "optional/qr": "Creates a QR code from stdin", + "optional/sleep": "Suspends the shell for a number of seconds", + "parser/expr-inlined": "Inline expressions", + "parser/c-style-fun": "Inlined commands for expressions and statements", + "parser/range": "Outputs a ranged subset of data from stdin", + "parser/item-index": "Outputs an element from an array, map or table", + "parser/element": "Outputs an element from a nested structure", + "parser/namedpipe": "Reads from a Murex named pipe", + "parser/stdin": "Read the stdin belonging to the parent code block", + "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", + "parser/double-quote": "Initiates or terminates a string (variables expanded)", + "parser/scalar": "Expand values as a scalar", + "parser/brace-quote": "Initiates or terminates a string (variables expanded)", + "parser/create-array": "Quickly generate arrays", + "parser/create-object": "Quickly generate objects (dictionaries / maps)", + "parser/logical-and": "Continues next operation if previous operation passes", + "parser/single-quote": "Initiates or terminates a string (variables not expanded)", + "parser/brace-quote-func": "Write a string to the stdout without new line (deprecated)", + "parser/multiply-by": "Multiplies a variable by the right hand value (expression)", + "parser/multiplication": "Multiplies one numeric value with another (expression)", + "parser/add-with": "Adds the right hand value to a variable (expression)", + "parser/addition": "Adds two numeric values together (expression)", + "parser/subtract-by": "Subtracts a variable by the right hand value (expression)", + "parser/pipe-arrow": "Pipes stdout from the left hand command to stdin of the right hand command", + "parser/subtraction": "Subtracts one numeric value from another (expression)", + "parser/divide-by": "Divides a variable by the right hand value (expression)", + "parser/division": "Divides one numeric value from another (expression)", + "parser/assign-or-merge": "Merges the right hand value to a variable on the left hand side (expression)", + "parser/pipe-generic": "Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command", + "parser/equ": "Evaluate a mathematical function (deprecated)", + "parser/file-append": "Writes stdin to disk - appending contents if file already exists", + "parser/elvis": "Returns the right operand if the left operand is falsy (expression)", + "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined (expression)", + "parser/pipe-err": "Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED)", + "parser/array": "Expand values as an array", + "parser/lambda": "Iterate through structured data", + "parser/curly-brace": "Initiates or terminates a code block", + "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", + "parser/logical-or": "Continues next operation only if previous operation fails", + "parser/tilde": "Home directory path variable", + "events/oncommandcompletion": "Trigger an event upon a command's completion", + "events/onfilesystemchange": "Add a filesystem watch", + "events/onkeypress": "Custom definable key bindings and macros", + "events/onpreview": "Full screen previews for files and command documentation", + "events/onprompt": "Events triggered by changes in state of the interactive shell", + "events/onsecondselapsed": "Events triggered by time intervals", + "events/onsignalreceived": "Trap OS signals", + "types/generic": "generic (primitive)", + "types/bool": "Boolean (primitive)", + "types/commonlog": "Apache httpd \"common\" log format", + "types/csv": "CSV files (and other character delimited tables)", + "types/float": "Floating point number (primitive)", + "types/hcl": "HashiCorp Configuration Language (HCL)", + "types/int": "Whole number (primitive)", + "types/json": "JavaScript Object Notation (JSON)", + "types/jsonc": "Concatenated JSON", + "types/jsonl": "JSON Lines", + "types/num": "Floating point number (primitive)", + "types/path": "Structured object for working with file and directory paths", + "types/paths": "Structured array for working with `$PATH` style data", + "types/str": "string (primitive)", + "types/toml": "Tom's Obvious, Minimal Language (TOML)", + "types/yaml": "YAML Ain't Markup Language (YAML)", + "types/mxjson": "Murex-flavoured JSON (deprecated)", + "variables/numeric": "Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above", + "variables/meta-values": "State information for iteration blocks", + "variables/argv": "Array of the command name and parameters within a given scope", + "variables/columns": "Character width of terminal", + "variables/event_return": "Return values for events", + "variables/hostname": "Hostname of the current machine", + "variables/murex_argv": "Array of the command name and parameters passed to the current shell", + "variables/murex_exe": "Absolute path to running shell", + "variables/params": "Array of the parameters within a given scope", + "variables/pwdhist": "History of each change to the sessions working directory", + "variables/pwd": "Current working directory", + "variables/self": "Meta information about the running scope.", + "variables/shell": "Path of current shell", + "apis/Marshal": "Converts structured memory into a structured file format (eg for stdio)", + "apis/ReadArray": "Read from a data type one array element at a time", + "apis/ReadArrayWithType": "Read from a data type one array element at a time and return the elements contents and data type", + "apis/ReadIndex": "Data type handler for the index, `[`, builtin", + "apis/ReadMap": "Treat data type as a key/value structure and read its contents", + "apis/ReadNotIndex": "Data type handler for the bang-prefixed index, `![`, builtin", + "apis/Unmarshal": "Converts a structured file format into structured memory", + "apis/WriteArray": "Write a data type, one array element at a time", + "apis/lang.ArrayTemplate": "Unmarshals a data type into a Go struct and returns the results as an array", "apis/lang.ArrayWithTypeTemplate": "Unmarshals a data type into a Go struct and returns the results as an array with data type included", - "apis/lang.IndexTemplateObject": "Returns element(s) from a data structure", - "apis/lang.IndexTemplateTable": "Returns element(s) from a table", - "apis/lang.MarshalData": "Converts structured memory into a Murex data-type (eg for stdio)", - "apis/lang.UnmarshalData": "Converts a Murex data-type into structured memory", - "user-guide/ansi": "Infixed constants that return ANSI escape sequences", - "user-guide/bang-prefix": "Bang prefixing to reverse default actions", - "user-guide/code-block": "Overview of how code blocks are parsed", - "user-guide/fileref": "How to track what code was loaded and from where", - "user-guide/hint-text": "A status bar for your shell", - "user-guide/integrations": "Default integrations shipped with Murex", - "user-guide/interactive-shell": "What's different about Murex's interactive shell?", - "user-guide/job-control": "How to manage jobs with Murex", - "user-guide/modules": "An introduction to Murex modules and packages", - "user-guide/namedpipes": "A detailed breakdown of named pipes in Murex", + "apis/lang.IndexTemplateObject": "Returns element(s) from a data structure", + "apis/lang.IndexTemplateTable": "Returns element(s) from a table", + "apis/lang.MarshalData": "Converts structured memory into a Murex data-type (eg for stdio)", + "apis/lang.UnmarshalData": "Converts a Murex data-type into structured memory", + "user-guide/ansi": "Infixed constants that return ANSI escape sequences", + "user-guide/bang-prefix": "Bang prefixing to reverse default actions", + "user-guide/code-block": "Overview of how code blocks are parsed", + "user-guide/fileref": "How to track what code was loaded and from where", + "user-guide/hint-text": "A status bar for your shell", + "user-guide/integrations": "Default integrations shipped with Murex", + "user-guide/interactive-shell": "What's different about Murex's interactive shell?", + "user-guide/job-control": "How to manage jobs with Murex", + "user-guide/modules": "An introduction to Murex modules and packages", + "user-guide/namedpipes": "A detailed breakdown of named pipes in Murex", "user-guide/operators-and-tokens": "All supported operators and tokens", - "user-guide/pipeline": "Overview of what a \"pipeline\" is", - "user-guide/profile": "A breakdown of the different files loaded on start up", - "user-guide/reserved-vars": "Special variables reserved by Murex", - "user-guide/rosetta-stone": "A tabulated list of Bashism's and their equivalent Murex syntax", - "user-guide/schedulers": "Overview of the different schedulers (or 'run modes') in Murex", - "user-guide/strict-types": "Expressions can auto-convert types or strictly honour data types", - "user-guide/terminal-keys": "A list of all the terminal hotkeys and their uses", - "user-guide/scoping": "How scoping works within Murex", - "integrations/chatgpt": "How to enable ChatGPT hints", - "integrations/cheatsh": "Cheatsheets provided by cheat.sh", - "integrations/kitty": "Get more out of Kitty terminal emulator", - "integrations/make": "`make` integrations", - "integrations/man-pages": "Linux/UNIX `man` page integrations", - "integrations/spellcheck": "How to enable inline spellchecking", - "integrations/terminology": "Get more out of Terminology terminal emulator", - "integrations/direnv": "Directory specific environmental variables", - "integrations/yarn": "Working with `yarn` and `package.json`", - "integrations/iterm2": "Get more out of iTerm2 terminal emulator", - "changelog/v2.0": "This release comes with spellchecking, inlined images, smarter syntax completion and more", - "changelog/v2.1": "This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details.", - "changelog/v2.10": "This release brings a few minor improvements and bug fixes rather than big new headline features.", - "changelog/v2.11": "This release mainly focuses on refinements in performance and usability, rather than introducing new features", - "changelog/v2.2": "This is mainly a bug fix release but it does include one breaking change for `config`. Please read for details.", - "changelog/v2.3": "This release includes significant changes to the interactive terminal", - "changelog/v2.4": "This release introduces a strict mode for variables, new builtin, performance improvements, and better error messages; plus a potential breaking change", - "changelog/v2.5": "This release introduces a number of new builtins, fixes some regression bugs and supercharges the `select` optional builtin (which I plan to include into the core builtins for non-Windows users in the next release).", - "changelog/v2.6": "This update has introduced a potential breaking change: variables now need to be defined before usage otherwise the commandline will fail. Read notes to learn how to disable this feature where needed. Also included in this release is the `select` command as part of the standard build.", - "changelog/v2.7": "This update has introduced another potential breaking change for your safety: zero length arrays now fail by default. Also errors inside subshells will cause the parent command to fail if ran inside a `try` or `trypipe` block.", - "changelog/v2.8": "This release comes with a number of experimental but stable features that might eventually become standard practice. The features are there to use if you with but adjacent from the older code so there is zero risk in updating to this version.", - "changelog/v2.9": "This release focuses on testing and REPL usability improvements but also includes updates several new run modes to make error handling easier in larger scripts.", - "changelog/v3.0": "This is a major release that brings a significant number of changes and improvements, including a complete overhaul of the parser. Backwards compatibility is a high priority however these new features bring greater readability and consistency to shell scripting. So while the older syntax remains for compatibility, it is worth migrating over to the newer syntax for all new code being written", - "changelog/v3.1": "This release includes mostly bug fixes and new experimental features which are opt into. To enable all experimental features, set the environmental variable `MUREX_EXPERIMENTAL` to any value. Or you can enable specific features individually via `config`", - "changelog/v4.0": "This release sees significant improvements for use with non-latin characters in both the interactive prompt and shell scripting. It introduces new syntax to make working with structured data even easier than before. As well as new data types and smoother user experience.", - "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", - "changelog/v4.2": "Murex usage has raised considerably in recent weeks. This release addresses a number of feature requests and bugs raised on Github.", - "changelog/v4.3": "This brings improved support on Windows plus one breaking change from the previous release (v4.2)", - "changelog/v4.4": "v4.4 features two new builtins, improvements in testing, and automatic generation of autocompletion suggestions backed by man page parsing. Plus there has been a lot of focus on improving _readline_ responsiveness", - "changelog/v5.0": "v5.0 is a massive release. It brings along changes to syntax, new operators as well as new builtins, reserved variables and a new event", - "changelog/v5.1": "This release brings new operators and a builtin, all for managing null types. There is also a substantial revamp to readline's responsiveness.", - "changelog/v5.2": "The v5.2 release introduces significant new features and improvements for those using Murex as their interactive shell. Many of these features are unique to Murex.", - "changelog/v5.3": "Caching has been vastly improved in this release due to a new sqlite3-backed persistent `cache.db`. There have also been some improvements to `[f1]` help pages", - "changelog/v6.0": "Despite this being a new major version release, it is a vary minor update. Aside from a handful of bugfixes, the most significant change is notice of deprecation for `=`, `let`, and `?`.", - "changelog/v6.1": "This release sees a massive jump in event-driven capabilities as well as several new features and bug fixes.", - "changelog/v6.2": "Bug fix release", + "user-guide/pipeline": "Overview of what a \"pipeline\" is", + "user-guide/profile": "A breakdown of the different files loaded on start up", + "user-guide/reserved-vars": "Special variables reserved by Murex", + "user-guide/rosetta-stone": "A tabulated list of Bashism's and their equivalent Murex syntax", + "user-guide/schedulers": "Overview of the different schedulers (or 'run modes') in Murex", + "user-guide/strict-types": "Expressions can auto-convert types or strictly honour data types", + "user-guide/terminal-keys": "A list of all the terminal hotkeys and their uses", + "user-guide/scoping": "How scoping works within Murex", + "integrations/chatgpt": "How to enable ChatGPT hints", + "integrations/cheatsh": "Cheatsheets provided by cheat.sh", + "integrations/kitty": "Get more out of Kitty terminal emulator", + "integrations/make": "`make` integrations", + "integrations/man-pages": "Linux/UNIX `man` page integrations", + "integrations/spellcheck": "How to enable inline spellchecking", + "integrations/terminology": "Get more out of Terminology terminal emulator", + "integrations/direnv": "Directory specific environmental variables", + "integrations/yarn": "Working with `yarn` and `package.json`", + "integrations/iterm2": "Get more out of iTerm2 terminal emulator", + "changelog/v2.0": "This release comes with spellchecking, inlined images, smarter syntax completion and more", + "changelog/v2.1": "This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details.", + "changelog/v2.10": "This release brings a few minor improvements and bug fixes rather than big new headline features.", + "changelog/v2.11": "This release mainly focuses on refinements in performance and usability, rather than introducing new features", + "changelog/v2.2": "This is mainly a bug fix release but it does include one breaking change for `config`. Please read for details.", + "changelog/v2.3": "This release includes significant changes to the interactive terminal", + "changelog/v2.4": "This release introduces a strict mode for variables, new builtin, performance improvements, and better error messages; plus a potential breaking change", + "changelog/v2.5": "This release introduces a number of new builtins, fixes some regression bugs and supercharges the `select` optional builtin (which I plan to include into the core builtins for non-Windows users in the next release).", + "changelog/v2.6": "This update has introduced a potential breaking change: variables now need to be defined before usage otherwise the commandline will fail. Read notes to learn how to disable this feature where needed. Also included in this release is the `select` command as part of the standard build.", + "changelog/v2.7": "This update has introduced another potential breaking change for your safety: zero length arrays now fail by default. Also errors inside subshells will cause the parent command to fail if ran inside a `try` or `trypipe` block.", + "changelog/v2.8": "This release comes with a number of experimental but stable features that might eventually become standard practice. The features are there to use if you with but adjacent from the older code so there is zero risk in updating to this version.", + "changelog/v2.9": "This release focuses on testing and REPL usability improvements but also includes updates several new run modes to make error handling easier in larger scripts.", + "changelog/v3.0": "This is a major release that brings a significant number of changes and improvements, including a complete overhaul of the parser. Backwards compatibility is a high priority however these new features bring greater readability and consistency to shell scripting. So while the older syntax remains for compatibility, it is worth migrating over to the newer syntax for all new code being written", + "changelog/v3.1": "This release includes mostly bug fixes and new experimental features which are opt into. To enable all experimental features, set the environmental variable `MUREX_EXPERIMENTAL` to any value. Or you can enable specific features individually via `config`", + "changelog/v4.0": "This release sees significant improvements for use with non-latin characters in both the interactive prompt and shell scripting. It introduces new syntax to make working with structured data even easier than before. As well as new data types and smoother user experience.", + "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", + "changelog/v4.2": "Murex usage has raised considerably in recent weeks. This release addresses a number of feature requests and bugs raised on Github.", + "changelog/v4.3": "This brings improved support on Windows plus one breaking change from the previous release (v4.2)", + "changelog/v4.4": "v4.4 features two new builtins, improvements in testing, and automatic generation of autocompletion suggestions backed by man page parsing. Plus there has been a lot of focus on improving _readline_ responsiveness", + "changelog/v5.0": "v5.0 is a massive release. It brings along changes to syntax, new operators as well as new builtins, reserved variables and a new event", + "changelog/v5.1": "This release brings new operators and a builtin, all for managing null types. There is also a substantial revamp to readline's responsiveness.", + "changelog/v5.2": "The v5.2 release introduces significant new features and improvements for those using Murex as their interactive shell. Many of these features are unique to Murex.", + "changelog/v5.3": "Caching has been vastly improved in this release due to a new sqlite3-backed persistent `cache.db`. There have also been some improvements to `[f1]` help pages", + "changelog/v6.0": "Despite this being a new major version release, it is a vary minor update. Aside from a handful of bugfixes, the most significant change is notice of deprecation for `=`, `let`, and `?`.", + "changelog/v6.1": "This release sees a massive jump in event-driven capabilities as well as several new features and bug fixes.", + "changelog/v6.2": "Bug fix release", + } + Synonym = map[string]string{ - "key-code": "key-code", - "addheading": "addheading", - "prefix": "prefix", - "list.prefix": "prefix", - "suffix": "suffix", - "list.suffix": "suffix", - "alias": "alias", - "!alias": "alias", - "alter": "alter", - "~>": "alter", - "append": "append", - "list.append": "append", - "bg": "bg", - "cpuarch": "cpuarch", - "sys.cpu.arch": "cpuarch", - "cpucount": "cpucount", - "sys.cpu.count": "cpucount", - "catch": "catch", - "!catch": "catch", - "cd": "cd", - "list.case": "list.case", - "bexists": "bexists", - "history": "history", - "count": "count", - "len": "count", - "2darray": "2darray", - "ja": "ja", - "map": "map", - "pipe": "pipe", - "!pipe": "pipe", - "ta": "ta", - "tmp": "tmp", - "datetime": "datetime", - "str.datetime": "datetime", - "debug": "debug", - "export": "export", - "!export": "export", - "unset": "export", - "var.env": "export", - "!var.env": "export", - "args": "args", - "global": "global", - "!global": "global", - "openagent": "openagent", - "!openagent": "openagent", - "method": "method", - "cast": "cast", - "set": "set", - "!set": "set", - "unsafe": "unsafe", - "type": "type", - "fid-list": "fid-list", - "jobs": "fid-list", - "getfile": "getfile", - "err": "err", - "esccli": "esccli", - "eschtml": "eschtml", - "!eschtml": "eschtml", - "escurl": "escurl", - "!escurl": "escurl", - "exec": "exec", - "command": "exec", - "exec.file": "exec", - "fexec": "fexec", - "builtin": "fexec", - "exec.builtin": "fexec", - "exec.function": "fexec", - "exec.private": "fexec", - "break": "break", - "return": "return", - "exit": "exit", - "expr": "expr", - "false": "false", - "foreach": "foreach", - "formap": "formap", - "for": "for", - "fg": "fg", - "runmode": "runmode", - "rand": "rand", - "get-type": "get-type", - "exitnum": "exitnum", - "pt": "pt", - "get": "get", - "g": "g", - "!g": "g", - "if": "if", - "!if": "if", - "source": "source", - ".": "source", - "is-null": "is-null", - "mjoin": "mjoin", - "list.join": "mjoin", - "fid-killall": "fid-killall", - "fid-kill": "fid-kill", - "left": "left", - "list.left": "left", - "f": "f", - "which": "which", - "lockfile": "lockfile", - "and": "and", - "!and": "and", - "or": "or", - "!or": "or", - "while": "while", - "!while": "while", - "man-summary": "man-summary", - "help.man.summary": "man-summary", - "match": "match", - "!match": "match", - "list.str": "match", - "!list.str": "match", - "event": "event", - "!event": "event", - "murex-package": "murex-package", - "version": "version", - "murex-docs": "murex-docs", - "help": "murex-docs", - "continue": "continue", - "!": "not-func", - "not": "not-func", - "null": "devnull", - "open": "open", - "os": "os", - "sys.os": "os", - "out": "out", - "echo": "out", - "tout": "tout", - "man-get-flags": "man-get-flags", - "trypipe": "trypipe", - "post": "post", - "prepend": "prepend", - "list.prepend": "prepend", - "pretty": "pretty", - "struct-keys": "struct-keys", - "private": "private", - "time": "time", - "function": "function", - "!function": "function", - "escape": "escape", - "!escape": "escape", + + "key-code": "key-code", + "addheading": "addheading", + "prefix": "prefix", + "list.prefix": "prefix", + "suffix": "suffix", + "list.suffix": "suffix", + "alias": "alias", + "!alias": "alias", + "alter": "alter", + "~>": "alter", + "append": "append", + "list.append": "append", + "bg": "bg", + "cpuarch": "cpuarch", + "sys.cpu.arch": "cpuarch", + "cpucount": "cpucount", + "sys.cpu.count": "cpucount", + "catch": "catch", + "!catch": "catch", + "cd": "cd", + "list.case": "list.case", + "bexists": "bexists", + "history": "history", + "count": "count", + "len": "count", + "2darray": "2darray", + "ja": "ja", + "map": "map", + "pipe": "pipe", + "!pipe": "pipe", + "ta": "ta", + "tmp": "tmp", + "datetime": "datetime", + "str.datetime": "datetime", + "debug": "debug", + "export": "export", + "!export": "export", + "unset": "export", + "var.env": "export", + "!var.env": "export", + "args": "args", + "global": "global", + "!global": "global", + "openagent": "openagent", + "!openagent": "openagent", + "method": "method", + "cast": "cast", + "set": "set", + "!set": "set", + "unsafe": "unsafe", + "type": "type", + "fid-list": "fid-list", + "jobs": "fid-list", + "getfile": "getfile", + "err": "err", + "esccli": "esccli", + "eschtml": "eschtml", + "!eschtml": "eschtml", + "escurl": "escurl", + "!escurl": "escurl", + "exec": "exec", + "command": "exec", + "exec.file": "exec", + "fexec": "fexec", + "builtin": "fexec", + "exec.builtin": "fexec", + "exec.function": "fexec", + "exec.private": "fexec", + "break": "break", + "return": "return", + "exit": "exit", + "expr": "expr", + "false": "false", + "foreach": "foreach", + "formap": "formap", + "for": "for", + "fg": "fg", + "runmode": "runmode", + "rand": "rand", + "get-type": "get-type", + "exitnum": "exitnum", + "pt": "pt", + "get": "get", + "g": "g", + "!g": "g", + "if": "if", + "!if": "if", + "source": "source", + ".": "source", + "is-null": "is-null", + "mjoin": "mjoin", + "list.join": "mjoin", + "fid-killall": "fid-killall", + "fid-kill": "fid-kill", + "left": "left", + "list.left": "left", + "f": "f", + "which": "which", + "lockfile": "lockfile", + "and": "and", + "!and": "and", + "or": "or", + "!or": "or", + "while": "while", + "!while": "while", + "man-summary": "man-summary", + "help.man.summary": "man-summary", + "match": "match", + "!match": "match", + "list.str": "match", + "!list.str": "match", + "event": "event", + "!event": "event", + "murex-package": "murex-package", + "version": "version", + "murex-docs": "murex-docs", + "help": "murex-docs", + "continue": "continue", + "!": "not-func", + "not": "not-func", + "null": "devnull", + "open": "open", + "os": "os", + "sys.os": "os", + "out": "out", + "echo": "out", + "tout": "tout", + "man-get-flags": "man-get-flags", + "trypipe": "trypipe", + "post": "post", + "prepend": "prepend", + "list.prepend": "prepend", + "pretty": "pretty", + "struct-keys": "struct-keys", + "private": "private", + "time": "time", + "function": "function", + "!function": "function", + "escape": "escape", + "!escape": "escape", "murex-update-exe-list": "murex-update-exe-list", - "read": "read", - "tread": "tread", - "format": "format", - "rx": "rx", - "!rx": "rx", - "regexp": "regexp", - "!regexp": "regexp", - "list.regex": "regexp", - "!list.regex": "regexp", - "open-image": "open-image", - "mtac": "mtac", - "list.reverse": "mtac", - "right": "right", - "list.right": "right", - "round": "round", - "num.round": "round", - "signal": "signal", - "summary": "summary", - "!summary": "summary", - "config": "config", - "!config": "config", - "runtime": "runtime", - "builtins": "runtime", - "shell.runtime": "runtime", - "test": "test", - "!test": "test", - "msort": "msort", - "list.sort": "msort", - "jsplit": "jsplit", - "str.split": "jsplit", - "trypipeerr": "trypipeerr", - "tryerr": "tryerr", - "a": "a", - "mkarray": "a", - "switch": "switch", - "autocomplete": "autocomplete", - "tabulate": "tabulate", - "true": "true", - "try": "try", - "die": "die", - "let": "let", - "murex-parser": "murex-parser", + "read": "read", + "tread": "tread", + "format": "format", + "rx": "rx", + "!rx": "rx", + "regexp": "regexp", + "!regexp": "regexp", + "list.regex": "regexp", + "!list.regex": "regexp", + "open-image": "open-image", + "mtac": "mtac", + "list.reverse": "mtac", + "right": "right", + "list.right": "right", + "round": "round", + "num.round": "round", + "signal": "signal", + "summary": "summary", + "!summary": "summary", + "config": "config", + "!config": "config", + "runtime": "runtime", + "builtins": "runtime", + "shell.runtime": "runtime", + "test": "test", + "!test": "test", + "msort": "msort", + "list.sort": "msort", + "jsplit": "jsplit", + "str.split": "jsplit", + "trypipeerr": "trypipeerr", + "tryerr": "tryerr", + "a": "a", + "mkarray": "a", + "switch": "switch", + "autocomplete": "autocomplete", + "tabulate": "tabulate", + "true": "true", + "try": "try", + "die": "die", + "let": "let", + "murex-parser": "murex-parser", - "select": "optional/select", + + "select": "optional/select", "table.select": "optional/select", - "!bz2": "optional/bz2", - "base64": "optional/base64", - "!base64": "optional/base64", - "gz": "optional/gz", - "!gz": "optional/gz", - "qr": "optional/qr", - "sleep": "optional/sleep", + "!bz2": "optional/bz2", + "base64": "optional/base64", + "!base64": "optional/base64", + "gz": "optional/gz", + "!gz": "optional/gz", + "qr": "optional/qr", + "sleep": "optional/sleep", - "expr-inlined": "parser/expr-inlined", - "c-style-fun": "parser/c-style-fun", - "@[": "parser/range", - "[": "parser/item-index", - "![": "parser/item-index", - "item-index": "parser/item-index", - "index": "parser/item-index", - "[[": "parser/element", - "element": "parser/element", + + "expr-inlined": "parser/expr-inlined", + "c-style-fun": "parser/c-style-fun", + "@[": "parser/range", + "[": "parser/item-index", + "![": "parser/item-index", + "item-index": "parser/item-index", + "index": "parser/item-index", + "[[": "parser/element", + "element": "parser/element", "(murex named pipe)": "parser/namedpipe", - "<>": "parser/namedpipe", - "read-named-pipe": "parser/namedpipe", - "": "parser/stdin", - ">": "parser/file-truncate", - "|>": "parser/file-truncate", - "fwrite": "parser/file-truncate", - "double-quote": "parser/double-quote", - "scalar": "parser/scalar", - "brace-quote": "parser/brace-quote", - "create-array": "parser/create-array", - "create-object": "parser/create-object", - "logical-and": "parser/logical-and", - "single-quote": "parser/single-quote", - "(": "parser/brace-quote-func", - "multiply-by": "parser/multiply-by", - "multiplication": "parser/multiplication", - "add-with": "parser/add-with", - "addition": "parser/addition", - "subtract-by": "parser/subtract-by", - "pipe-arrow": "parser/pipe-arrow", - "subtraction": "parser/subtraction", - "divide-by": "parser/divide-by", - "division": "parser/division", - "assign-or-merge": "parser/assign-or-merge", - "pipe-generic": "parser/pipe-generic", - "=": "parser/equ", - ">>": "parser/file-append", - "fappend": "parser/file-append", - "elvis": "parser/elvis", - "null-coalescing": "parser/null-coalescing", - "pipe-err": "parser/pipe-err", - "array": "parser/array", - "lambda": "parser/lambda", - "curly-brace": "parser/curly-brace", - "pipe-posix": "parser/pipe-posix", - "logical-or": "parser/logical-or", - "tilde": "parser/tilde", + "<>": "parser/namedpipe", + "read-named-pipe": "parser/namedpipe", + "": "parser/stdin", + ">": "parser/file-truncate", + "|>": "parser/file-truncate", + "fwrite": "parser/file-truncate", + "double-quote": "parser/double-quote", + "scalar": "parser/scalar", + "brace-quote": "parser/brace-quote", + "create-array": "parser/create-array", + "create-object": "parser/create-object", + "logical-and": "parser/logical-and", + "single-quote": "parser/single-quote", + "(": "parser/brace-quote-func", + "multiply-by": "parser/multiply-by", + "multiplication": "parser/multiplication", + "add-with": "parser/add-with", + "addition": "parser/addition", + "subtract-by": "parser/subtract-by", + "pipe-arrow": "parser/pipe-arrow", + "subtraction": "parser/subtraction", + "divide-by": "parser/divide-by", + "division": "parser/division", + "assign-or-merge": "parser/assign-or-merge", + "pipe-generic": "parser/pipe-generic", + "=": "parser/equ", + ">>": "parser/file-append", + "fappend": "parser/file-append", + "elvis": "parser/elvis", + "null-coalescing": "parser/null-coalescing", + "pipe-err": "parser/pipe-err", + "array": "parser/array", + "lambda": "parser/lambda", + "curly-brace": "parser/curly-brace", + "pipe-posix": "parser/pipe-posix", + "logical-or": "parser/logical-or", + "tilde": "parser/tilde", - "commands/key-code": "commands/key-code", - "commands/addheading": "commands/addheading", - "commands/prefix": "commands/prefix", - "commands/list.prefix": "commands/prefix", - "commands/suffix": "commands/suffix", - "commands/list.suffix": "commands/suffix", - "commands/alias": "commands/alias", - "commands/!alias": "commands/alias", - "commands/alter": "commands/alter", - "commands/~>": "commands/alter", - "commands/append": "commands/append", - "commands/list.append": "commands/append", - "commands/bg": "commands/bg", - "commands/cpuarch": "commands/cpuarch", - "commands/sys.cpu.arch": "commands/cpuarch", - "commands/cpucount": "commands/cpucount", - "commands/sys.cpu.count": "commands/cpucount", - "commands/catch": "commands/catch", - "commands/!catch": "commands/catch", - "commands/cd": "commands/cd", - "commands/list.case": "commands/list.case", - "commands/bexists": "commands/bexists", - "commands/history": "commands/history", - "commands/count": "commands/count", - "commands/len": "commands/count", - "commands/2darray": "commands/2darray", - "commands/ja": "commands/ja", - "commands/map": "commands/map", - "commands/pipe": "commands/pipe", - "commands/!pipe": "commands/pipe", - "commands/ta": "commands/ta", - "commands/tmp": "commands/tmp", - "commands/datetime": "commands/datetime", - "commands/str.datetime": "commands/datetime", - "commands/debug": "commands/debug", - "commands/export": "commands/export", - "commands/!export": "commands/export", - "commands/unset": "commands/export", - "commands/var.env": "commands/export", - "commands/!var.env": "commands/export", - "commands/args": "commands/args", - "commands/global": "commands/global", - "commands/!global": "commands/global", - "commands/openagent": "commands/openagent", - "commands/!openagent": "commands/openagent", - "commands/method": "commands/method", - "commands/cast": "commands/cast", - "commands/set": "commands/set", - "commands/!set": "commands/set", - "commands/unsafe": "commands/unsafe", - "commands/type": "commands/type", - "commands/fid-list": "commands/fid-list", - "commands/jobs": "commands/fid-list", - "commands/getfile": "commands/getfile", - "commands/err": "commands/err", - "commands/esccli": "commands/esccli", - "commands/eschtml": "commands/eschtml", - "commands/!eschtml": "commands/eschtml", - "commands/escurl": "commands/escurl", - "commands/!escurl": "commands/escurl", - "commands/exec": "commands/exec", - "commands/command": "commands/exec", - "commands/exec.file": "commands/exec", - "commands/fexec": "commands/fexec", - "commands/builtin": "commands/fexec", - "commands/exec.builtin": "commands/fexec", - "commands/exec.function": "commands/fexec", - "commands/exec.private": "commands/fexec", - "commands/break": "commands/break", - "commands/return": "commands/return", - "commands/exit": "commands/exit", - "commands/expr": "commands/expr", - "commands/false": "commands/false", - "commands/foreach": "commands/foreach", - "commands/formap": "commands/formap", - "commands/for": "commands/for", - "commands/fg": "commands/fg", - "commands/runmode": "commands/runmode", - "commands/rand": "commands/rand", - "commands/get-type": "commands/get-type", - "commands/exitnum": "commands/exitnum", - "commands/pt": "commands/pt", - "commands/get": "commands/get", - "commands/g": "commands/g", - "commands/!g": "commands/g", - "commands/if": "commands/if", - "commands/!if": "commands/if", - "commands/source": "commands/source", - "commands/.": "commands/source", - "commands/is-null": "commands/is-null", - "commands/mjoin": "commands/mjoin", - "commands/list.join": "commands/mjoin", - "commands/fid-killall": "commands/fid-killall", - "commands/fid-kill": "commands/fid-kill", - "commands/left": "commands/left", - "commands/list.left": "commands/left", - "commands/f": "commands/f", - "commands/which": "commands/which", - "commands/lockfile": "commands/lockfile", - "commands/and": "commands/and", - "commands/!and": "commands/and", - "commands/or": "commands/or", - "commands/!or": "commands/or", - "commands/while": "commands/while", - "commands/!while": "commands/while", - "commands/man-summary": "commands/man-summary", - "commands/help.man.summary": "commands/man-summary", - "commands/match": "commands/match", - "commands/!match": "commands/match", - "commands/list.str": "commands/match", - "commands/!list.str": "commands/match", - "commands/event": "commands/event", - "commands/!event": "commands/event", - "commands/murex-package": "commands/murex-package", - "commands/version": "commands/version", - "commands/murex-docs": "commands/murex-docs", - "commands/help": "commands/murex-docs", - "commands/continue": "commands/continue", - "commands/!": "commands/not-func", - "commands/not": "commands/not-func", - "commands/null": "commands/devnull", - "commands/open": "commands/open", - "commands/os": "commands/os", - "commands/sys.os": "commands/os", - "commands/out": "commands/out", - "commands/echo": "commands/out", - "commands/tout": "commands/tout", - "commands/man-get-flags": "commands/man-get-flags", - "commands/trypipe": "commands/trypipe", - "commands/post": "commands/post", - "commands/prepend": "commands/prepend", - "commands/list.prepend": "commands/prepend", - "commands/pretty": "commands/pretty", - "commands/struct-keys": "commands/struct-keys", - "commands/private": "commands/private", - "commands/time": "commands/time", - "commands/function": "commands/function", - "commands/!function": "commands/function", - "commands/escape": "commands/escape", - "commands/!escape": "commands/escape", - "commands/murex-update-exe-list": "commands/murex-update-exe-list", - "commands/read": "commands/read", - "commands/tread": "commands/tread", - "commands/format": "commands/format", - "commands/rx": "commands/rx", - "commands/!rx": "commands/rx", - "commands/regexp": "commands/regexp", - "commands/!regexp": "commands/regexp", - "commands/list.regex": "commands/regexp", - "commands/!list.regex": "commands/regexp", - "commands/open-image": "commands/open-image", - "commands/mtac": "commands/mtac", - "commands/list.reverse": "commands/mtac", - "commands/right": "commands/right", - "commands/list.right": "commands/right", - "commands/round": "commands/round", - "commands/num.round": "commands/round", - "commands/signal": "commands/signal", - "commands/summary": "commands/summary", - "commands/!summary": "commands/summary", - "commands/config": "commands/config", - "commands/!config": "commands/config", - "commands/runtime": "commands/runtime", - "commands/builtins": "commands/runtime", - "commands/shell.runtime": "commands/runtime", - "commands/test": "commands/test", - "commands/!test": "commands/test", - "commands/msort": "commands/msort", - "commands/list.sort": "commands/msort", - "commands/jsplit": "commands/jsplit", - "commands/str.split": "commands/jsplit", - "commands/trypipeerr": "commands/trypipeerr", - "commands/tryerr": "commands/tryerr", - "commands/a": "commands/a", - "commands/mkarray": "commands/a", - "commands/switch": "commands/switch", - "commands/autocomplete": "commands/autocomplete", - "commands/tabulate": "commands/tabulate", - "commands/true": "commands/true", - "commands/try": "commands/try", - "commands/die": "commands/die", - "commands/let": "commands/let", - "commands/murex-parser": "commands/murex-parser", - "mkarray/date": "mkarray/date", - "mkarray/character": "mkarray/character", - "mkarray/decimal": "mkarray/decimal", - "mkarray/non-decimal": "mkarray/non-decimal", - "mkarray/special": "mkarray/special", - "optional/select": "optional/select", - "optional/table.select": "optional/select", - "optional/!bz2": "optional/bz2", - "optional/base64": "optional/base64", - "optional/!base64": "optional/base64", - "optional/gz": "optional/gz", - "optional/!gz": "optional/gz", - "optional/qr": "optional/qr", - "optional/sleep": "optional/sleep", - "parser/expr-inlined": "parser/expr-inlined", - "parser/c-style-fun": "parser/c-style-fun", - "parser/@[": "parser/range", - "parser/[": "parser/item-index", - "parser/![": "parser/item-index", - "parser/item-index": "parser/item-index", - "parser/index": "parser/item-index", - "parser/[[": "parser/element", - "parser/element": "parser/element", - "parser/(murex named pipe)": "parser/namedpipe", - "parser/<>": "parser/namedpipe", - "parser/read-named-pipe": "parser/namedpipe", - "parser/": "parser/stdin", - "parser/>": "parser/file-truncate", - "parser/|>": "parser/file-truncate", - "parser/fwrite": "parser/file-truncate", - "parser/double-quote": "parser/double-quote", - "parser/scalar": "parser/scalar", - "parser/brace-quote": "parser/brace-quote", - "parser/create-array": "parser/create-array", - "parser/create-object": "parser/create-object", - "parser/logical-and": "parser/logical-and", - "parser/single-quote": "parser/single-quote", - "parser/(": "parser/brace-quote-func", - "parser/multiply-by": "parser/multiply-by", - "parser/multiplication": "parser/multiplication", - "parser/add-with": "parser/add-with", - "parser/addition": "parser/addition", - "parser/subtract-by": "parser/subtract-by", - "parser/pipe-arrow": "parser/pipe-arrow", - "parser/subtraction": "parser/subtraction", - "parser/divide-by": "parser/divide-by", - "parser/division": "parser/division", - "parser/assign-or-merge": "parser/assign-or-merge", - "parser/pipe-generic": "parser/pipe-generic", - "parser/=": "parser/equ", - "parser/>>": "parser/file-append", - "parser/fappend": "parser/file-append", - "parser/elvis": "parser/elvis", - "parser/null-coalescing": "parser/null-coalescing", - "parser/pipe-err": "parser/pipe-err", - "parser/array": "parser/array", - "parser/lambda": "parser/lambda", - "parser/curly-brace": "parser/curly-brace", - "parser/pipe-posix": "parser/pipe-posix", - "parser/logical-or": "parser/logical-or", - "parser/tilde": "parser/tilde", - "events/oncommandcompletion": "events/oncommandcompletion", - "events/onCommandCompletion": "events/oncommandcompletion", - "events/onfilesystemchange": "events/onfilesystemchange", - "events/onFileSystemChange": "events/onfilesystemchange", - "events/onkeypress": "events/onkeypress", - "events/onKeyPress": "events/onkeypress", - "events/onpreview": "events/onpreview", - "events/onPreview": "events/onpreview", - "events/onprompt": "events/onprompt", - "events/onPrompt": "events/onprompt", - "events/onsecondselapsed": "events/onsecondselapsed", - "events/onSecondsElapsed": "events/onsecondselapsed", - "events/onsignalreceived": "events/onsignalreceived", - "events/onSignalReceived": "events/onsignalreceived", - "types/generic": "types/generic", - "types/*": "types/generic", - "types/bool": "types/bool", - "types/commonlog": "types/commonlog", - "types/csv": "types/csv", - "types/float": "types/float", - "types/hcl": "types/hcl", - "types/int": "types/int", - "types/json": "types/json", - "types/jsonc": "types/jsonc", - "types/jsonl": "types/jsonl", - "types/num": "types/num", - "types/path": "types/path", - "types/paths": "types/paths", - "types/str": "types/str", - "types/string": "types/str", - "types/toml": "types/toml", - "types/yaml": "types/yaml", - "types/mxjson": "types/mxjson", - "variables/numeric": "variables/numeric", - "variables/meta-values": "variables/meta-values", - "variables/$.": "variables/meta-values", - "variables/argv": "variables/argv", - "variables/ARGV": "variables/argv", - "variables/ARGS": "variables/argv", - "variables/columns": "variables/columns", - "variables/COLUMNS": "variables/columns", - "variables/event_return": "variables/event_return", - "variables/EVENT_RETURN": "variables/event_return", - "variables/hostname": "variables/hostname", - "variables/HOSTNAME": "variables/hostname", - "variables/murex_argv": "variables/murex_argv", - "variables/MUREX_ARGV": "variables/murex_argv", - "variables/MUREX_ARGS": "variables/murex_argv", - "variables/murex_exe": "variables/murex_exe", - "variables/MUREX_EXE": "variables/murex_exe", - "variables/params": "variables/params", - "variables/PARAMS": "variables/params", - "variables/pwdhist": "variables/pwdhist", - "variables/PWDHIST": "variables/pwdhist", - "variables/pwd": "variables/pwd", - "variables/PWD": "variables/pwd", - "variables/self": "variables/self", - "variables/SELF": "variables/self", - "variables/shell": "variables/shell", - "variables/SHELL": "variables/shell", - "apis/Marshal": "apis/Marshal", - "apis/ReadArray": "apis/ReadArray", - "apis/ReadArrayWithType": "apis/ReadArrayWithType", - "apis/ReadIndex": "apis/ReadIndex", - "apis/ReadMap": "apis/ReadMap", - "apis/ReadNotIndex": "apis/ReadNotIndex", - "apis/Unmarshal": "apis/Unmarshal", - "apis/WriteArray": "apis/WriteArray", - "apis/lang.ArrayTemplate": "apis/lang.ArrayTemplate", + + "commands/key-code": "commands/key-code", + "commands/addheading": "commands/addheading", + "commands/prefix": "commands/prefix", + "commands/list.prefix": "commands/prefix", + "commands/suffix": "commands/suffix", + "commands/list.suffix": "commands/suffix", + "commands/alias": "commands/alias", + "commands/!alias": "commands/alias", + "commands/alter": "commands/alter", + "commands/~>": "commands/alter", + "commands/append": "commands/append", + "commands/list.append": "commands/append", + "commands/bg": "commands/bg", + "commands/cpuarch": "commands/cpuarch", + "commands/sys.cpu.arch": "commands/cpuarch", + "commands/cpucount": "commands/cpucount", + "commands/sys.cpu.count": "commands/cpucount", + "commands/catch": "commands/catch", + "commands/!catch": "commands/catch", + "commands/cd": "commands/cd", + "commands/list.case": "commands/list.case", + "commands/bexists": "commands/bexists", + "commands/history": "commands/history", + "commands/count": "commands/count", + "commands/len": "commands/count", + "commands/2darray": "commands/2darray", + "commands/ja": "commands/ja", + "commands/map": "commands/map", + "commands/pipe": "commands/pipe", + "commands/!pipe": "commands/pipe", + "commands/ta": "commands/ta", + "commands/tmp": "commands/tmp", + "commands/datetime": "commands/datetime", + "commands/str.datetime": "commands/datetime", + "commands/debug": "commands/debug", + "commands/export": "commands/export", + "commands/!export": "commands/export", + "commands/unset": "commands/export", + "commands/var.env": "commands/export", + "commands/!var.env": "commands/export", + "commands/args": "commands/args", + "commands/global": "commands/global", + "commands/!global": "commands/global", + "commands/openagent": "commands/openagent", + "commands/!openagent": "commands/openagent", + "commands/method": "commands/method", + "commands/cast": "commands/cast", + "commands/set": "commands/set", + "commands/!set": "commands/set", + "commands/unsafe": "commands/unsafe", + "commands/type": "commands/type", + "commands/fid-list": "commands/fid-list", + "commands/jobs": "commands/fid-list", + "commands/getfile": "commands/getfile", + "commands/err": "commands/err", + "commands/esccli": "commands/esccli", + "commands/eschtml": "commands/eschtml", + "commands/!eschtml": "commands/eschtml", + "commands/escurl": "commands/escurl", + "commands/!escurl": "commands/escurl", + "commands/exec": "commands/exec", + "commands/command": "commands/exec", + "commands/exec.file": "commands/exec", + "commands/fexec": "commands/fexec", + "commands/builtin": "commands/fexec", + "commands/exec.builtin": "commands/fexec", + "commands/exec.function": "commands/fexec", + "commands/exec.private": "commands/fexec", + "commands/break": "commands/break", + "commands/return": "commands/return", + "commands/exit": "commands/exit", + "commands/expr": "commands/expr", + "commands/false": "commands/false", + "commands/foreach": "commands/foreach", + "commands/formap": "commands/formap", + "commands/for": "commands/for", + "commands/fg": "commands/fg", + "commands/runmode": "commands/runmode", + "commands/rand": "commands/rand", + "commands/get-type": "commands/get-type", + "commands/exitnum": "commands/exitnum", + "commands/pt": "commands/pt", + "commands/get": "commands/get", + "commands/g": "commands/g", + "commands/!g": "commands/g", + "commands/if": "commands/if", + "commands/!if": "commands/if", + "commands/source": "commands/source", + "commands/.": "commands/source", + "commands/is-null": "commands/is-null", + "commands/mjoin": "commands/mjoin", + "commands/list.join": "commands/mjoin", + "commands/fid-killall": "commands/fid-killall", + "commands/fid-kill": "commands/fid-kill", + "commands/left": "commands/left", + "commands/list.left": "commands/left", + "commands/f": "commands/f", + "commands/which": "commands/which", + "commands/lockfile": "commands/lockfile", + "commands/and": "commands/and", + "commands/!and": "commands/and", + "commands/or": "commands/or", + "commands/!or": "commands/or", + "commands/while": "commands/while", + "commands/!while": "commands/while", + "commands/man-summary": "commands/man-summary", + "commands/help.man.summary": "commands/man-summary", + "commands/match": "commands/match", + "commands/!match": "commands/match", + "commands/list.str": "commands/match", + "commands/!list.str": "commands/match", + "commands/event": "commands/event", + "commands/!event": "commands/event", + "commands/murex-package": "commands/murex-package", + "commands/version": "commands/version", + "commands/murex-docs": "commands/murex-docs", + "commands/help": "commands/murex-docs", + "commands/continue": "commands/continue", + "commands/!": "commands/not-func", + "commands/not": "commands/not-func", + "commands/null": "commands/devnull", + "commands/open": "commands/open", + "commands/os": "commands/os", + "commands/sys.os": "commands/os", + "commands/out": "commands/out", + "commands/echo": "commands/out", + "commands/tout": "commands/tout", + "commands/man-get-flags": "commands/man-get-flags", + "commands/trypipe": "commands/trypipe", + "commands/post": "commands/post", + "commands/prepend": "commands/prepend", + "commands/list.prepend": "commands/prepend", + "commands/pretty": "commands/pretty", + "commands/struct-keys": "commands/struct-keys", + "commands/private": "commands/private", + "commands/time": "commands/time", + "commands/function": "commands/function", + "commands/!function": "commands/function", + "commands/escape": "commands/escape", + "commands/!escape": "commands/escape", + "commands/murex-update-exe-list": "commands/murex-update-exe-list", + "commands/read": "commands/read", + "commands/tread": "commands/tread", + "commands/format": "commands/format", + "commands/rx": "commands/rx", + "commands/!rx": "commands/rx", + "commands/regexp": "commands/regexp", + "commands/!regexp": "commands/regexp", + "commands/list.regex": "commands/regexp", + "commands/!list.regex": "commands/regexp", + "commands/open-image": "commands/open-image", + "commands/mtac": "commands/mtac", + "commands/list.reverse": "commands/mtac", + "commands/right": "commands/right", + "commands/list.right": "commands/right", + "commands/round": "commands/round", + "commands/num.round": "commands/round", + "commands/signal": "commands/signal", + "commands/summary": "commands/summary", + "commands/!summary": "commands/summary", + "commands/config": "commands/config", + "commands/!config": "commands/config", + "commands/runtime": "commands/runtime", + "commands/builtins": "commands/runtime", + "commands/shell.runtime": "commands/runtime", + "commands/test": "commands/test", + "commands/!test": "commands/test", + "commands/msort": "commands/msort", + "commands/list.sort": "commands/msort", + "commands/jsplit": "commands/jsplit", + "commands/str.split": "commands/jsplit", + "commands/trypipeerr": "commands/trypipeerr", + "commands/tryerr": "commands/tryerr", + "commands/a": "commands/a", + "commands/mkarray": "commands/a", + "commands/switch": "commands/switch", + "commands/autocomplete": "commands/autocomplete", + "commands/tabulate": "commands/tabulate", + "commands/true": "commands/true", + "commands/try": "commands/try", + "commands/die": "commands/die", + "commands/let": "commands/let", + "commands/murex-parser": "commands/murex-parser", + "mkarray/date": "mkarray/date", + "mkarray/character": "mkarray/character", + "mkarray/decimal": "mkarray/decimal", + "mkarray/non-decimal": "mkarray/non-decimal", + "mkarray/special": "mkarray/special", + "optional/select": "optional/select", + "optional/table.select": "optional/select", + "optional/!bz2": "optional/bz2", + "optional/base64": "optional/base64", + "optional/!base64": "optional/base64", + "optional/gz": "optional/gz", + "optional/!gz": "optional/gz", + "optional/qr": "optional/qr", + "optional/sleep": "optional/sleep", + "parser/expr-inlined": "parser/expr-inlined", + "parser/c-style-fun": "parser/c-style-fun", + "parser/@[": "parser/range", + "parser/[": "parser/item-index", + "parser/![": "parser/item-index", + "parser/item-index": "parser/item-index", + "parser/index": "parser/item-index", + "parser/[[": "parser/element", + "parser/element": "parser/element", + "parser/(murex named pipe)": "parser/namedpipe", + "parser/<>": "parser/namedpipe", + "parser/read-named-pipe": "parser/namedpipe", + "parser/": "parser/stdin", + "parser/>": "parser/file-truncate", + "parser/|>": "parser/file-truncate", + "parser/fwrite": "parser/file-truncate", + "parser/double-quote": "parser/double-quote", + "parser/scalar": "parser/scalar", + "parser/brace-quote": "parser/brace-quote", + "parser/create-array": "parser/create-array", + "parser/create-object": "parser/create-object", + "parser/logical-and": "parser/logical-and", + "parser/single-quote": "parser/single-quote", + "parser/(": "parser/brace-quote-func", + "parser/multiply-by": "parser/multiply-by", + "parser/multiplication": "parser/multiplication", + "parser/add-with": "parser/add-with", + "parser/addition": "parser/addition", + "parser/subtract-by": "parser/subtract-by", + "parser/pipe-arrow": "parser/pipe-arrow", + "parser/subtraction": "parser/subtraction", + "parser/divide-by": "parser/divide-by", + "parser/division": "parser/division", + "parser/assign-or-merge": "parser/assign-or-merge", + "parser/pipe-generic": "parser/pipe-generic", + "parser/=": "parser/equ", + "parser/>>": "parser/file-append", + "parser/fappend": "parser/file-append", + "parser/elvis": "parser/elvis", + "parser/null-coalescing": "parser/null-coalescing", + "parser/pipe-err": "parser/pipe-err", + "parser/array": "parser/array", + "parser/lambda": "parser/lambda", + "parser/curly-brace": "parser/curly-brace", + "parser/pipe-posix": "parser/pipe-posix", + "parser/logical-or": "parser/logical-or", + "parser/tilde": "parser/tilde", + "events/oncommandcompletion": "events/oncommandcompletion", + "events/onCommandCompletion": "events/oncommandcompletion", + "events/onfilesystemchange": "events/onfilesystemchange", + "events/onFileSystemChange": "events/onfilesystemchange", + "events/onkeypress": "events/onkeypress", + "events/onKeyPress": "events/onkeypress", + "events/onpreview": "events/onpreview", + "events/onPreview": "events/onpreview", + "events/onprompt": "events/onprompt", + "events/onPrompt": "events/onprompt", + "events/onsecondselapsed": "events/onsecondselapsed", + "events/onSecondsElapsed": "events/onsecondselapsed", + "events/onsignalreceived": "events/onsignalreceived", + "events/onSignalReceived": "events/onsignalreceived", + "types/generic": "types/generic", + "types/*": "types/generic", + "types/bool": "types/bool", + "types/commonlog": "types/commonlog", + "types/csv": "types/csv", + "types/float": "types/float", + "types/hcl": "types/hcl", + "types/int": "types/int", + "types/json": "types/json", + "types/jsonc": "types/jsonc", + "types/jsonl": "types/jsonl", + "types/num": "types/num", + "types/path": "types/path", + "types/paths": "types/paths", + "types/str": "types/str", + "types/string": "types/str", + "types/toml": "types/toml", + "types/yaml": "types/yaml", + "types/mxjson": "types/mxjson", + "variables/numeric": "variables/numeric", + "variables/meta-values": "variables/meta-values", + "variables/$.": "variables/meta-values", + "variables/argv": "variables/argv", + "variables/ARGV": "variables/argv", + "variables/ARGS": "variables/argv", + "variables/columns": "variables/columns", + "variables/COLUMNS": "variables/columns", + "variables/event_return": "variables/event_return", + "variables/EVENT_RETURN": "variables/event_return", + "variables/hostname": "variables/hostname", + "variables/HOSTNAME": "variables/hostname", + "variables/murex_argv": "variables/murex_argv", + "variables/MUREX_ARGV": "variables/murex_argv", + "variables/MUREX_ARGS": "variables/murex_argv", + "variables/murex_exe": "variables/murex_exe", + "variables/MUREX_EXE": "variables/murex_exe", + "variables/params": "variables/params", + "variables/PARAMS": "variables/params", + "variables/pwdhist": "variables/pwdhist", + "variables/PWDHIST": "variables/pwdhist", + "variables/pwd": "variables/pwd", + "variables/PWD": "variables/pwd", + "variables/self": "variables/self", + "variables/SELF": "variables/self", + "variables/shell": "variables/shell", + "variables/SHELL": "variables/shell", + "apis/Marshal": "apis/Marshal", + "apis/ReadArray": "apis/ReadArray", + "apis/ReadArrayWithType": "apis/ReadArrayWithType", + "apis/ReadIndex": "apis/ReadIndex", + "apis/ReadMap": "apis/ReadMap", + "apis/ReadNotIndex": "apis/ReadNotIndex", + "apis/Unmarshal": "apis/Unmarshal", + "apis/WriteArray": "apis/WriteArray", + "apis/lang.ArrayTemplate": "apis/lang.ArrayTemplate", "apis/lang.ArrayWithTypeTemplate": "apis/lang.ArrayWithTypeTemplate", - "apis/lang.IndexTemplateObject": "apis/lang.IndexTemplateObject", - "apis/lang.IndexTemplateTable": "apis/lang.IndexTemplateTable", - "apis/lang.MarshalData": "apis/lang.MarshalData", - "apis/lang.UnmarshalData": "apis/lang.UnmarshalData", - "user-guide/ansi": "user-guide/ansi", - "user-guide/bang-prefix": "user-guide/bang-prefix", - "user-guide/bang": "user-guide/bang-prefix", - "user-guide/code-block": "user-guide/code-block", - "user-guide/fileref": "user-guide/fileref", - "user-guide/FileRef": "user-guide/fileref", - "user-guide/hint-text": "user-guide/hint-text", - "user-guide/integrations": "user-guide/integrations", - "user-guide/interactive-shell": "user-guide/interactive-shell", - "user-guide/repl": "user-guide/interactive-shell", - "user-guide/readline": "user-guide/interactive-shell", - "user-guide/job-control": "user-guide/job-control", - "user-guide/module": "user-guide/modules", - "user-guide/modules": "user-guide/modules", - "user-guide/package": "user-guide/modules", - "user-guide/packages": "user-guide/modules", - "user-guide/namedpipes": "user-guide/namedpipes", + "apis/lang.IndexTemplateObject": "apis/lang.IndexTemplateObject", + "apis/lang.IndexTemplateTable": "apis/lang.IndexTemplateTable", + "apis/lang.MarshalData": "apis/lang.MarshalData", + "apis/lang.UnmarshalData": "apis/lang.UnmarshalData", + "user-guide/ansi": "user-guide/ansi", + "user-guide/bang-prefix": "user-guide/bang-prefix", + "user-guide/bang": "user-guide/bang-prefix", + "user-guide/code-block": "user-guide/code-block", + "user-guide/fileref": "user-guide/fileref", + "user-guide/FileRef": "user-guide/fileref", + "user-guide/hint-text": "user-guide/hint-text", + "user-guide/integrations": "user-guide/integrations", + "user-guide/interactive-shell": "user-guide/interactive-shell", + "user-guide/repl": "user-guide/interactive-shell", + "user-guide/readline": "user-guide/interactive-shell", + "user-guide/job-control": "user-guide/job-control", + "user-guide/module": "user-guide/modules", + "user-guide/modules": "user-guide/modules", + "user-guide/package": "user-guide/modules", + "user-guide/packages": "user-guide/modules", + "user-guide/namedpipes": "user-guide/namedpipes", "user-guide/operators-and-tokens": "user-guide/operators-and-tokens", - "user-guide/pipeline": "user-guide/pipeline", - "user-guide/profile": "user-guide/profile", - "user-guide/.murex_profile": "user-guide/profile", - "user-guide/murex_profile": "user-guide/profile", - "user-guide/.murex_preload": "user-guide/profile", - "user-guide/murex_preload": "user-guide/profile", - "user-guide/reserved-vars": "user-guide/reserved-vars", - "user-guide/reserved": "user-guide/reserved-vars", - "user-guide/reserved-variables": "user-guide/reserved-vars", - "user-guide/special-vars": "user-guide/reserved-vars", - "user-guide/special-variables": "user-guide/reserved-vars", - "user-guide/rosetta-stone": "user-guide/rosetta-stone", - "user-guide/schedulers": "user-guide/schedulers", - "user-guide/strict-types": "user-guide/strict-types", - "user-guide/hotkeys": "user-guide/terminal-keys", - "user-guide/scoping": "user-guide/scoping", - "integrations/chatgpt": "integrations/chatgpt", - "integrations/ChatGPT": "integrations/chatgpt", - "integrations/cheatsh": "integrations/cheatsh", - "integrations/cheat.sh": "integrations/cheatsh", - "integrations/kitty": "integrations/kitty", - "integrations/make": "integrations/make", - "integrations/Makefile": "integrations/make", - "integrations/man-pages": "integrations/man-pages", - "integrations/spellcheck": "integrations/spellcheck", - "integrations/terminology": "integrations/terminology", - "integrations/direnv": "integrations/direnv", - "integrations/yarn": "integrations/yarn", - "integrations/package.json": "integrations/yarn", - "integrations/iterm2": "integrations/iterm2", - "changelog/v2.0": "changelog/v2.0", - "changelog/v2.1": "changelog/v2.1", - "changelog/v2.10": "changelog/v2.10", - "changelog/v2.11": "changelog/v2.11", - "changelog/v2.2": "changelog/v2.2", - "changelog/v2.3": "changelog/v2.3", - "changelog/v2.4": "changelog/v2.4", - "changelog/v2.5": "changelog/v2.5", - "changelog/v2.6": "changelog/v2.6", - "changelog/v2.7": "changelog/v2.7", - "changelog/v2.8": "changelog/v2.8", - "changelog/v2.9": "changelog/v2.9", - "changelog/v3.0": "changelog/v3.0", - "changelog/v3.1": "changelog/v3.1", - "changelog/v4.0": "changelog/v4.0", - "changelog/v4.1": "changelog/v4.1", - "changelog/v4.2": "changelog/v4.2", - "changelog/v4.3": "changelog/v4.3", - "changelog/v4.4": "changelog/v4.4", - "changelog/v5.0": "changelog/v5.0", - "changelog/v5.1": "changelog/v5.1", - "changelog/v5.2": "changelog/v5.2", - "changelog/v5.3": "changelog/v5.3", - "changelog/v6.0": "changelog/v6.0", - "changelog/v6.1": "changelog/v6.1", - "changelog/v6.2": "changelog/v6.2", + "user-guide/pipeline": "user-guide/pipeline", + "user-guide/profile": "user-guide/profile", + "user-guide/.murex_profile": "user-guide/profile", + "user-guide/murex_profile": "user-guide/profile", + "user-guide/.murex_preload": "user-guide/profile", + "user-guide/murex_preload": "user-guide/profile", + "user-guide/reserved-vars": "user-guide/reserved-vars", + "user-guide/reserved": "user-guide/reserved-vars", + "user-guide/reserved-variables": "user-guide/reserved-vars", + "user-guide/special-vars": "user-guide/reserved-vars", + "user-guide/special-variables": "user-guide/reserved-vars", + "user-guide/rosetta-stone": "user-guide/rosetta-stone", + "user-guide/schedulers": "user-guide/schedulers", + "user-guide/strict-types": "user-guide/strict-types", + "user-guide/hotkeys": "user-guide/terminal-keys", + "user-guide/scoping": "user-guide/scoping", + "integrations/chatgpt": "integrations/chatgpt", + "integrations/ChatGPT": "integrations/chatgpt", + "integrations/cheatsh": "integrations/cheatsh", + "integrations/cheat.sh": "integrations/cheatsh", + "integrations/kitty": "integrations/kitty", + "integrations/make": "integrations/make", + "integrations/Makefile": "integrations/make", + "integrations/man-pages": "integrations/man-pages", + "integrations/spellcheck": "integrations/spellcheck", + "integrations/terminology": "integrations/terminology", + "integrations/direnv": "integrations/direnv", + "integrations/yarn": "integrations/yarn", + "integrations/package.json": "integrations/yarn", + "integrations/iterm2": "integrations/iterm2", + "changelog/v2.0": "changelog/v2.0", + "changelog/v2.1": "changelog/v2.1", + "changelog/v2.10": "changelog/v2.10", + "changelog/v2.11": "changelog/v2.11", + "changelog/v2.2": "changelog/v2.2", + "changelog/v2.3": "changelog/v2.3", + "changelog/v2.4": "changelog/v2.4", + "changelog/v2.5": "changelog/v2.5", + "changelog/v2.6": "changelog/v2.6", + "changelog/v2.7": "changelog/v2.7", + "changelog/v2.8": "changelog/v2.8", + "changelog/v2.9": "changelog/v2.9", + "changelog/v3.0": "changelog/v3.0", + "changelog/v3.1": "changelog/v3.1", + "changelog/v4.0": "changelog/v4.0", + "changelog/v4.1": "changelog/v4.1", + "changelog/v4.2": "changelog/v4.2", + "changelog/v4.3": "changelog/v4.3", + "changelog/v4.4": "changelog/v4.4", + "changelog/v5.0": "changelog/v5.0", + "changelog/v5.1": "changelog/v5.1", + "changelog/v5.2": "changelog/v5.2", + "changelog/v5.3": "changelog/v5.3", + "changelog/v6.0": "changelog/v6.0", + "changelog/v6.1": "changelog/v6.1", + "changelog/v6.2": "changelog/v6.2", + } -} +} \ No newline at end of file diff --git a/docs/integrations/README.md b/docs/integrations/README.md new file mode 100644 index 000000000..7eb4403f4 --- /dev/null +++ b/docs/integrations/README.md @@ -0,0 +1,63 @@ +# Integrations + +## Description + +Murex is highly customizable, as every good shell should be. However the Murex +community believe that extendability and support for customizations are no +substitute for good defaults. + +Murex aims to provide you with the best support for your wider command line +needs, in its "out-of-the-box" configuration. + +So with that goal in mind, the following configurations come pre-installed with +Murex's base install. + +## Included Integrations + +> Please note that this is not an exhaustive list of all integrations +> precompiled into Murex. A full breakdown can be viewed under `/integrations` +> in the project source directory ([view in Github](https://github.com/lmorg/murex/tree/master/integrations)). + +* [ChatGPT](../integrations/chatgpt.md): + How to enable ChatGPT hints +* [Cheat.sh](../integrations/cheatsh.md): + Cheatsheets provided by cheat.sh +* [Kitty Integrations](../integrations/kitty.md): + Get more out of Kitty terminal emulator +* [Makefiles / `make`](../integrations/make.md): + `make` integrations +* [Man Pages (POSIX)](../integrations/man-pages.md): + Linux/UNIX `man` page integrations +* [Spellcheck](../integrations/spellcheck.md): + How to enable inline spellchecking +* [Terminology Integrations](../integrations/terminology.md): + Get more out of Terminology terminal emulator +* [`direnv` Integrations](../integrations/direnv.md): + Directory specific environmental variables +* [`yarn` Integrations](../integrations/yarn.md): + Working with `yarn` and `package.json` +* [iTerm2 Integrations](../integrations/iterm2.md): + Get more out of iTerm2 terminal emulator + +## Pages + +* [ChatGPT](../integrations/chatgpt.md): + How to enable ChatGPT hints +* [Cheat.sh](../integrations/cheatsh.md): + Cheatsheets provided by cheat.sh +* [Kitty Integrations](../integrations/kitty.md): + Get more out of Kitty terminal emulator +* [Makefiles / `make`](../integrations/make.md): + `make` integrations +* [Man Pages (POSIX)](../integrations/man-pages.md): + Linux/UNIX `man` page integrations +* [Spellcheck](../integrations/spellcheck.md): + How to enable inline spellchecking +* [Terminology Integrations](../integrations/terminology.md): + Get more out of Terminology terminal emulator +* [`direnv` Integrations](../integrations/direnv.md): + Directory specific environmental variables +* [`yarn` Integrations](../integrations/yarn.md): + Working with `yarn` and `package.json` +* [iTerm2 Integrations](../integrations/iterm2.md): + Get more out of iTerm2 terminal emulator \ No newline at end of file diff --git a/docs/integrations/chatgpt.md b/docs/integrations/chatgpt.md index 058ddef2b..1d97d864b 100644 --- a/docs/integrations/chatgpt.md +++ b/docs/integrations/chatgpt.md @@ -145,26 +145,25 @@ under `/integrations`. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/cheatsh.md b/docs/integrations/cheatsh.md index 439fb1388..85692c2ec 100644 --- a/docs/integrations/cheatsh.md +++ b/docs/integrations/cheatsh.md @@ -48,26 +48,25 @@ under `/integrations`. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/direnv.md b/docs/integrations/direnv.md index 17b3af4f4..663fc3fd8 100644 --- a/docs/integrations/direnv.md +++ b/docs/integrations/direnv.md @@ -26,26 +26,25 @@ document. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/iterm2.md b/docs/integrations/iterm2.md index 04c2a40bc..62c806811 100644 --- a/docs/integrations/iterm2.md +++ b/docs/integrations/iterm2.md @@ -40,26 +40,25 @@ open https://murex.rocks/git-autocomplete.png ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/kitty.md b/docs/integrations/kitty.md index 4263e19ed..19b044cec 100644 --- a/docs/integrations/kitty.md +++ b/docs/integrations/kitty.md @@ -34,26 +34,25 @@ to Kitty's ANSI escape sequences to render those images beautifully. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/make.md b/docs/integrations/make.md index 2c43b4182..a0b0f8ba6 100644 --- a/docs/integrations/make.md +++ b/docs/integrations/make.md @@ -36,26 +36,25 @@ under `/integrations`. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/man-pages.md b/docs/integrations/man-pages.md index 252dec9e3..570e57e73 100644 --- a/docs/integrations/man-pages.md +++ b/docs/integrations/man-pages.md @@ -60,26 +60,25 @@ That command will generally be pulled from its accompanying `man` page. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/spellcheck.md b/docs/integrations/spellcheck.md index eb4f28713..3bf5fab19 100644 --- a/docs/integrations/spellcheck.md +++ b/docs/integrations/spellcheck.md @@ -181,26 +181,25 @@ and what the package names are for `aspell` and its corresponding dictionaries. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/terminology.md b/docs/integrations/terminology.md index bdbda036c..99f1cead2 100644 --- a/docs/integrations/terminology.md +++ b/docs/integrations/terminology.md @@ -35,26 +35,25 @@ beautifully. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/integrations/yarn.md b/docs/integrations/yarn.md index a3df5c9ce..883d0850d 100644 --- a/docs/integrations/yarn.md +++ b/docs/integrations/yarn.md @@ -33,26 +33,25 @@ under `/integrations`. ## Other Integrations * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator - + Get more out of iTerm2 terminal emulator
      diff --git a/docs/user-guide/integrations.md b/docs/user-guide/integrations.md index de8125545..dd210d766 100644 --- a/docs/user-guide/integrations.md +++ b/docs/user-guide/integrations.md @@ -4,38 +4,42 @@ ## Description -Murex is highly customisable, as every good shell should be. However the Murex -community believe that extendability and support for customisations are no +Murex is highly customizable, as every good shell should be. However the Murex +community believe that extendability and support for customizations are no substitute for good defaults. - + Murex aims to provide you with the best support for your wider command line needs, in its "out-of-the-box" configuration. So with that goal in mind, the following configurations come pre-installed with Murex's base install. -## Supported Integrations +## Included Integrations + +> Please note that this is not an exhaustive list of all integrations +> precompiled into Murex. A full breakdown can be viewed under `/integrations` +> in the project source directory ([view in Github](https://github.com/lmorg/murex/tree/master/integrations)). * [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints + How to enable ChatGPT hints * [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh + Cheatsheets provided by cheat.sh * [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator + Get more out of Kitty terminal emulator * [Makefiles / `make`](../integrations/make.md): - `make` integrations + `make` integrations * [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations + Linux/UNIX `man` page integrations * [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking + How to enable inline spellchecking * [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator + Get more out of Terminology terminal emulator * [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables + Directory specific environmental variables * [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` + Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator + Get more out of iTerm2 terminal emulator ## See Also diff --git a/gen/docgen.yaml b/gen/docgen.yaml index eedd518f9..854ed865d 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -114,11 +114,13 @@ Categories: Description: Templates: - OutputPath: docs/mkarray - CategoryFile: ../../gen/includes/autogenerated.mkarray.inc.md OutputExt: .md - CategoryTemplate: gen/mkarray-md-cat.tmpl DocumentTemplate: gen/mkarray-md-doc.tmpl + - OutputPath: gen/includes + CategoryFile: ../../gen/includes/autogenerated.mkarray.inc.md + CategoryTemplate: gen/mkarray-inc-cat.tmpl + - ID: optional Title: Optional Builtins Reference Description: |- @@ -281,9 +283,9 @@ Categories: Description: Templates: - OutputPath: docs/integrations - CategoryFile: ../../gen/includes/autogenerated.integrations.inc.md + CategoryFile: README.md OutputExt: .md - CategoryTemplate: gen/integrations-md-cat.tmpl.md + CategoryTemplate: gen/integrations-md-cat.tmpl DocumentTemplate: gen/integrations-md-doc.tmpl # blog diff --git a/gen/includes/autogenerated.integrations.inc.md b/gen/includes/autogenerated.integrations.inc.md deleted file mode 100644 index 3d7d8a88a..000000000 --- a/gen/includes/autogenerated.integrations.inc.md +++ /dev/null @@ -1,20 +0,0 @@ -* [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints -* [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh -* [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator -* [Makefiles / `make`](../integrations/make.md): - `make` integrations -* [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations -* [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking -* [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator -* [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables -* [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` -* [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator diff --git a/gen/integrations-md-cat.tmpl b/gen/integrations-md-cat.tmpl new file mode 100644 index 000000000..143389589 --- /dev/null +++ b/gen/integrations-md-cat.tmpl @@ -0,0 +1,17 @@ +{{ $doc := doct "" "integrations" }}{{ if env "DOCGEN_TARGET=vuepress" }}--- +index: true +icon: puzzle-piece +title: {{ quote .Title }} +description: {{ quote $doc.Summary }} +category: {{ .ID }} +--- + +{{ end }}# {{ .Title }} + +{{ include $doc.Description }} + +## Pages + +{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/integrations-md-cat.tmpl.md b/gen/integrations-md-cat.tmpl.md deleted file mode 100644 index f7f9b75e1..000000000 --- a/gen/integrations-md-cat.tmpl.md +++ /dev/null @@ -1,3 +0,0 @@ -{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} -{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): - {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 7cca3ff92..7f51b4b7d 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -18,7 +18,9 @@ category: {{ .CategoryID }} ## Other Integrations -{{ file "gen/includes/autogenerated.integrations.inc.md" }} +{{ if otherdocs "integrations" }}{{ range $i,$a := otherdocs "integrations" }}{{ if gt $i 0 }} +{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }}
      diff --git a/gen/mkarray-md-cat.tmpl b/gen/mkarray-inc-cat.tmpl similarity index 100% rename from gen/mkarray-md-cat.tmpl rename to gen/mkarray-inc-cat.tmpl diff --git a/gen/user-guide/integrations.inc.md b/gen/user-guide/integrations.inc.md new file mode 100644 index 000000000..eb1e025b3 --- /dev/null +++ b/gen/user-guide/integrations.inc.md @@ -0,0 +1,21 @@ +## Description + +Murex is highly customizable, as every good shell should be. However the Murex +community believe that extendability and support for customizations are no +substitute for good defaults. + +Murex aims to provide you with the best support for your wider command line +needs, in its "out-of-the-box" configuration. + +So with that goal in mind, the following configurations come pre-installed with +Murex's base install. + +## Included Integrations + +> Please note that this is not an exhaustive list of all integrations +> precompiled into Murex. A full breakdown can be viewed under `/integrations` +> in the project source directory ([view in Github](https://github.com/lmorg/murex/tree/master/integrations)). + +{{ if otherdocs "integrations" }}{{ range $i,$a := otherdocs "integrations" }}{{ if gt $i 0 }} +{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} diff --git a/gen/user-guide/integrations_doc.yaml b/gen/user-guide/integrations_doc.yaml index 48b1a6dee..d80f8d3ff 100644 --- a/gen/user-guide/integrations_doc.yaml +++ b/gen/user-guide/integrations_doc.yaml @@ -5,23 +5,9 @@ Summary: >- Default integrations shipped with Murex Description: |- - ## Description - - Murex is highly customisable, as every good shell should be. However the Murex - community believe that extendability and support for customisations are no - substitute for good defaults. - - Murex aims to provide you with the best support for your wider command line - needs, in its "out-of-the-box" configuration. - - So with that goal in mind, the following configurations come pre-installed with - Murex's base install. - - ## Supported Integrations - - {{ include "gen/includes/autogenerated.integrations.inc.md" }} + {{ include "gen/user-guide/integrations.inc.md" }} Synonyms: - Related: + Related: - modules - spellcheck - fileref diff --git a/version.svg b/version.svg index 69dd2e080..c3d48d982 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4146Version6.3.4146 +Version: 6.3.4170Version6.3.4170 From 36e25109ee3738aa5660dba9fc727e1247d04f7a Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 19:10:48 +0100 Subject: [PATCH 134/142] website: add summaries + rewrite types cat --- app/app.go | 4 +- builtins/docs/summaries.go | 2062 +++++++++++++++--------------- docs/blog/README.md | 2 +- docs/commands/export.md | 2 +- docs/commands/get-type.md | 2 +- docs/commands/global.md | 2 +- docs/commands/is-null.md | 2 +- docs/commands/let.md | 2 +- docs/commands/set.md | 2 +- docs/integrations/README.md | 23 - docs/parser/equ.md | 2 +- docs/parser/scalar.md | 8 +- docs/types/README.md | 37 +- docs/user-guide/README.md | 2 +- docs/user-guide/reserved-vars.md | 2 +- docs/user-guide/scoping.md | 16 +- docs/user-guide/strict-types.md | 2 +- docs/variables/argv.md | 2 +- docs/variables/params.md | 2 +- docs/variables/pwdhist.md | 2 +- docs/variables/self.md | 2 +- gen/blog-md-cat.tmpl | 2 +- gen/changelog-md-cat.tmpl | 2 +- gen/commands-md-cat.tmpl | 2 +- gen/docgen.yaml | 25 +- gen/events-md-cat.tmpl | 2 +- gen/integrations-md-cat.tmpl | 8 +- gen/murex-md-cat.tmpl | 2 +- gen/parser-md-cat.tmpl | 2 +- gen/parser/variables_doc.yaml | 8 +- gen/types-md-cat.inc.md | 39 +- gen/user-guide/scoping_doc.yaml | 16 +- gen/userguide-md-cat.tmpl.md | 2 +- gen/variables-md-cat.tmpl | 2 +- utils/docgen/api/category.go | 10 +- utils/docgen/main.go | 2 +- version.svg | 2 +- 37 files changed, 1161 insertions(+), 1145 deletions(-) diff --git a/app/app.go b/app/app.go index 2924f7350..935a68623 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4170 + Revision = 4172 Branch = "develop" - BuildDate = "2024-09-15 18:02:38" + BuildDate = "2024-09-15 19:10:50" ) // Copyright is the copyright owner string diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index d38bca4d2..5c8cd8cd4 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -5,1059 +5,1049 @@ package docs func init() { Summary = map[string]string{ - - - "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "addheading": "Adds headings to a table", - "prefix": "Prefix a string to every item in a list", - "suffix": "Prefix a string to every item in a list", - "alias": "Create an alias for a command", - "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "append": "Add data to the end of an array", - "bg": "Run processes in the background", - "cpuarch": "Output the hosts CPU architecture", - "cpucount": "Output the number of CPU cores available on your host", - "catch": "Handles the exception code raised by `try` or `trypipe`", - "cd": "Change (working) directory", - "list.case": "Changes the character case of a string or all elements in an array", - "bexists": "Check which builtins exist", - "history": "Outputs murex's command history", - "count": "Count items in a map, list or array", - "2darray": "Create a 2D JSON array from multiple input sources", - "ja": "A sophisticated yet simply way to build a JSON array", - "map": "Creates a map from two data sources", - "pipe": "Manage Murex named pipes", - "ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "tmp": "Create a temporary file and write to it", - "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "debug": "Debugging information", - "export": "Define an environmental variable and set it's value", - "args": "Command line flag parser for Murex shell scripting", - "global": "Define a global variable and set it's value", - "openagent": "Creates a handler function for `open`", - "method": "Define a methods supported data-types", - "cast": "Alters the data-type of the previous function without altering its output", - "set": "Define a variable (typically local) and set it's value", - "unsafe": "Execute a block of code, always returning a zero exit number", - "type": "Command type (function, builtin, alias, etc)", - "fid-list": "Lists all running functions within the current Murex session", - "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "err": "Print a line to the stderr", - "esccli": "Escapes an array so output is valid shell code", - "eschtml": "Encode or decodes text for HTML", - "escurl": "Encode or decodes text for the URL", - "exec": "Runs an executable", - "fexec": "Execute a command or function, bypassing the usual order of precedence.", - "break": "Terminate execution of a block within your processes scope", - "return": "Exits current function scope", - "exit": "Exit murex", - "expr": "Expressions: mathematical, string comparisons, logical operators", - "false": "Returns a `false` value", - "foreach": "Iterate through an array", - "formap": "Iterate through a map or other collection of data", - "for": "A more familiar iteration loop to existing developers", - "fg": "Sends a background process into the foreground", - "runmode": "Alter the scheduler's behaviour at higher scoping level", - "rand": "Random field generator", - "get-type": "Returns the data-type of a variable or pipe", - "exitnum": "Output the exit number of the previous process", - "pt": "Pipe telemetry. Writes data-types and bytes written", - "get": "Makes a standard HTTP request and returns the result as a JSON object", - "g": "Glob pattern matching for file system objects (eg `*.txt`)", - "if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "source": "Import Murex code from another file or code block", - "is-null": "Checks if a variable is null or undefined", - "mjoin": "Joins a list or array into a single string", - "fid-killall": "Terminate all running Murex functions in current session", - "fid-kill": "Terminate a running Murex function", - "left": "Left substring every item in a list", - "f": "Lists or filters file system objects (eg files)", - "which": "Locate command origin", - "lockfile": "Create and manage lock files", - "and": "Returns `true` or `false` depending on whether multiple conditions are met", - "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "while": "Loop until condition false", - "man-summary": "Outputs a man page summary of a command", - "match": "Match an exact value in an array", - "event": "Event driven programming for shell scripts", - "murex-package": "Murex's package manager", - "version": "Get Murex version", - "murex-docs": "Displays the man pages for Murex builtins", - "continue": "Terminate process of a block within a caller function", - "not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "devnull": "null function. Similar to /dev/null", - "open": "Open a file with a preferred handler", - "os": "Output the auto-detected OS name", - "out": "Print a string to the stdout with a trailing new line character", - "tout": "Print a string to the stdout and set it's data-type", - "man-get-flags": "Parses man page files for command line flags", - "trypipe": "Checks for non-zero exits of each function in a pipeline", - "post": "HTTP POST request with a JSON-parsable return", - "prepend": "Add data to the start of an array", - "pretty": "Prettifies JSON to make it human readable", - "struct-keys": "Outputs all the keys in a structure as a file path", - "private": "Define a private function block", - "time": "Returns the execution run time of a command or block", - "function": "Define a function block", - "escape": "Escape or unescape input", + + "key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "addheading": "Adds headings to a table", + "prefix": "Prefix a string to every item in a list", + "suffix": "Prefix a string to every item in a list", + "alias": "Create an alias for a command", + "alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "append": "Add data to the end of an array", + "bg": "Run processes in the background", + "cpuarch": "Output the hosts CPU architecture", + "cpucount": "Output the number of CPU cores available on your host", + "catch": "Handles the exception code raised by `try` or `trypipe`", + "cd": "Change (working) directory", + "list.case": "Changes the character case of a string or all elements in an array", + "bexists": "Check which builtins exist", + "history": "Outputs murex's command history", + "count": "Count items in a map, list or array", + "2darray": "Create a 2D JSON array from multiple input sources", + "ja": "A sophisticated yet simply way to build a JSON array", + "map": "Creates a map from two data sources", + "pipe": "Manage Murex named pipes", + "ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "tmp": "Create a temporary file and write to it", + "datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "debug": "Debugging information", + "export": "Define an environmental variable and set it's value", + "args": "Command line flag parser for Murex shell scripting", + "global": "Define a global variable and set it's value", + "openagent": "Creates a handler function for `open`", + "method": "Define a methods supported data-types", + "cast": "Alters the data-type of the previous function without altering its output", + "set": "Define a variable (typically local) and set it's value", + "unsafe": "Execute a block of code, always returning a zero exit number", + "type": "Command type (function, builtin, alias, etc)", + "fid-list": "Lists all running functions within the current Murex session", + "getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "err": "Print a line to the stderr", + "esccli": "Escapes an array so output is valid shell code", + "eschtml": "Encode or decodes text for HTML", + "escurl": "Encode or decodes text for the URL", + "exec": "Runs an executable", + "fexec": "Execute a command or function, bypassing the usual order of precedence.", + "break": "Terminate execution of a block within your processes scope", + "return": "Exits current function scope", + "exit": "Exit murex", + "expr": "Expressions: mathematical, string comparisons, logical operators", + "false": "Returns a `false` value", + "foreach": "Iterate through an array", + "formap": "Iterate through a map or other collection of data", + "for": "A more familiar iteration loop to existing developers", + "fg": "Sends a background process into the foreground", + "runmode": "Alter the scheduler's behaviour at higher scoping level", + "rand": "Random field generator", + "get-type": "Returns the data-type of a variable or pipe", + "exitnum": "Output the exit number of the previous process", + "pt": "Pipe telemetry. Writes data-types and bytes written", + "get": "Makes a standard HTTP request and returns the result as a JSON object", + "g": "Glob pattern matching for file system objects (eg `*.txt`)", + "if": "Conditional statement to execute different blocks of code depending on the result of the condition", + "source": "Import Murex code from another file or code block", + "is-null": "Checks if a variable is null or undefined", + "mjoin": "Joins a list or array into a single string", + "fid-killall": "Terminate all running Murex functions in current session", + "fid-kill": "Terminate a running Murex function", + "left": "Left substring every item in a list", + "f": "Lists or filters file system objects (eg files)", + "which": "Locate command origin", + "lockfile": "Create and manage lock files", + "and": "Returns `true` or `false` depending on whether multiple conditions are met", + "or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "while": "Loop until condition false", + "man-summary": "Outputs a man page summary of a command", + "match": "Match an exact value in an array", + "event": "Event driven programming for shell scripts", + "murex-package": "Murex's package manager", + "version": "Get Murex version", + "murex-docs": "Displays the man pages for Murex builtins", + "continue": "Terminate process of a block within a caller function", + "not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "devnull": "null function. Similar to /dev/null", + "open": "Open a file with a preferred handler", + "os": "Output the auto-detected OS name", + "out": "Print a string to the stdout with a trailing new line character", + "tout": "Print a string to the stdout and set it's data-type", + "man-get-flags": "Parses man page files for command line flags", + "trypipe": "Checks for non-zero exits of each function in a pipeline", + "post": "HTTP POST request with a JSON-parsable return", + "prepend": "Add data to the start of an array", + "pretty": "Prettifies JSON to make it human readable", + "struct-keys": "Outputs all the keys in a structure as a file path", + "private": "Define a private function block", + "time": "Returns the execution run time of a command or block", + "function": "Define a function block", + "escape": "Escape or unescape input", "murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", - "read": "`read` a line of input from the user and store as a variable", - "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", - "format": "Reformat one data-type into another data-type", - "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "regexp": "Regexp tools for arrays / lists of strings", - "open-image": "Renders bitmap image data on your terminal", - "mtac": "Reverse the order of an array", - "right": "Right substring every item in a list", - "round": "Round a number by a user defined precision", - "signal": "Sends a signal RPC", - "summary": "Defines a summary help text for a command", - "config": "Query or define Murex runtime settings", - "runtime": "Returns runtime information on the internal state of Murex", - "test": "Murex's test framework - define tests, run tests and debug shell scripts", - "msort": "Sorts an array - data type agnostic", - "jsplit": "Splits stdin into a JSON array based on a regex parameter", - "trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "tryerr": "Handles errors inside a block of code", - "a": "A sophisticated yet simple way to stream an array or list (mkarray)", - "switch": "Blocks of cascading conditionals", - "autocomplete": "Set definitions for tab-completion in the command line", - "tabulate": "Table transformation tools", - "true": "Returns a `true` value", - "try": "Handles non-zero exits inside a block of code", - "die": "Terminate murex with an exit number of 1 (deprecated)", - "let": "Evaluate a mathematical function and assign to variable (deprecated)", - "murex-parser": "Runs the Murex parser against a block of code", + "read": "`read` a line of input from the user and store as a variable", + "tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "format": "Reformat one data-type into another data-type", + "rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "regexp": "Regexp tools for arrays / lists of strings", + "open-image": "Renders bitmap image data on your terminal", + "mtac": "Reverse the order of an array", + "right": "Right substring every item in a list", + "round": "Round a number by a user defined precision", + "signal": "Sends a signal RPC", + "summary": "Defines a summary help text for a command", + "config": "Query or define Murex runtime settings", + "runtime": "Returns runtime information on the internal state of Murex", + "test": "Murex's test framework - define tests, run tests and debug shell scripts", + "msort": "Sorts an array - data type agnostic", + "jsplit": "Splits stdin into a JSON array based on a regex parameter", + "trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "tryerr": "Handles errors inside a block of code", + "a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "switch": "Blocks of cascading conditionals", + "autocomplete": "Set definitions for tab-completion in the command line", + "tabulate": "Table transformation tools", + "true": "Returns a `true` value", + "try": "Handles non-zero exits inside a block of code", + "die": "Terminate murex with an exit number of 1 (deprecated)", + "let": "Evaluate a mathematical function and assign to variable (deprecated)", + "murex-parser": "Runs the Murex parser against a block of code", - "select": "Inlining SQL into shell pipelines", - "bz2": "Decompress a bz2 file", + "bz2": "Decompress a bz2 file", "base64": "Encode or decode a base64 string", - "gz": "Compress or decompress a gzip file", - "qr": "Creates a QR code from stdin", - "sleep": "Suspends the shell for a number of seconds", + "gz": "Compress or decompress a gzip file", + "qr": "Creates a QR code from stdin", + "sleep": "Suspends the shell for a number of seconds", - - "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", - "commands/addheading": "Adds headings to a table", - "commands/prefix": "Prefix a string to every item in a list", - "commands/suffix": "Prefix a string to every item in a list", - "commands/alias": "Create an alias for a command", - "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", - "commands/append": "Add data to the end of an array", - "commands/bg": "Run processes in the background", - "commands/cpuarch": "Output the hosts CPU architecture", - "commands/cpucount": "Output the number of CPU cores available on your host", - "commands/catch": "Handles the exception code raised by `try` or `trypipe`", - "commands/cd": "Change (working) directory", - "commands/list.case": "Changes the character case of a string or all elements in an array", - "commands/bexists": "Check which builtins exist", - "commands/history": "Outputs murex's command history", - "commands/count": "Count items in a map, list or array", - "commands/2darray": "Create a 2D JSON array from multiple input sources", - "commands/ja": "A sophisticated yet simply way to build a JSON array", - "commands/map": "Creates a map from two data sources", - "commands/pipe": "Manage Murex named pipes", - "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", - "commands/tmp": "Create a temporary file and write to it", - "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", - "commands/debug": "Debugging information", - "commands/export": "Define an environmental variable and set it's value", - "commands/args": "Command line flag parser for Murex shell scripting", - "commands/global": "Define a global variable and set it's value", - "commands/openagent": "Creates a handler function for `open`", - "commands/method": "Define a methods supported data-types", - "commands/cast": "Alters the data-type of the previous function without altering its output", - "commands/set": "Define a variable (typically local) and set it's value", - "commands/unsafe": "Execute a block of code, always returning a zero exit number", - "commands/type": "Command type (function, builtin, alias, etc)", - "commands/fid-list": "Lists all running functions within the current Murex session", - "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", - "commands/err": "Print a line to the stderr", - "commands/esccli": "Escapes an array so output is valid shell code", - "commands/eschtml": "Encode or decodes text for HTML", - "commands/escurl": "Encode or decodes text for the URL", - "commands/exec": "Runs an executable", - "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", - "commands/break": "Terminate execution of a block within your processes scope", - "commands/return": "Exits current function scope", - "commands/exit": "Exit murex", - "commands/expr": "Expressions: mathematical, string comparisons, logical operators", - "commands/false": "Returns a `false` value", - "commands/foreach": "Iterate through an array", - "commands/formap": "Iterate through a map or other collection of data", - "commands/for": "A more familiar iteration loop to existing developers", - "commands/fg": "Sends a background process into the foreground", - "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", - "commands/rand": "Random field generator", - "commands/get-type": "Returns the data-type of a variable or pipe", - "commands/exitnum": "Output the exit number of the previous process", - "commands/pt": "Pipe telemetry. Writes data-types and bytes written", - "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", - "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", - "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", - "commands/source": "Import Murex code from another file or code block", - "commands/is-null": "Checks if a variable is null or undefined", - "commands/mjoin": "Joins a list or array into a single string", - "commands/fid-killall": "Terminate all running Murex functions in current session", - "commands/fid-kill": "Terminate a running Murex function", - "commands/left": "Left substring every item in a list", - "commands/f": "Lists or filters file system objects (eg files)", - "commands/which": "Locate command origin", - "commands/lockfile": "Create and manage lock files", - "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", - "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", - "commands/while": "Loop until condition false", - "commands/man-summary": "Outputs a man page summary of a command", - "commands/match": "Match an exact value in an array", - "commands/event": "Event driven programming for shell scripts", - "commands/murex-package": "Murex's package manager", - "commands/version": "Get Murex version", - "commands/murex-docs": "Displays the man pages for Murex builtins", - "commands/continue": "Terminate process of a block within a caller function", - "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", - "commands/devnull": "null function. Similar to /dev/null", - "commands/open": "Open a file with a preferred handler", - "commands/os": "Output the auto-detected OS name", - "commands/out": "Print a string to the stdout with a trailing new line character", - "commands/tout": "Print a string to the stdout and set it's data-type", - "commands/man-get-flags": "Parses man page files for command line flags", - "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", - "commands/post": "HTTP POST request with a JSON-parsable return", - "commands/prepend": "Add data to the start of an array", - "commands/pretty": "Prettifies JSON to make it human readable", - "commands/struct-keys": "Outputs all the keys in a structure as a file path", - "commands/private": "Define a private function block", - "commands/time": "Returns the execution run time of a command or block", - "commands/function": "Define a function block", - "commands/escape": "Escape or unescape input", - "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", - "commands/read": "`read` a line of input from the user and store as a variable", - "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", - "commands/format": "Reformat one data-type into another data-type", - "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", - "commands/regexp": "Regexp tools for arrays / lists of strings", - "commands/open-image": "Renders bitmap image data on your terminal", - "commands/mtac": "Reverse the order of an array", - "commands/right": "Right substring every item in a list", - "commands/round": "Round a number by a user defined precision", - "commands/signal": "Sends a signal RPC", - "commands/summary": "Defines a summary help text for a command", - "commands/config": "Query or define Murex runtime settings", - "commands/runtime": "Returns runtime information on the internal state of Murex", - "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", - "commands/msort": "Sorts an array - data type agnostic", - "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", - "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", - "commands/tryerr": "Handles errors inside a block of code", - "commands/a": "A sophisticated yet simple way to stream an array or list (mkarray)", - "commands/switch": "Blocks of cascading conditionals", - "commands/autocomplete": "Set definitions for tab-completion in the command line", - "commands/tabulate": "Table transformation tools", - "commands/true": "Returns a `true` value", - "commands/try": "Handles non-zero exits inside a block of code", - "commands/die": "Terminate murex with an exit number of 1 (deprecated)", - "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", - "commands/murex-parser": "Runs the Murex parser against a block of code", - "mkarray/date": "Create arrays of dates", - "mkarray/character": "Making character arrays (a to z)", - "mkarray/decimal": "Create arrays of decimal integers", - "mkarray/non-decimal": "Create arrays of integers from non-decimal number bases", - "mkarray/special": "Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc)", - "optional/select": "Inlining SQL into shell pipelines", - "optional/bz2": "Decompress a bz2 file", - "optional/base64": "Encode or decode a base64 string", - "optional/gz": "Compress or decompress a gzip file", - "optional/qr": "Creates a QR code from stdin", - "optional/sleep": "Suspends the shell for a number of seconds", - "parser/expr-inlined": "Inline expressions", - "parser/c-style-fun": "Inlined commands for expressions and statements", - "parser/range": "Outputs a ranged subset of data from stdin", - "parser/item-index": "Outputs an element from an array, map or table", - "parser/element": "Outputs an element from a nested structure", - "parser/namedpipe": "Reads from a Murex named pipe", - "parser/stdin": "Read the stdin belonging to the parent code block", - "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", - "parser/double-quote": "Initiates or terminates a string (variables expanded)", - "parser/scalar": "Expand values as a scalar", - "parser/brace-quote": "Initiates or terminates a string (variables expanded)", - "parser/create-array": "Quickly generate arrays", - "parser/create-object": "Quickly generate objects (dictionaries / maps)", - "parser/logical-and": "Continues next operation if previous operation passes", - "parser/single-quote": "Initiates or terminates a string (variables not expanded)", - "parser/brace-quote-func": "Write a string to the stdout without new line (deprecated)", - "parser/multiply-by": "Multiplies a variable by the right hand value (expression)", - "parser/multiplication": "Multiplies one numeric value with another (expression)", - "parser/add-with": "Adds the right hand value to a variable (expression)", - "parser/addition": "Adds two numeric values together (expression)", - "parser/subtract-by": "Subtracts a variable by the right hand value (expression)", - "parser/pipe-arrow": "Pipes stdout from the left hand command to stdin of the right hand command", - "parser/subtraction": "Subtracts one numeric value from another (expression)", - "parser/divide-by": "Divides a variable by the right hand value (expression)", - "parser/division": "Divides one numeric value from another (expression)", - "parser/assign-or-merge": "Merges the right hand value to a variable on the left hand side (expression)", - "parser/pipe-generic": "Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command", - "parser/equ": "Evaluate a mathematical function (deprecated)", - "parser/file-append": "Writes stdin to disk - appending contents if file already exists", - "parser/elvis": "Returns the right operand if the left operand is falsy (expression)", - "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined (expression)", - "parser/pipe-err": "Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED)", - "parser/array": "Expand values as an array", - "parser/lambda": "Iterate through structured data", - "parser/curly-brace": "Initiates or terminates a code block", - "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", - "parser/logical-or": "Continues next operation only if previous operation fails", - "parser/tilde": "Home directory path variable", - "events/oncommandcompletion": "Trigger an event upon a command's completion", - "events/onfilesystemchange": "Add a filesystem watch", - "events/onkeypress": "Custom definable key bindings and macros", - "events/onpreview": "Full screen previews for files and command documentation", - "events/onprompt": "Events triggered by changes in state of the interactive shell", - "events/onsecondselapsed": "Events triggered by time intervals", - "events/onsignalreceived": "Trap OS signals", - "types/generic": "generic (primitive)", - "types/bool": "Boolean (primitive)", - "types/commonlog": "Apache httpd \"common\" log format", - "types/csv": "CSV files (and other character delimited tables)", - "types/float": "Floating point number (primitive)", - "types/hcl": "HashiCorp Configuration Language (HCL)", - "types/int": "Whole number (primitive)", - "types/json": "JavaScript Object Notation (JSON)", - "types/jsonc": "Concatenated JSON", - "types/jsonl": "JSON Lines", - "types/num": "Floating point number (primitive)", - "types/path": "Structured object for working with file and directory paths", - "types/paths": "Structured array for working with `$PATH` style data", - "types/str": "string (primitive)", - "types/toml": "Tom's Obvious, Minimal Language (TOML)", - "types/yaml": "YAML Ain't Markup Language (YAML)", - "types/mxjson": "Murex-flavoured JSON (deprecated)", - "variables/numeric": "Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above", - "variables/meta-values": "State information for iteration blocks", - "variables/argv": "Array of the command name and parameters within a given scope", - "variables/columns": "Character width of terminal", - "variables/event_return": "Return values for events", - "variables/hostname": "Hostname of the current machine", - "variables/murex_argv": "Array of the command name and parameters passed to the current shell", - "variables/murex_exe": "Absolute path to running shell", - "variables/params": "Array of the parameters within a given scope", - "variables/pwdhist": "History of each change to the sessions working directory", - "variables/pwd": "Current working directory", - "variables/self": "Meta information about the running scope.", - "variables/shell": "Path of current shell", - "apis/Marshal": "Converts structured memory into a structured file format (eg for stdio)", - "apis/ReadArray": "Read from a data type one array element at a time", - "apis/ReadArrayWithType": "Read from a data type one array element at a time and return the elements contents and data type", - "apis/ReadIndex": "Data type handler for the index, `[`, builtin", - "apis/ReadMap": "Treat data type as a key/value structure and read its contents", - "apis/ReadNotIndex": "Data type handler for the bang-prefixed index, `![`, builtin", - "apis/Unmarshal": "Converts a structured file format into structured memory", - "apis/WriteArray": "Write a data type, one array element at a time", - "apis/lang.ArrayTemplate": "Unmarshals a data type into a Go struct and returns the results as an array", + "commands/key-code": "Returns character sequences for any key pressed (ie sent from the terminal)", + "commands/addheading": "Adds headings to a table", + "commands/prefix": "Prefix a string to every item in a list", + "commands/suffix": "Prefix a string to every item in a list", + "commands/alias": "Create an alias for a command", + "commands/alter": "Change a value within a structured data-type and pass that change along the pipeline without altering the original source input", + "commands/append": "Add data to the end of an array", + "commands/bg": "Run processes in the background", + "commands/cpuarch": "Output the hosts CPU architecture", + "commands/cpucount": "Output the number of CPU cores available on your host", + "commands/catch": "Handles the exception code raised by `try` or `trypipe`", + "commands/cd": "Change (working) directory", + "commands/list.case": "Changes the character case of a string or all elements in an array", + "commands/bexists": "Check which builtins exist", + "commands/history": "Outputs murex's command history", + "commands/count": "Count items in a map, list or array", + "commands/2darray": "Create a 2D JSON array from multiple input sources", + "commands/ja": "A sophisticated yet simply way to build a JSON array", + "commands/map": "Creates a map from two data sources", + "commands/pipe": "Manage Murex named pipes", + "commands/ta": "A sophisticated yet simple way to build an array of a user defined data-type", + "commands/tmp": "Create a temporary file and write to it", + "commands/datetime": "A date and/or time conversion tool (like `printf` but for date and time values)", + "commands/debug": "Debugging information", + "commands/export": "Define an environmental variable and set it's value", + "commands/args": "Command line flag parser for Murex shell scripting", + "commands/global": "Define a global variable and set it's value", + "commands/openagent": "Creates a handler function for `open`", + "commands/method": "Define a methods supported data-types", + "commands/cast": "Alters the data-type of the previous function without altering its output", + "commands/set": "Define a variable (typically local) and set it's value", + "commands/unsafe": "Execute a block of code, always returning a zero exit number", + "commands/type": "Command type (function, builtin, alias, etc)", + "commands/fid-list": "Lists all running functions within the current Murex session", + "commands/getfile": "Makes a standard HTTP request and return the contents as Murex-aware data type for passing along Murex pipelines.", + "commands/err": "Print a line to the stderr", + "commands/esccli": "Escapes an array so output is valid shell code", + "commands/eschtml": "Encode or decodes text for HTML", + "commands/escurl": "Encode or decodes text for the URL", + "commands/exec": "Runs an executable", + "commands/fexec": "Execute a command or function, bypassing the usual order of precedence.", + "commands/break": "Terminate execution of a block within your processes scope", + "commands/return": "Exits current function scope", + "commands/exit": "Exit murex", + "commands/expr": "Expressions: mathematical, string comparisons, logical operators", + "commands/false": "Returns a `false` value", + "commands/foreach": "Iterate through an array", + "commands/formap": "Iterate through a map or other collection of data", + "commands/for": "A more familiar iteration loop to existing developers", + "commands/fg": "Sends a background process into the foreground", + "commands/runmode": "Alter the scheduler's behaviour at higher scoping level", + "commands/rand": "Random field generator", + "commands/get-type": "Returns the data-type of a variable or pipe", + "commands/exitnum": "Output the exit number of the previous process", + "commands/pt": "Pipe telemetry. Writes data-types and bytes written", + "commands/get": "Makes a standard HTTP request and returns the result as a JSON object", + "commands/g": "Glob pattern matching for file system objects (eg `*.txt`)", + "commands/if": "Conditional statement to execute different blocks of code depending on the result of the condition", + "commands/source": "Import Murex code from another file or code block", + "commands/is-null": "Checks if a variable is null or undefined", + "commands/mjoin": "Joins a list or array into a single string", + "commands/fid-killall": "Terminate all running Murex functions in current session", + "commands/fid-kill": "Terminate a running Murex function", + "commands/left": "Left substring every item in a list", + "commands/f": "Lists or filters file system objects (eg files)", + "commands/which": "Locate command origin", + "commands/lockfile": "Create and manage lock files", + "commands/and": "Returns `true` or `false` depending on whether multiple conditions are met", + "commands/or": "Returns `true` or `false` depending on whether one code-block out of multiple ones supplied is successful or unsuccessful.", + "commands/while": "Loop until condition false", + "commands/man-summary": "Outputs a man page summary of a command", + "commands/match": "Match an exact value in an array", + "commands/event": "Event driven programming for shell scripts", + "commands/murex-package": "Murex's package manager", + "commands/version": "Get Murex version", + "commands/murex-docs": "Displays the man pages for Murex builtins", + "commands/continue": "Terminate process of a block within a caller function", + "commands/not-func": "Reads the stdin and exit number from previous process and not's it's condition", + "commands/devnull": "null function. Similar to /dev/null", + "commands/open": "Open a file with a preferred handler", + "commands/os": "Output the auto-detected OS name", + "commands/out": "Print a string to the stdout with a trailing new line character", + "commands/tout": "Print a string to the stdout and set it's data-type", + "commands/man-get-flags": "Parses man page files for command line flags", + "commands/trypipe": "Checks for non-zero exits of each function in a pipeline", + "commands/post": "HTTP POST request with a JSON-parsable return", + "commands/prepend": "Add data to the start of an array", + "commands/pretty": "Prettifies JSON to make it human readable", + "commands/struct-keys": "Outputs all the keys in a structure as a file path", + "commands/private": "Define a private function block", + "commands/time": "Returns the execution run time of a command or block", + "commands/function": "Define a function block", + "commands/escape": "Escape or unescape input", + "commands/murex-update-exe-list": "Forces Murex to rescan $PATH looking for executables", + "commands/read": "`read` a line of input from the user and store as a variable", + "commands/tread": "`read` a line of input from the user and store as a user defined *typed* variable (deprecated)", + "commands/format": "Reformat one data-type into another data-type", + "commands/rx": "Regexp pattern matching for file system objects (eg `.*\\\\.txt`)", + "commands/regexp": "Regexp tools for arrays / lists of strings", + "commands/open-image": "Renders bitmap image data on your terminal", + "commands/mtac": "Reverse the order of an array", + "commands/right": "Right substring every item in a list", + "commands/round": "Round a number by a user defined precision", + "commands/signal": "Sends a signal RPC", + "commands/summary": "Defines a summary help text for a command", + "commands/config": "Query or define Murex runtime settings", + "commands/runtime": "Returns runtime information on the internal state of Murex", + "commands/test": "Murex's test framework - define tests, run tests and debug shell scripts", + "commands/msort": "Sorts an array - data type agnostic", + "commands/jsplit": "Splits stdin into a JSON array based on a regex parameter", + "commands/trypipeerr": "Checks state of each function in a pipeline and exits block on error", + "commands/tryerr": "Handles errors inside a block of code", + "commands/a": "A sophisticated yet simple way to stream an array or list (mkarray)", + "commands/switch": "Blocks of cascading conditionals", + "commands/autocomplete": "Set definitions for tab-completion in the command line", + "commands/tabulate": "Table transformation tools", + "commands/true": "Returns a `true` value", + "commands/try": "Handles non-zero exits inside a block of code", + "commands/die": "Terminate murex with an exit number of 1 (deprecated)", + "commands/let": "Evaluate a mathematical function and assign to variable (deprecated)", + "commands/murex-parser": "Runs the Murex parser against a block of code", + "mkarray/date": "Create arrays of dates", + "mkarray/character": "Making character arrays (a to z)", + "mkarray/decimal": "Create arrays of decimal integers", + "mkarray/non-decimal": "Create arrays of integers from non-decimal number bases", + "mkarray/special": "Create arrays from ranges of dictionary terms (eg weekdays, months, seasons, etc)", + "optional/select": "Inlining SQL into shell pipelines", + "optional/bz2": "Decompress a bz2 file", + "optional/base64": "Encode or decode a base64 string", + "optional/gz": "Compress or decompress a gzip file", + "optional/qr": "Creates a QR code from stdin", + "optional/sleep": "Suspends the shell for a number of seconds", + "parser/expr-inlined": "Inline expressions", + "parser/c-style-fun": "Inlined commands for expressions and statements", + "parser/range": "Outputs a ranged subset of data from stdin", + "parser/item-index": "Outputs an element from an array, map or table", + "parser/element": "Outputs an element from a nested structure", + "parser/namedpipe": "Reads from a Murex named pipe", + "parser/stdin": "Read the stdin belonging to the parent code block", + "parser/file-truncate": "Writes stdin to disk - overwriting contents if file already exists", + "parser/double-quote": "Initiates or terminates a string (variables expanded)", + "parser/scalar": "Expand values as a scalar", + "parser/brace-quote": "Initiates or terminates a string (variables expanded)", + "parser/create-array": "Quickly generate arrays", + "parser/create-object": "Quickly generate objects (dictionaries / maps)", + "parser/logical-and": "Continues next operation if previous operation passes", + "parser/single-quote": "Initiates or terminates a string (variables not expanded)", + "parser/brace-quote-func": "Write a string to the stdout without new line (deprecated)", + "parser/multiply-by": "Multiplies a variable by the right hand value (expression)", + "parser/multiplication": "Multiplies one numeric value with another (expression)", + "parser/add-with": "Adds the right hand value to a variable (expression)", + "parser/addition": "Adds two numeric values together (expression)", + "parser/subtract-by": "Subtracts a variable by the right hand value (expression)", + "parser/pipe-arrow": "Pipes stdout from the left hand command to stdin of the right hand command", + "parser/subtraction": "Subtracts one numeric value from another (expression)", + "parser/divide-by": "Divides a variable by the right hand value (expression)", + "parser/division": "Divides one numeric value from another (expression)", + "parser/assign-or-merge": "Merges the right hand value to a variable on the left hand side (expression)", + "parser/pipe-generic": "Pipes a reformatted stdout stream from the left hand command to stdin of the right hand command", + "parser/equ": "Evaluate a mathematical function (deprecated)", + "parser/file-append": "Writes stdin to disk - appending contents if file already exists", + "parser/elvis": "Returns the right operand if the left operand is falsy (expression)", + "parser/null-coalescing": "Returns the right operand if the left operand is empty / undefined (expression)", + "parser/pipe-err": "Pipes stderr from the left hand command to stdin of the right hand command (DEPRECATED)", + "parser/array": "Expand values as an array", + "parser/lambda": "Iterate through structured data", + "parser/curly-brace": "Initiates or terminates a code block", + "parser/pipe-posix": "Pipes stdout from the left hand command to stdin of the right hand command", + "parser/logical-or": "Continues next operation only if previous operation fails", + "parser/tilde": "Home directory path variable", + "events/oncommandcompletion": "Trigger an event upon a command's completion", + "events/onfilesystemchange": "Add a filesystem watch", + "events/onkeypress": "Custom definable key bindings and macros", + "events/onpreview": "Full screen previews for files and command documentation", + "events/onprompt": "Events triggered by changes in state of the interactive shell", + "events/onsecondselapsed": "Events triggered by time intervals", + "events/onsignalreceived": "Trap OS signals", + "types/generic": "generic (primitive)", + "types/bool": "Boolean (primitive)", + "types/commonlog": "Apache httpd \"common\" log format", + "types/csv": "CSV files (and other character delimited tables)", + "types/float": "Floating point number (primitive)", + "types/hcl": "HashiCorp Configuration Language (HCL)", + "types/int": "Whole number (primitive)", + "types/json": "JavaScript Object Notation (JSON)", + "types/jsonc": "Concatenated JSON", + "types/jsonl": "JSON Lines", + "types/num": "Floating point number (primitive)", + "types/path": "Structured object for working with file and directory paths", + "types/paths": "Structured array for working with `$PATH` style data", + "types/str": "string (primitive)", + "types/toml": "Tom's Obvious, Minimal Language (TOML)", + "types/yaml": "YAML Ain't Markup Language (YAML)", + "types/mxjson": "Murex-flavoured JSON (deprecated)", + "variables/numeric": "Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above", + "variables/meta-values": "State information for iteration blocks", + "variables/argv": "Array of the command name and parameters within a given scope", + "variables/columns": "Character width of terminal", + "variables/event_return": "Return values for events", + "variables/hostname": "Hostname of the current machine", + "variables/murex_argv": "Array of the command name and parameters passed to the current shell", + "variables/murex_exe": "Absolute path to running shell", + "variables/params": "Array of the parameters within a given scope", + "variables/pwdhist": "History of each change to the sessions working directory", + "variables/pwd": "Current working directory", + "variables/self": "Meta information about the running scope.", + "variables/shell": "Path of current shell", + "apis/Marshal": "Converts structured memory into a structured file format (eg for stdio)", + "apis/ReadArray": "Read from a data type one array element at a time", + "apis/ReadArrayWithType": "Read from a data type one array element at a time and return the elements contents and data type", + "apis/ReadIndex": "Data type handler for the index, `[`, builtin", + "apis/ReadMap": "Treat data type as a key/value structure and read its contents", + "apis/ReadNotIndex": "Data type handler for the bang-prefixed index, `![`, builtin", + "apis/Unmarshal": "Converts a structured file format into structured memory", + "apis/WriteArray": "Write a data type, one array element at a time", + "apis/lang.ArrayTemplate": "Unmarshals a data type into a Go struct and returns the results as an array", "apis/lang.ArrayWithTypeTemplate": "Unmarshals a data type into a Go struct and returns the results as an array with data type included", - "apis/lang.IndexTemplateObject": "Returns element(s) from a data structure", - "apis/lang.IndexTemplateTable": "Returns element(s) from a table", - "apis/lang.MarshalData": "Converts structured memory into a Murex data-type (eg for stdio)", - "apis/lang.UnmarshalData": "Converts a Murex data-type into structured memory", - "user-guide/ansi": "Infixed constants that return ANSI escape sequences", - "user-guide/bang-prefix": "Bang prefixing to reverse default actions", - "user-guide/code-block": "Overview of how code blocks are parsed", - "user-guide/fileref": "How to track what code was loaded and from where", - "user-guide/hint-text": "A status bar for your shell", - "user-guide/integrations": "Default integrations shipped with Murex", - "user-guide/interactive-shell": "What's different about Murex's interactive shell?", - "user-guide/job-control": "How to manage jobs with Murex", - "user-guide/modules": "An introduction to Murex modules and packages", - "user-guide/namedpipes": "A detailed breakdown of named pipes in Murex", + "apis/lang.IndexTemplateObject": "Returns element(s) from a data structure", + "apis/lang.IndexTemplateTable": "Returns element(s) from a table", + "apis/lang.MarshalData": "Converts structured memory into a Murex data-type (eg for stdio)", + "apis/lang.UnmarshalData": "Converts a Murex data-type into structured memory", + "user-guide/ansi": "Infixed constants that return ANSI escape sequences", + "user-guide/bang-prefix": "Bang prefixing to reverse default actions", + "user-guide/code-block": "Overview of how code blocks are parsed", + "user-guide/fileref": "How to track what code was loaded and from where", + "user-guide/hint-text": "A status bar for your shell", + "user-guide/integrations": "Default integrations shipped with Murex", + "user-guide/interactive-shell": "What's different about Murex's interactive shell?", + "user-guide/job-control": "How to manage jobs with Murex", + "user-guide/modules": "An introduction to Murex modules and packages", + "user-guide/namedpipes": "A detailed breakdown of named pipes in Murex", "user-guide/operators-and-tokens": "All supported operators and tokens", - "user-guide/pipeline": "Overview of what a \"pipeline\" is", - "user-guide/profile": "A breakdown of the different files loaded on start up", - "user-guide/reserved-vars": "Special variables reserved by Murex", - "user-guide/rosetta-stone": "A tabulated list of Bashism's and their equivalent Murex syntax", - "user-guide/schedulers": "Overview of the different schedulers (or 'run modes') in Murex", - "user-guide/strict-types": "Expressions can auto-convert types or strictly honour data types", - "user-guide/terminal-keys": "A list of all the terminal hotkeys and their uses", - "user-guide/scoping": "How scoping works within Murex", - "integrations/chatgpt": "How to enable ChatGPT hints", - "integrations/cheatsh": "Cheatsheets provided by cheat.sh", - "integrations/kitty": "Get more out of Kitty terminal emulator", - "integrations/make": "`make` integrations", - "integrations/man-pages": "Linux/UNIX `man` page integrations", - "integrations/spellcheck": "How to enable inline spellchecking", - "integrations/terminology": "Get more out of Terminology terminal emulator", - "integrations/direnv": "Directory specific environmental variables", - "integrations/yarn": "Working with `yarn` and `package.json`", - "integrations/iterm2": "Get more out of iTerm2 terminal emulator", - "changelog/v2.0": "This release comes with spellchecking, inlined images, smarter syntax completion and more", - "changelog/v2.1": "This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details.", - "changelog/v2.10": "This release brings a few minor improvements and bug fixes rather than big new headline features.", - "changelog/v2.11": "This release mainly focuses on refinements in performance and usability, rather than introducing new features", - "changelog/v2.2": "This is mainly a bug fix release but it does include one breaking change for `config`. Please read for details.", - "changelog/v2.3": "This release includes significant changes to the interactive terminal", - "changelog/v2.4": "This release introduces a strict mode for variables, new builtin, performance improvements, and better error messages; plus a potential breaking change", - "changelog/v2.5": "This release introduces a number of new builtins, fixes some regression bugs and supercharges the `select` optional builtin (which I plan to include into the core builtins for non-Windows users in the next release).", - "changelog/v2.6": "This update has introduced a potential breaking change: variables now need to be defined before usage otherwise the commandline will fail. Read notes to learn how to disable this feature where needed. Also included in this release is the `select` command as part of the standard build.", - "changelog/v2.7": "This update has introduced another potential breaking change for your safety: zero length arrays now fail by default. Also errors inside subshells will cause the parent command to fail if ran inside a `try` or `trypipe` block.", - "changelog/v2.8": "This release comes with a number of experimental but stable features that might eventually become standard practice. The features are there to use if you with but adjacent from the older code so there is zero risk in updating to this version.", - "changelog/v2.9": "This release focuses on testing and REPL usability improvements but also includes updates several new run modes to make error handling easier in larger scripts.", - "changelog/v3.0": "This is a major release that brings a significant number of changes and improvements, including a complete overhaul of the parser. Backwards compatibility is a high priority however these new features bring greater readability and consistency to shell scripting. So while the older syntax remains for compatibility, it is worth migrating over to the newer syntax for all new code being written", - "changelog/v3.1": "This release includes mostly bug fixes and new experimental features which are opt into. To enable all experimental features, set the environmental variable `MUREX_EXPERIMENTAL` to any value. Or you can enable specific features individually via `config`", - "changelog/v4.0": "This release sees significant improvements for use with non-latin characters in both the interactive prompt and shell scripting. It introduces new syntax to make working with structured data even easier than before. As well as new data types and smoother user experience.", - "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", - "changelog/v4.2": "Murex usage has raised considerably in recent weeks. This release addresses a number of feature requests and bugs raised on Github.", - "changelog/v4.3": "This brings improved support on Windows plus one breaking change from the previous release (v4.2)", - "changelog/v4.4": "v4.4 features two new builtins, improvements in testing, and automatic generation of autocompletion suggestions backed by man page parsing. Plus there has been a lot of focus on improving _readline_ responsiveness", - "changelog/v5.0": "v5.0 is a massive release. It brings along changes to syntax, new operators as well as new builtins, reserved variables and a new event", - "changelog/v5.1": "This release brings new operators and a builtin, all for managing null types. There is also a substantial revamp to readline's responsiveness.", - "changelog/v5.2": "The v5.2 release introduces significant new features and improvements for those using Murex as their interactive shell. Many of these features are unique to Murex.", - "changelog/v5.3": "Caching has been vastly improved in this release due to a new sqlite3-backed persistent `cache.db`. There have also been some improvements to `[f1]` help pages", - "changelog/v6.0": "Despite this being a new major version release, it is a vary minor update. Aside from a handful of bugfixes, the most significant change is notice of deprecation for `=`, `let`, and `?`.", - "changelog/v6.1": "This release sees a massive jump in event-driven capabilities as well as several new features and bug fixes.", - "changelog/v6.2": "Bug fix release", - + "user-guide/pipeline": "Overview of what a \"pipeline\" is", + "user-guide/profile": "A breakdown of the different files loaded on start up", + "user-guide/reserved-vars": "Special variables reserved by Murex", + "user-guide/rosetta-stone": "A tabulated list of Bashism's and their equivalent Murex syntax", + "user-guide/schedulers": "Overview of the different schedulers (or 'run modes') in Murex", + "user-guide/strict-types": "Expressions can auto-convert types or strictly honour data types", + "user-guide/terminal-keys": "A list of all the terminal hotkeys and their uses", + "user-guide/scoping": "How scoping works within Murex", + "integrations/chatgpt": "How to enable ChatGPT hints", + "integrations/cheatsh": "Cheatsheets provided by cheat.sh", + "integrations/kitty": "Get more out of Kitty terminal emulator", + "integrations/make": "`make` integrations", + "integrations/man-pages": "Linux/UNIX `man` page integrations", + "integrations/spellcheck": "How to enable inline spellchecking", + "integrations/terminology": "Get more out of Terminology terminal emulator", + "integrations/direnv": "Directory specific environmental variables", + "integrations/yarn": "Working with `yarn` and `package.json`", + "integrations/iterm2": "Get more out of iTerm2 terminal emulator", + "changelog/v2.0": "This release comes with spellchecking, inlined images, smarter syntax completion and more", + "changelog/v2.1": "This release comes with support for inlining SQL and some major bug fixes plus a breaking change for `config`. Please read for details.", + "changelog/v2.10": "This release brings a few minor improvements and bug fixes rather than big new headline features.", + "changelog/v2.11": "This release mainly focuses on refinements in performance and usability, rather than introducing new features", + "changelog/v2.2": "This is mainly a bug fix release but it does include one breaking change for `config`. Please read for details.", + "changelog/v2.3": "This release includes significant changes to the interactive terminal", + "changelog/v2.4": "This release introduces a strict mode for variables, new builtin, performance improvements, and better error messages; plus a potential breaking change", + "changelog/v2.5": "This release introduces a number of new builtins, fixes some regression bugs and supercharges the `select` optional builtin (which I plan to include into the core builtins for non-Windows users in the next release).", + "changelog/v2.6": "This update has introduced a potential breaking change: variables now need to be defined before usage otherwise the commandline will fail. Read notes to learn how to disable this feature where needed. Also included in this release is the `select` command as part of the standard build.", + "changelog/v2.7": "This update has introduced another potential breaking change for your safety: zero length arrays now fail by default. Also errors inside subshells will cause the parent command to fail if ran inside a `try` or `trypipe` block.", + "changelog/v2.8": "This release comes with a number of experimental but stable features that might eventually become standard practice. The features are there to use if you with but adjacent from the older code so there is zero risk in updating to this version.", + "changelog/v2.9": "This release focuses on testing and REPL usability improvements but also includes updates several new run modes to make error handling easier in larger scripts.", + "changelog/v3.0": "This is a major release that brings a significant number of changes and improvements, including a complete overhaul of the parser. Backwards compatibility is a high priority however these new features bring greater readability and consistency to shell scripting. So while the older syntax remains for compatibility, it is worth migrating over to the newer syntax for all new code being written", + "changelog/v3.1": "This release includes mostly bug fixes and new experimental features which are opt into. To enable all experimental features, set the environmental variable `MUREX_EXPERIMENTAL` to any value. Or you can enable specific features individually via `config`", + "changelog/v4.0": "This release sees significant improvements for use with non-latin characters in both the interactive prompt and shell scripting. It introduces new syntax to make working with structured data even easier than before. As well as new data types and smoother user experience.", + "changelog/v4.1": "The previous releases have brought significant advancements to Murex's syntax but at the cost of longer gaps between releases. So the 4.1.x versions will be shorter releases but focusing on bug fixes. The 4.1.x release notes will be appended to [murex.rocks changelog](https://murex.rocks/changelog/v4.1.html) and available on [Github releases](https://github.com/lmorg/murex/releases) too", + "changelog/v4.2": "Murex usage has raised considerably in recent weeks. This release addresses a number of feature requests and bugs raised on Github.", + "changelog/v4.3": "This brings improved support on Windows plus one breaking change from the previous release (v4.2)", + "changelog/v4.4": "v4.4 features two new builtins, improvements in testing, and automatic generation of autocompletion suggestions backed by man page parsing. Plus there has been a lot of focus on improving _readline_ responsiveness", + "changelog/v5.0": "v5.0 is a massive release. It brings along changes to syntax, new operators as well as new builtins, reserved variables and a new event", + "changelog/v5.1": "This release brings new operators and a builtin, all for managing null types. There is also a substantial revamp to readline's responsiveness.", + "changelog/v5.2": "The v5.2 release introduces significant new features and improvements for those using Murex as their interactive shell. Many of these features are unique to Murex.", + "changelog/v5.3": "Caching has been vastly improved in this release due to a new sqlite3-backed persistent `cache.db`. There have also been some improvements to `[f1]` help pages", + "changelog/v6.0": "Despite this being a new major version release, it is a vary minor update. Aside from a handful of bugfixes, the most significant change is notice of deprecation for `=`, `let`, and `?`.", + "changelog/v6.1": "This release sees a massive jump in event-driven capabilities as well as several new features and bug fixes.", + "changelog/v6.2": "Bug fix release", } - Synonym = map[string]string{ - - "key-code": "key-code", - "addheading": "addheading", - "prefix": "prefix", - "list.prefix": "prefix", - "suffix": "suffix", - "list.suffix": "suffix", - "alias": "alias", - "!alias": "alias", - "alter": "alter", - "~>": "alter", - "append": "append", - "list.append": "append", - "bg": "bg", - "cpuarch": "cpuarch", - "sys.cpu.arch": "cpuarch", - "cpucount": "cpucount", - "sys.cpu.count": "cpucount", - "catch": "catch", - "!catch": "catch", - "cd": "cd", - "list.case": "list.case", - "bexists": "bexists", - "history": "history", - "count": "count", - "len": "count", - "2darray": "2darray", - "ja": "ja", - "map": "map", - "pipe": "pipe", - "!pipe": "pipe", - "ta": "ta", - "tmp": "tmp", - "datetime": "datetime", - "str.datetime": "datetime", - "debug": "debug", - "export": "export", - "!export": "export", - "unset": "export", - "var.env": "export", - "!var.env": "export", - "args": "args", - "global": "global", - "!global": "global", - "openagent": "openagent", - "!openagent": "openagent", - "method": "method", - "cast": "cast", - "set": "set", - "!set": "set", - "unsafe": "unsafe", - "type": "type", - "fid-list": "fid-list", - "jobs": "fid-list", - "getfile": "getfile", - "err": "err", - "esccli": "esccli", - "eschtml": "eschtml", - "!eschtml": "eschtml", - "escurl": "escurl", - "!escurl": "escurl", - "exec": "exec", - "command": "exec", - "exec.file": "exec", - "fexec": "fexec", - "builtin": "fexec", - "exec.builtin": "fexec", - "exec.function": "fexec", - "exec.private": "fexec", - "break": "break", - "return": "return", - "exit": "exit", - "expr": "expr", - "false": "false", - "foreach": "foreach", - "formap": "formap", - "for": "for", - "fg": "fg", - "runmode": "runmode", - "rand": "rand", - "get-type": "get-type", - "exitnum": "exitnum", - "pt": "pt", - "get": "get", - "g": "g", - "!g": "g", - "if": "if", - "!if": "if", - "source": "source", - ".": "source", - "is-null": "is-null", - "mjoin": "mjoin", - "list.join": "mjoin", - "fid-killall": "fid-killall", - "fid-kill": "fid-kill", - "left": "left", - "list.left": "left", - "f": "f", - "which": "which", - "lockfile": "lockfile", - "and": "and", - "!and": "and", - "or": "or", - "!or": "or", - "while": "while", - "!while": "while", - "man-summary": "man-summary", - "help.man.summary": "man-summary", - "match": "match", - "!match": "match", - "list.str": "match", - "!list.str": "match", - "event": "event", - "!event": "event", - "murex-package": "murex-package", - "version": "version", - "murex-docs": "murex-docs", - "help": "murex-docs", - "continue": "continue", - "!": "not-func", - "not": "not-func", - "null": "devnull", - "open": "open", - "os": "os", - "sys.os": "os", - "out": "out", - "echo": "out", - "tout": "tout", - "man-get-flags": "man-get-flags", - "trypipe": "trypipe", - "post": "post", - "prepend": "prepend", - "list.prepend": "prepend", - "pretty": "pretty", - "struct-keys": "struct-keys", - "private": "private", - "time": "time", - "function": "function", - "!function": "function", - "escape": "escape", - "!escape": "escape", + "key-code": "key-code", + "addheading": "addheading", + "prefix": "prefix", + "list.prefix": "prefix", + "suffix": "suffix", + "list.suffix": "suffix", + "alias": "alias", + "!alias": "alias", + "alter": "alter", + "~>": "alter", + "append": "append", + "list.append": "append", + "bg": "bg", + "cpuarch": "cpuarch", + "sys.cpu.arch": "cpuarch", + "cpucount": "cpucount", + "sys.cpu.count": "cpucount", + "catch": "catch", + "!catch": "catch", + "cd": "cd", + "list.case": "list.case", + "bexists": "bexists", + "history": "history", + "count": "count", + "len": "count", + "2darray": "2darray", + "ja": "ja", + "map": "map", + "pipe": "pipe", + "!pipe": "pipe", + "ta": "ta", + "tmp": "tmp", + "datetime": "datetime", + "str.datetime": "datetime", + "debug": "debug", + "export": "export", + "!export": "export", + "unset": "export", + "var.env": "export", + "!var.env": "export", + "args": "args", + "global": "global", + "!global": "global", + "openagent": "openagent", + "!openagent": "openagent", + "method": "method", + "cast": "cast", + "set": "set", + "!set": "set", + "unsafe": "unsafe", + "type": "type", + "fid-list": "fid-list", + "jobs": "fid-list", + "getfile": "getfile", + "err": "err", + "esccli": "esccli", + "eschtml": "eschtml", + "!eschtml": "eschtml", + "escurl": "escurl", + "!escurl": "escurl", + "exec": "exec", + "command": "exec", + "exec.file": "exec", + "fexec": "fexec", + "builtin": "fexec", + "exec.builtin": "fexec", + "exec.function": "fexec", + "exec.private": "fexec", + "break": "break", + "return": "return", + "exit": "exit", + "expr": "expr", + "false": "false", + "foreach": "foreach", + "formap": "formap", + "for": "for", + "fg": "fg", + "runmode": "runmode", + "rand": "rand", + "get-type": "get-type", + "exitnum": "exitnum", + "pt": "pt", + "get": "get", + "g": "g", + "!g": "g", + "if": "if", + "!if": "if", + "source": "source", + ".": "source", + "is-null": "is-null", + "mjoin": "mjoin", + "list.join": "mjoin", + "fid-killall": "fid-killall", + "fid-kill": "fid-kill", + "left": "left", + "list.left": "left", + "f": "f", + "which": "which", + "lockfile": "lockfile", + "and": "and", + "!and": "and", + "or": "or", + "!or": "or", + "while": "while", + "!while": "while", + "man-summary": "man-summary", + "help.man.summary": "man-summary", + "match": "match", + "!match": "match", + "list.str": "match", + "!list.str": "match", + "event": "event", + "!event": "event", + "murex-package": "murex-package", + "version": "version", + "murex-docs": "murex-docs", + "help": "murex-docs", + "continue": "continue", + "!": "not-func", + "not": "not-func", + "null": "devnull", + "open": "open", + "os": "os", + "sys.os": "os", + "out": "out", + "echo": "out", + "tout": "tout", + "man-get-flags": "man-get-flags", + "trypipe": "trypipe", + "post": "post", + "prepend": "prepend", + "list.prepend": "prepend", + "pretty": "pretty", + "struct-keys": "struct-keys", + "private": "private", + "time": "time", + "function": "function", + "!function": "function", + "escape": "escape", + "!escape": "escape", "murex-update-exe-list": "murex-update-exe-list", - "read": "read", - "tread": "tread", - "format": "format", - "rx": "rx", - "!rx": "rx", - "regexp": "regexp", - "!regexp": "regexp", - "list.regex": "regexp", - "!list.regex": "regexp", - "open-image": "open-image", - "mtac": "mtac", - "list.reverse": "mtac", - "right": "right", - "list.right": "right", - "round": "round", - "num.round": "round", - "signal": "signal", - "summary": "summary", - "!summary": "summary", - "config": "config", - "!config": "config", - "runtime": "runtime", - "builtins": "runtime", - "shell.runtime": "runtime", - "test": "test", - "!test": "test", - "msort": "msort", - "list.sort": "msort", - "jsplit": "jsplit", - "str.split": "jsplit", - "trypipeerr": "trypipeerr", - "tryerr": "tryerr", - "a": "a", - "mkarray": "a", - "switch": "switch", - "autocomplete": "autocomplete", - "tabulate": "tabulate", - "true": "true", - "try": "try", - "die": "die", - "let": "let", - "murex-parser": "murex-parser", + "read": "read", + "tread": "tread", + "format": "format", + "rx": "rx", + "!rx": "rx", + "regexp": "regexp", + "!regexp": "regexp", + "list.regex": "regexp", + "!list.regex": "regexp", + "open-image": "open-image", + "mtac": "mtac", + "list.reverse": "mtac", + "right": "right", + "list.right": "right", + "round": "round", + "num.round": "round", + "signal": "signal", + "summary": "summary", + "!summary": "summary", + "config": "config", + "!config": "config", + "runtime": "runtime", + "builtins": "runtime", + "shell.runtime": "runtime", + "test": "test", + "!test": "test", + "msort": "msort", + "list.sort": "msort", + "jsplit": "jsplit", + "str.split": "jsplit", + "trypipeerr": "trypipeerr", + "tryerr": "tryerr", + "a": "a", + "mkarray": "a", + "switch": "switch", + "autocomplete": "autocomplete", + "tabulate": "tabulate", + "true": "true", + "try": "try", + "die": "die", + "let": "let", + "murex-parser": "murex-parser", - - "select": "optional/select", + "select": "optional/select", "table.select": "optional/select", - "!bz2": "optional/bz2", - "base64": "optional/base64", - "!base64": "optional/base64", - "gz": "optional/gz", - "!gz": "optional/gz", - "qr": "optional/qr", - "sleep": "optional/sleep", + "!bz2": "optional/bz2", + "base64": "optional/base64", + "!base64": "optional/base64", + "gz": "optional/gz", + "!gz": "optional/gz", + "qr": "optional/qr", + "sleep": "optional/sleep", - - "expr-inlined": "parser/expr-inlined", - "c-style-fun": "parser/c-style-fun", - "@[": "parser/range", - "[": "parser/item-index", - "![": "parser/item-index", - "item-index": "parser/item-index", - "index": "parser/item-index", - "[[": "parser/element", - "element": "parser/element", + "expr-inlined": "parser/expr-inlined", + "c-style-fun": "parser/c-style-fun", + "@[": "parser/range", + "[": "parser/item-index", + "![": "parser/item-index", + "item-index": "parser/item-index", + "index": "parser/item-index", + "[[": "parser/element", + "element": "parser/element", "(murex named pipe)": "parser/namedpipe", - "<>": "parser/namedpipe", - "read-named-pipe": "parser/namedpipe", - "": "parser/stdin", - ">": "parser/file-truncate", - "|>": "parser/file-truncate", - "fwrite": "parser/file-truncate", - "double-quote": "parser/double-quote", - "scalar": "parser/scalar", - "brace-quote": "parser/brace-quote", - "create-array": "parser/create-array", - "create-object": "parser/create-object", - "logical-and": "parser/logical-and", - "single-quote": "parser/single-quote", - "(": "parser/brace-quote-func", - "multiply-by": "parser/multiply-by", - "multiplication": "parser/multiplication", - "add-with": "parser/add-with", - "addition": "parser/addition", - "subtract-by": "parser/subtract-by", - "pipe-arrow": "parser/pipe-arrow", - "subtraction": "parser/subtraction", - "divide-by": "parser/divide-by", - "division": "parser/division", - "assign-or-merge": "parser/assign-or-merge", - "pipe-generic": "parser/pipe-generic", - "=": "parser/equ", - ">>": "parser/file-append", - "fappend": "parser/file-append", - "elvis": "parser/elvis", - "null-coalescing": "parser/null-coalescing", - "pipe-err": "parser/pipe-err", - "array": "parser/array", - "lambda": "parser/lambda", - "curly-brace": "parser/curly-brace", - "pipe-posix": "parser/pipe-posix", - "logical-or": "parser/logical-or", - "tilde": "parser/tilde", + "<>": "parser/namedpipe", + "read-named-pipe": "parser/namedpipe", + "": "parser/stdin", + ">": "parser/file-truncate", + "|>": "parser/file-truncate", + "fwrite": "parser/file-truncate", + "double-quote": "parser/double-quote", + "scalar": "parser/scalar", + "brace-quote": "parser/brace-quote", + "create-array": "parser/create-array", + "create-object": "parser/create-object", + "logical-and": "parser/logical-and", + "single-quote": "parser/single-quote", + "(": "parser/brace-quote-func", + "multiply-by": "parser/multiply-by", + "multiplication": "parser/multiplication", + "add-with": "parser/add-with", + "addition": "parser/addition", + "subtract-by": "parser/subtract-by", + "pipe-arrow": "parser/pipe-arrow", + "subtraction": "parser/subtraction", + "divide-by": "parser/divide-by", + "division": "parser/division", + "assign-or-merge": "parser/assign-or-merge", + "pipe-generic": "parser/pipe-generic", + "=": "parser/equ", + ">>": "parser/file-append", + "fappend": "parser/file-append", + "elvis": "parser/elvis", + "null-coalescing": "parser/null-coalescing", + "pipe-err": "parser/pipe-err", + "array": "parser/array", + "lambda": "parser/lambda", + "curly-brace": "parser/curly-brace", + "pipe-posix": "parser/pipe-posix", + "logical-or": "parser/logical-or", + "tilde": "parser/tilde", - - "commands/key-code": "commands/key-code", - "commands/addheading": "commands/addheading", - "commands/prefix": "commands/prefix", - "commands/list.prefix": "commands/prefix", - "commands/suffix": "commands/suffix", - "commands/list.suffix": "commands/suffix", - "commands/alias": "commands/alias", - "commands/!alias": "commands/alias", - "commands/alter": "commands/alter", - "commands/~>": "commands/alter", - "commands/append": "commands/append", - "commands/list.append": "commands/append", - "commands/bg": "commands/bg", - "commands/cpuarch": "commands/cpuarch", - "commands/sys.cpu.arch": "commands/cpuarch", - "commands/cpucount": "commands/cpucount", - "commands/sys.cpu.count": "commands/cpucount", - "commands/catch": "commands/catch", - "commands/!catch": "commands/catch", - "commands/cd": "commands/cd", - "commands/list.case": "commands/list.case", - "commands/bexists": "commands/bexists", - "commands/history": "commands/history", - "commands/count": "commands/count", - "commands/len": "commands/count", - "commands/2darray": "commands/2darray", - "commands/ja": "commands/ja", - "commands/map": "commands/map", - "commands/pipe": "commands/pipe", - "commands/!pipe": "commands/pipe", - "commands/ta": "commands/ta", - "commands/tmp": "commands/tmp", - "commands/datetime": "commands/datetime", - "commands/str.datetime": "commands/datetime", - "commands/debug": "commands/debug", - "commands/export": "commands/export", - "commands/!export": "commands/export", - "commands/unset": "commands/export", - "commands/var.env": "commands/export", - "commands/!var.env": "commands/export", - "commands/args": "commands/args", - "commands/global": "commands/global", - "commands/!global": "commands/global", - "commands/openagent": "commands/openagent", - "commands/!openagent": "commands/openagent", - "commands/method": "commands/method", - "commands/cast": "commands/cast", - "commands/set": "commands/set", - "commands/!set": "commands/set", - "commands/unsafe": "commands/unsafe", - "commands/type": "commands/type", - "commands/fid-list": "commands/fid-list", - "commands/jobs": "commands/fid-list", - "commands/getfile": "commands/getfile", - "commands/err": "commands/err", - "commands/esccli": "commands/esccli", - "commands/eschtml": "commands/eschtml", - "commands/!eschtml": "commands/eschtml", - "commands/escurl": "commands/escurl", - "commands/!escurl": "commands/escurl", - "commands/exec": "commands/exec", - "commands/command": "commands/exec", - "commands/exec.file": "commands/exec", - "commands/fexec": "commands/fexec", - "commands/builtin": "commands/fexec", - "commands/exec.builtin": "commands/fexec", - "commands/exec.function": "commands/fexec", - "commands/exec.private": "commands/fexec", - "commands/break": "commands/break", - "commands/return": "commands/return", - "commands/exit": "commands/exit", - "commands/expr": "commands/expr", - "commands/false": "commands/false", - "commands/foreach": "commands/foreach", - "commands/formap": "commands/formap", - "commands/for": "commands/for", - "commands/fg": "commands/fg", - "commands/runmode": "commands/runmode", - "commands/rand": "commands/rand", - "commands/get-type": "commands/get-type", - "commands/exitnum": "commands/exitnum", - "commands/pt": "commands/pt", - "commands/get": "commands/get", - "commands/g": "commands/g", - "commands/!g": "commands/g", - "commands/if": "commands/if", - "commands/!if": "commands/if", - "commands/source": "commands/source", - "commands/.": "commands/source", - "commands/is-null": "commands/is-null", - "commands/mjoin": "commands/mjoin", - "commands/list.join": "commands/mjoin", - "commands/fid-killall": "commands/fid-killall", - "commands/fid-kill": "commands/fid-kill", - "commands/left": "commands/left", - "commands/list.left": "commands/left", - "commands/f": "commands/f", - "commands/which": "commands/which", - "commands/lockfile": "commands/lockfile", - "commands/and": "commands/and", - "commands/!and": "commands/and", - "commands/or": "commands/or", - "commands/!or": "commands/or", - "commands/while": "commands/while", - "commands/!while": "commands/while", - "commands/man-summary": "commands/man-summary", - "commands/help.man.summary": "commands/man-summary", - "commands/match": "commands/match", - "commands/!match": "commands/match", - "commands/list.str": "commands/match", - "commands/!list.str": "commands/match", - "commands/event": "commands/event", - "commands/!event": "commands/event", - "commands/murex-package": "commands/murex-package", - "commands/version": "commands/version", - "commands/murex-docs": "commands/murex-docs", - "commands/help": "commands/murex-docs", - "commands/continue": "commands/continue", - "commands/!": "commands/not-func", - "commands/not": "commands/not-func", - "commands/null": "commands/devnull", - "commands/open": "commands/open", - "commands/os": "commands/os", - "commands/sys.os": "commands/os", - "commands/out": "commands/out", - "commands/echo": "commands/out", - "commands/tout": "commands/tout", - "commands/man-get-flags": "commands/man-get-flags", - "commands/trypipe": "commands/trypipe", - "commands/post": "commands/post", - "commands/prepend": "commands/prepend", - "commands/list.prepend": "commands/prepend", - "commands/pretty": "commands/pretty", - "commands/struct-keys": "commands/struct-keys", - "commands/private": "commands/private", - "commands/time": "commands/time", - "commands/function": "commands/function", - "commands/!function": "commands/function", - "commands/escape": "commands/escape", - "commands/!escape": "commands/escape", - "commands/murex-update-exe-list": "commands/murex-update-exe-list", - "commands/read": "commands/read", - "commands/tread": "commands/tread", - "commands/format": "commands/format", - "commands/rx": "commands/rx", - "commands/!rx": "commands/rx", - "commands/regexp": "commands/regexp", - "commands/!regexp": "commands/regexp", - "commands/list.regex": "commands/regexp", - "commands/!list.regex": "commands/regexp", - "commands/open-image": "commands/open-image", - "commands/mtac": "commands/mtac", - "commands/list.reverse": "commands/mtac", - "commands/right": "commands/right", - "commands/list.right": "commands/right", - "commands/round": "commands/round", - "commands/num.round": "commands/round", - "commands/signal": "commands/signal", - "commands/summary": "commands/summary", - "commands/!summary": "commands/summary", - "commands/config": "commands/config", - "commands/!config": "commands/config", - "commands/runtime": "commands/runtime", - "commands/builtins": "commands/runtime", - "commands/shell.runtime": "commands/runtime", - "commands/test": "commands/test", - "commands/!test": "commands/test", - "commands/msort": "commands/msort", - "commands/list.sort": "commands/msort", - "commands/jsplit": "commands/jsplit", - "commands/str.split": "commands/jsplit", - "commands/trypipeerr": "commands/trypipeerr", - "commands/tryerr": "commands/tryerr", - "commands/a": "commands/a", - "commands/mkarray": "commands/a", - "commands/switch": "commands/switch", - "commands/autocomplete": "commands/autocomplete", - "commands/tabulate": "commands/tabulate", - "commands/true": "commands/true", - "commands/try": "commands/try", - "commands/die": "commands/die", - "commands/let": "commands/let", - "commands/murex-parser": "commands/murex-parser", - "mkarray/date": "mkarray/date", - "mkarray/character": "mkarray/character", - "mkarray/decimal": "mkarray/decimal", - "mkarray/non-decimal": "mkarray/non-decimal", - "mkarray/special": "mkarray/special", - "optional/select": "optional/select", - "optional/table.select": "optional/select", - "optional/!bz2": "optional/bz2", - "optional/base64": "optional/base64", - "optional/!base64": "optional/base64", - "optional/gz": "optional/gz", - "optional/!gz": "optional/gz", - "optional/qr": "optional/qr", - "optional/sleep": "optional/sleep", - "parser/expr-inlined": "parser/expr-inlined", - "parser/c-style-fun": "parser/c-style-fun", - "parser/@[": "parser/range", - "parser/[": "parser/item-index", - "parser/![": "parser/item-index", - "parser/item-index": "parser/item-index", - "parser/index": "parser/item-index", - "parser/[[": "parser/element", - "parser/element": "parser/element", - "parser/(murex named pipe)": "parser/namedpipe", - "parser/<>": "parser/namedpipe", - "parser/read-named-pipe": "parser/namedpipe", - "parser/": "parser/stdin", - "parser/>": "parser/file-truncate", - "parser/|>": "parser/file-truncate", - "parser/fwrite": "parser/file-truncate", - "parser/double-quote": "parser/double-quote", - "parser/scalar": "parser/scalar", - "parser/brace-quote": "parser/brace-quote", - "parser/create-array": "parser/create-array", - "parser/create-object": "parser/create-object", - "parser/logical-and": "parser/logical-and", - "parser/single-quote": "parser/single-quote", - "parser/(": "parser/brace-quote-func", - "parser/multiply-by": "parser/multiply-by", - "parser/multiplication": "parser/multiplication", - "parser/add-with": "parser/add-with", - "parser/addition": "parser/addition", - "parser/subtract-by": "parser/subtract-by", - "parser/pipe-arrow": "parser/pipe-arrow", - "parser/subtraction": "parser/subtraction", - "parser/divide-by": "parser/divide-by", - "parser/division": "parser/division", - "parser/assign-or-merge": "parser/assign-or-merge", - "parser/pipe-generic": "parser/pipe-generic", - "parser/=": "parser/equ", - "parser/>>": "parser/file-append", - "parser/fappend": "parser/file-append", - "parser/elvis": "parser/elvis", - "parser/null-coalescing": "parser/null-coalescing", - "parser/pipe-err": "parser/pipe-err", - "parser/array": "parser/array", - "parser/lambda": "parser/lambda", - "parser/curly-brace": "parser/curly-brace", - "parser/pipe-posix": "parser/pipe-posix", - "parser/logical-or": "parser/logical-or", - "parser/tilde": "parser/tilde", - "events/oncommandcompletion": "events/oncommandcompletion", - "events/onCommandCompletion": "events/oncommandcompletion", - "events/onfilesystemchange": "events/onfilesystemchange", - "events/onFileSystemChange": "events/onfilesystemchange", - "events/onkeypress": "events/onkeypress", - "events/onKeyPress": "events/onkeypress", - "events/onpreview": "events/onpreview", - "events/onPreview": "events/onpreview", - "events/onprompt": "events/onprompt", - "events/onPrompt": "events/onprompt", - "events/onsecondselapsed": "events/onsecondselapsed", - "events/onSecondsElapsed": "events/onsecondselapsed", - "events/onsignalreceived": "events/onsignalreceived", - "events/onSignalReceived": "events/onsignalreceived", - "types/generic": "types/generic", - "types/*": "types/generic", - "types/bool": "types/bool", - "types/commonlog": "types/commonlog", - "types/csv": "types/csv", - "types/float": "types/float", - "types/hcl": "types/hcl", - "types/int": "types/int", - "types/json": "types/json", - "types/jsonc": "types/jsonc", - "types/jsonl": "types/jsonl", - "types/num": "types/num", - "types/path": "types/path", - "types/paths": "types/paths", - "types/str": "types/str", - "types/string": "types/str", - "types/toml": "types/toml", - "types/yaml": "types/yaml", - "types/mxjson": "types/mxjson", - "variables/numeric": "variables/numeric", - "variables/meta-values": "variables/meta-values", - "variables/$.": "variables/meta-values", - "variables/argv": "variables/argv", - "variables/ARGV": "variables/argv", - "variables/ARGS": "variables/argv", - "variables/columns": "variables/columns", - "variables/COLUMNS": "variables/columns", - "variables/event_return": "variables/event_return", - "variables/EVENT_RETURN": "variables/event_return", - "variables/hostname": "variables/hostname", - "variables/HOSTNAME": "variables/hostname", - "variables/murex_argv": "variables/murex_argv", - "variables/MUREX_ARGV": "variables/murex_argv", - "variables/MUREX_ARGS": "variables/murex_argv", - "variables/murex_exe": "variables/murex_exe", - "variables/MUREX_EXE": "variables/murex_exe", - "variables/params": "variables/params", - "variables/PARAMS": "variables/params", - "variables/pwdhist": "variables/pwdhist", - "variables/PWDHIST": "variables/pwdhist", - "variables/pwd": "variables/pwd", - "variables/PWD": "variables/pwd", - "variables/self": "variables/self", - "variables/SELF": "variables/self", - "variables/shell": "variables/shell", - "variables/SHELL": "variables/shell", - "apis/Marshal": "apis/Marshal", - "apis/ReadArray": "apis/ReadArray", - "apis/ReadArrayWithType": "apis/ReadArrayWithType", - "apis/ReadIndex": "apis/ReadIndex", - "apis/ReadMap": "apis/ReadMap", - "apis/ReadNotIndex": "apis/ReadNotIndex", - "apis/Unmarshal": "apis/Unmarshal", - "apis/WriteArray": "apis/WriteArray", - "apis/lang.ArrayTemplate": "apis/lang.ArrayTemplate", + "commands/key-code": "commands/key-code", + "commands/addheading": "commands/addheading", + "commands/prefix": "commands/prefix", + "commands/list.prefix": "commands/prefix", + "commands/suffix": "commands/suffix", + "commands/list.suffix": "commands/suffix", + "commands/alias": "commands/alias", + "commands/!alias": "commands/alias", + "commands/alter": "commands/alter", + "commands/~>": "commands/alter", + "commands/append": "commands/append", + "commands/list.append": "commands/append", + "commands/bg": "commands/bg", + "commands/cpuarch": "commands/cpuarch", + "commands/sys.cpu.arch": "commands/cpuarch", + "commands/cpucount": "commands/cpucount", + "commands/sys.cpu.count": "commands/cpucount", + "commands/catch": "commands/catch", + "commands/!catch": "commands/catch", + "commands/cd": "commands/cd", + "commands/list.case": "commands/list.case", + "commands/bexists": "commands/bexists", + "commands/history": "commands/history", + "commands/count": "commands/count", + "commands/len": "commands/count", + "commands/2darray": "commands/2darray", + "commands/ja": "commands/ja", + "commands/map": "commands/map", + "commands/pipe": "commands/pipe", + "commands/!pipe": "commands/pipe", + "commands/ta": "commands/ta", + "commands/tmp": "commands/tmp", + "commands/datetime": "commands/datetime", + "commands/str.datetime": "commands/datetime", + "commands/debug": "commands/debug", + "commands/export": "commands/export", + "commands/!export": "commands/export", + "commands/unset": "commands/export", + "commands/var.env": "commands/export", + "commands/!var.env": "commands/export", + "commands/args": "commands/args", + "commands/global": "commands/global", + "commands/!global": "commands/global", + "commands/openagent": "commands/openagent", + "commands/!openagent": "commands/openagent", + "commands/method": "commands/method", + "commands/cast": "commands/cast", + "commands/set": "commands/set", + "commands/!set": "commands/set", + "commands/unsafe": "commands/unsafe", + "commands/type": "commands/type", + "commands/fid-list": "commands/fid-list", + "commands/jobs": "commands/fid-list", + "commands/getfile": "commands/getfile", + "commands/err": "commands/err", + "commands/esccli": "commands/esccli", + "commands/eschtml": "commands/eschtml", + "commands/!eschtml": "commands/eschtml", + "commands/escurl": "commands/escurl", + "commands/!escurl": "commands/escurl", + "commands/exec": "commands/exec", + "commands/command": "commands/exec", + "commands/exec.file": "commands/exec", + "commands/fexec": "commands/fexec", + "commands/builtin": "commands/fexec", + "commands/exec.builtin": "commands/fexec", + "commands/exec.function": "commands/fexec", + "commands/exec.private": "commands/fexec", + "commands/break": "commands/break", + "commands/return": "commands/return", + "commands/exit": "commands/exit", + "commands/expr": "commands/expr", + "commands/false": "commands/false", + "commands/foreach": "commands/foreach", + "commands/formap": "commands/formap", + "commands/for": "commands/for", + "commands/fg": "commands/fg", + "commands/runmode": "commands/runmode", + "commands/rand": "commands/rand", + "commands/get-type": "commands/get-type", + "commands/exitnum": "commands/exitnum", + "commands/pt": "commands/pt", + "commands/get": "commands/get", + "commands/g": "commands/g", + "commands/!g": "commands/g", + "commands/if": "commands/if", + "commands/!if": "commands/if", + "commands/source": "commands/source", + "commands/.": "commands/source", + "commands/is-null": "commands/is-null", + "commands/mjoin": "commands/mjoin", + "commands/list.join": "commands/mjoin", + "commands/fid-killall": "commands/fid-killall", + "commands/fid-kill": "commands/fid-kill", + "commands/left": "commands/left", + "commands/list.left": "commands/left", + "commands/f": "commands/f", + "commands/which": "commands/which", + "commands/lockfile": "commands/lockfile", + "commands/and": "commands/and", + "commands/!and": "commands/and", + "commands/or": "commands/or", + "commands/!or": "commands/or", + "commands/while": "commands/while", + "commands/!while": "commands/while", + "commands/man-summary": "commands/man-summary", + "commands/help.man.summary": "commands/man-summary", + "commands/match": "commands/match", + "commands/!match": "commands/match", + "commands/list.str": "commands/match", + "commands/!list.str": "commands/match", + "commands/event": "commands/event", + "commands/!event": "commands/event", + "commands/murex-package": "commands/murex-package", + "commands/version": "commands/version", + "commands/murex-docs": "commands/murex-docs", + "commands/help": "commands/murex-docs", + "commands/continue": "commands/continue", + "commands/!": "commands/not-func", + "commands/not": "commands/not-func", + "commands/null": "commands/devnull", + "commands/open": "commands/open", + "commands/os": "commands/os", + "commands/sys.os": "commands/os", + "commands/out": "commands/out", + "commands/echo": "commands/out", + "commands/tout": "commands/tout", + "commands/man-get-flags": "commands/man-get-flags", + "commands/trypipe": "commands/trypipe", + "commands/post": "commands/post", + "commands/prepend": "commands/prepend", + "commands/list.prepend": "commands/prepend", + "commands/pretty": "commands/pretty", + "commands/struct-keys": "commands/struct-keys", + "commands/private": "commands/private", + "commands/time": "commands/time", + "commands/function": "commands/function", + "commands/!function": "commands/function", + "commands/escape": "commands/escape", + "commands/!escape": "commands/escape", + "commands/murex-update-exe-list": "commands/murex-update-exe-list", + "commands/read": "commands/read", + "commands/tread": "commands/tread", + "commands/format": "commands/format", + "commands/rx": "commands/rx", + "commands/!rx": "commands/rx", + "commands/regexp": "commands/regexp", + "commands/!regexp": "commands/regexp", + "commands/list.regex": "commands/regexp", + "commands/!list.regex": "commands/regexp", + "commands/open-image": "commands/open-image", + "commands/mtac": "commands/mtac", + "commands/list.reverse": "commands/mtac", + "commands/right": "commands/right", + "commands/list.right": "commands/right", + "commands/round": "commands/round", + "commands/num.round": "commands/round", + "commands/signal": "commands/signal", + "commands/summary": "commands/summary", + "commands/!summary": "commands/summary", + "commands/config": "commands/config", + "commands/!config": "commands/config", + "commands/runtime": "commands/runtime", + "commands/builtins": "commands/runtime", + "commands/shell.runtime": "commands/runtime", + "commands/test": "commands/test", + "commands/!test": "commands/test", + "commands/msort": "commands/msort", + "commands/list.sort": "commands/msort", + "commands/jsplit": "commands/jsplit", + "commands/str.split": "commands/jsplit", + "commands/trypipeerr": "commands/trypipeerr", + "commands/tryerr": "commands/tryerr", + "commands/a": "commands/a", + "commands/mkarray": "commands/a", + "commands/switch": "commands/switch", + "commands/autocomplete": "commands/autocomplete", + "commands/tabulate": "commands/tabulate", + "commands/true": "commands/true", + "commands/try": "commands/try", + "commands/die": "commands/die", + "commands/let": "commands/let", + "commands/murex-parser": "commands/murex-parser", + "mkarray/date": "mkarray/date", + "mkarray/character": "mkarray/character", + "mkarray/decimal": "mkarray/decimal", + "mkarray/non-decimal": "mkarray/non-decimal", + "mkarray/special": "mkarray/special", + "optional/select": "optional/select", + "optional/table.select": "optional/select", + "optional/!bz2": "optional/bz2", + "optional/base64": "optional/base64", + "optional/!base64": "optional/base64", + "optional/gz": "optional/gz", + "optional/!gz": "optional/gz", + "optional/qr": "optional/qr", + "optional/sleep": "optional/sleep", + "parser/expr-inlined": "parser/expr-inlined", + "parser/c-style-fun": "parser/c-style-fun", + "parser/@[": "parser/range", + "parser/[": "parser/item-index", + "parser/![": "parser/item-index", + "parser/item-index": "parser/item-index", + "parser/index": "parser/item-index", + "parser/[[": "parser/element", + "parser/element": "parser/element", + "parser/(murex named pipe)": "parser/namedpipe", + "parser/<>": "parser/namedpipe", + "parser/read-named-pipe": "parser/namedpipe", + "parser/": "parser/stdin", + "parser/>": "parser/file-truncate", + "parser/|>": "parser/file-truncate", + "parser/fwrite": "parser/file-truncate", + "parser/double-quote": "parser/double-quote", + "parser/scalar": "parser/scalar", + "parser/brace-quote": "parser/brace-quote", + "parser/create-array": "parser/create-array", + "parser/create-object": "parser/create-object", + "parser/logical-and": "parser/logical-and", + "parser/single-quote": "parser/single-quote", + "parser/(": "parser/brace-quote-func", + "parser/multiply-by": "parser/multiply-by", + "parser/multiplication": "parser/multiplication", + "parser/add-with": "parser/add-with", + "parser/addition": "parser/addition", + "parser/subtract-by": "parser/subtract-by", + "parser/pipe-arrow": "parser/pipe-arrow", + "parser/subtraction": "parser/subtraction", + "parser/divide-by": "parser/divide-by", + "parser/division": "parser/division", + "parser/assign-or-merge": "parser/assign-or-merge", + "parser/pipe-generic": "parser/pipe-generic", + "parser/=": "parser/equ", + "parser/>>": "parser/file-append", + "parser/fappend": "parser/file-append", + "parser/elvis": "parser/elvis", + "parser/null-coalescing": "parser/null-coalescing", + "parser/pipe-err": "parser/pipe-err", + "parser/array": "parser/array", + "parser/lambda": "parser/lambda", + "parser/curly-brace": "parser/curly-brace", + "parser/pipe-posix": "parser/pipe-posix", + "parser/logical-or": "parser/logical-or", + "parser/tilde": "parser/tilde", + "events/oncommandcompletion": "events/oncommandcompletion", + "events/onCommandCompletion": "events/oncommandcompletion", + "events/onfilesystemchange": "events/onfilesystemchange", + "events/onFileSystemChange": "events/onfilesystemchange", + "events/onkeypress": "events/onkeypress", + "events/onKeyPress": "events/onkeypress", + "events/onpreview": "events/onpreview", + "events/onPreview": "events/onpreview", + "events/onprompt": "events/onprompt", + "events/onPrompt": "events/onprompt", + "events/onsecondselapsed": "events/onsecondselapsed", + "events/onSecondsElapsed": "events/onsecondselapsed", + "events/onsignalreceived": "events/onsignalreceived", + "events/onSignalReceived": "events/onsignalreceived", + "types/generic": "types/generic", + "types/*": "types/generic", + "types/bool": "types/bool", + "types/commonlog": "types/commonlog", + "types/csv": "types/csv", + "types/float": "types/float", + "types/hcl": "types/hcl", + "types/int": "types/int", + "types/json": "types/json", + "types/jsonc": "types/jsonc", + "types/jsonl": "types/jsonl", + "types/num": "types/num", + "types/path": "types/path", + "types/paths": "types/paths", + "types/str": "types/str", + "types/string": "types/str", + "types/toml": "types/toml", + "types/yaml": "types/yaml", + "types/mxjson": "types/mxjson", + "variables/numeric": "variables/numeric", + "variables/meta-values": "variables/meta-values", + "variables/$.": "variables/meta-values", + "variables/argv": "variables/argv", + "variables/ARGV": "variables/argv", + "variables/ARGS": "variables/argv", + "variables/columns": "variables/columns", + "variables/COLUMNS": "variables/columns", + "variables/event_return": "variables/event_return", + "variables/EVENT_RETURN": "variables/event_return", + "variables/hostname": "variables/hostname", + "variables/HOSTNAME": "variables/hostname", + "variables/murex_argv": "variables/murex_argv", + "variables/MUREX_ARGV": "variables/murex_argv", + "variables/MUREX_ARGS": "variables/murex_argv", + "variables/murex_exe": "variables/murex_exe", + "variables/MUREX_EXE": "variables/murex_exe", + "variables/params": "variables/params", + "variables/PARAMS": "variables/params", + "variables/pwdhist": "variables/pwdhist", + "variables/PWDHIST": "variables/pwdhist", + "variables/pwd": "variables/pwd", + "variables/PWD": "variables/pwd", + "variables/self": "variables/self", + "variables/SELF": "variables/self", + "variables/shell": "variables/shell", + "variables/SHELL": "variables/shell", + "apis/Marshal": "apis/Marshal", + "apis/ReadArray": "apis/ReadArray", + "apis/ReadArrayWithType": "apis/ReadArrayWithType", + "apis/ReadIndex": "apis/ReadIndex", + "apis/ReadMap": "apis/ReadMap", + "apis/ReadNotIndex": "apis/ReadNotIndex", + "apis/Unmarshal": "apis/Unmarshal", + "apis/WriteArray": "apis/WriteArray", + "apis/lang.ArrayTemplate": "apis/lang.ArrayTemplate", "apis/lang.ArrayWithTypeTemplate": "apis/lang.ArrayWithTypeTemplate", - "apis/lang.IndexTemplateObject": "apis/lang.IndexTemplateObject", - "apis/lang.IndexTemplateTable": "apis/lang.IndexTemplateTable", - "apis/lang.MarshalData": "apis/lang.MarshalData", - "apis/lang.UnmarshalData": "apis/lang.UnmarshalData", - "user-guide/ansi": "user-guide/ansi", - "user-guide/bang-prefix": "user-guide/bang-prefix", - "user-guide/bang": "user-guide/bang-prefix", - "user-guide/code-block": "user-guide/code-block", - "user-guide/fileref": "user-guide/fileref", - "user-guide/FileRef": "user-guide/fileref", - "user-guide/hint-text": "user-guide/hint-text", - "user-guide/integrations": "user-guide/integrations", - "user-guide/interactive-shell": "user-guide/interactive-shell", - "user-guide/repl": "user-guide/interactive-shell", - "user-guide/readline": "user-guide/interactive-shell", - "user-guide/job-control": "user-guide/job-control", - "user-guide/module": "user-guide/modules", - "user-guide/modules": "user-guide/modules", - "user-guide/package": "user-guide/modules", - "user-guide/packages": "user-guide/modules", - "user-guide/namedpipes": "user-guide/namedpipes", + "apis/lang.IndexTemplateObject": "apis/lang.IndexTemplateObject", + "apis/lang.IndexTemplateTable": "apis/lang.IndexTemplateTable", + "apis/lang.MarshalData": "apis/lang.MarshalData", + "apis/lang.UnmarshalData": "apis/lang.UnmarshalData", + "user-guide/ansi": "user-guide/ansi", + "user-guide/bang-prefix": "user-guide/bang-prefix", + "user-guide/bang": "user-guide/bang-prefix", + "user-guide/code-block": "user-guide/code-block", + "user-guide/fileref": "user-guide/fileref", + "user-guide/FileRef": "user-guide/fileref", + "user-guide/hint-text": "user-guide/hint-text", + "user-guide/integrations": "user-guide/integrations", + "user-guide/interactive-shell": "user-guide/interactive-shell", + "user-guide/repl": "user-guide/interactive-shell", + "user-guide/readline": "user-guide/interactive-shell", + "user-guide/job-control": "user-guide/job-control", + "user-guide/module": "user-guide/modules", + "user-guide/modules": "user-guide/modules", + "user-guide/package": "user-guide/modules", + "user-guide/packages": "user-guide/modules", + "user-guide/namedpipes": "user-guide/namedpipes", "user-guide/operators-and-tokens": "user-guide/operators-and-tokens", - "user-guide/pipeline": "user-guide/pipeline", - "user-guide/profile": "user-guide/profile", - "user-guide/.murex_profile": "user-guide/profile", - "user-guide/murex_profile": "user-guide/profile", - "user-guide/.murex_preload": "user-guide/profile", - "user-guide/murex_preload": "user-guide/profile", - "user-guide/reserved-vars": "user-guide/reserved-vars", - "user-guide/reserved": "user-guide/reserved-vars", - "user-guide/reserved-variables": "user-guide/reserved-vars", - "user-guide/special-vars": "user-guide/reserved-vars", - "user-guide/special-variables": "user-guide/reserved-vars", - "user-guide/rosetta-stone": "user-guide/rosetta-stone", - "user-guide/schedulers": "user-guide/schedulers", - "user-guide/strict-types": "user-guide/strict-types", - "user-guide/hotkeys": "user-guide/terminal-keys", - "user-guide/scoping": "user-guide/scoping", - "integrations/chatgpt": "integrations/chatgpt", - "integrations/ChatGPT": "integrations/chatgpt", - "integrations/cheatsh": "integrations/cheatsh", - "integrations/cheat.sh": "integrations/cheatsh", - "integrations/kitty": "integrations/kitty", - "integrations/make": "integrations/make", - "integrations/Makefile": "integrations/make", - "integrations/man-pages": "integrations/man-pages", - "integrations/spellcheck": "integrations/spellcheck", - "integrations/terminology": "integrations/terminology", - "integrations/direnv": "integrations/direnv", - "integrations/yarn": "integrations/yarn", - "integrations/package.json": "integrations/yarn", - "integrations/iterm2": "integrations/iterm2", - "changelog/v2.0": "changelog/v2.0", - "changelog/v2.1": "changelog/v2.1", - "changelog/v2.10": "changelog/v2.10", - "changelog/v2.11": "changelog/v2.11", - "changelog/v2.2": "changelog/v2.2", - "changelog/v2.3": "changelog/v2.3", - "changelog/v2.4": "changelog/v2.4", - "changelog/v2.5": "changelog/v2.5", - "changelog/v2.6": "changelog/v2.6", - "changelog/v2.7": "changelog/v2.7", - "changelog/v2.8": "changelog/v2.8", - "changelog/v2.9": "changelog/v2.9", - "changelog/v3.0": "changelog/v3.0", - "changelog/v3.1": "changelog/v3.1", - "changelog/v4.0": "changelog/v4.0", - "changelog/v4.1": "changelog/v4.1", - "changelog/v4.2": "changelog/v4.2", - "changelog/v4.3": "changelog/v4.3", - "changelog/v4.4": "changelog/v4.4", - "changelog/v5.0": "changelog/v5.0", - "changelog/v5.1": "changelog/v5.1", - "changelog/v5.2": "changelog/v5.2", - "changelog/v5.3": "changelog/v5.3", - "changelog/v6.0": "changelog/v6.0", - "changelog/v6.1": "changelog/v6.1", - "changelog/v6.2": "changelog/v6.2", - + "user-guide/pipeline": "user-guide/pipeline", + "user-guide/profile": "user-guide/profile", + "user-guide/.murex_profile": "user-guide/profile", + "user-guide/murex_profile": "user-guide/profile", + "user-guide/.murex_preload": "user-guide/profile", + "user-guide/murex_preload": "user-guide/profile", + "user-guide/reserved-vars": "user-guide/reserved-vars", + "user-guide/reserved": "user-guide/reserved-vars", + "user-guide/reserved-variables": "user-guide/reserved-vars", + "user-guide/special-vars": "user-guide/reserved-vars", + "user-guide/special-variables": "user-guide/reserved-vars", + "user-guide/rosetta-stone": "user-guide/rosetta-stone", + "user-guide/schedulers": "user-guide/schedulers", + "user-guide/strict-types": "user-guide/strict-types", + "user-guide/hotkeys": "user-guide/terminal-keys", + "user-guide/scoping": "user-guide/scoping", + "integrations/chatgpt": "integrations/chatgpt", + "integrations/ChatGPT": "integrations/chatgpt", + "integrations/cheatsh": "integrations/cheatsh", + "integrations/cheat.sh": "integrations/cheatsh", + "integrations/kitty": "integrations/kitty", + "integrations/make": "integrations/make", + "integrations/Makefile": "integrations/make", + "integrations/man-pages": "integrations/man-pages", + "integrations/spellcheck": "integrations/spellcheck", + "integrations/terminology": "integrations/terminology", + "integrations/direnv": "integrations/direnv", + "integrations/yarn": "integrations/yarn", + "integrations/package.json": "integrations/yarn", + "integrations/iterm2": "integrations/iterm2", + "changelog/v2.0": "changelog/v2.0", + "changelog/v2.1": "changelog/v2.1", + "changelog/v2.10": "changelog/v2.10", + "changelog/v2.11": "changelog/v2.11", + "changelog/v2.2": "changelog/v2.2", + "changelog/v2.3": "changelog/v2.3", + "changelog/v2.4": "changelog/v2.4", + "changelog/v2.5": "changelog/v2.5", + "changelog/v2.6": "changelog/v2.6", + "changelog/v2.7": "changelog/v2.7", + "changelog/v2.8": "changelog/v2.8", + "changelog/v2.9": "changelog/v2.9", + "changelog/v3.0": "changelog/v3.0", + "changelog/v3.1": "changelog/v3.1", + "changelog/v4.0": "changelog/v4.0", + "changelog/v4.1": "changelog/v4.1", + "changelog/v4.2": "changelog/v4.2", + "changelog/v4.3": "changelog/v4.3", + "changelog/v4.4": "changelog/v4.4", + "changelog/v5.0": "changelog/v5.0", + "changelog/v5.1": "changelog/v5.1", + "changelog/v5.2": "changelog/v5.2", + "changelog/v5.3": "changelog/v5.3", + "changelog/v6.0": "changelog/v6.0", + "changelog/v6.1": "changelog/v6.1", + "changelog/v6.2": "changelog/v6.2", } -} \ No newline at end of file +} diff --git a/docs/blog/README.md b/docs/blog/README.md index 32a330c1b..d11b8b608 100644 --- a/docs/blog/README.md +++ b/docs/blog/README.md @@ -1,6 +1,6 @@ # Blog -Collection of Murex related documents and personal thoughts. +A collection of Murex related documents and personal thoughts. ## Articles diff --git a/docs/commands/export.md b/docs/commands/export.md index 086c398a3..8b1e968cb 100644 --- a/docs/commands/export.md +++ b/docs/commands/export.md @@ -281,7 +281,7 @@ bar Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/commands/get-type.md b/docs/commands/get-type.md index 1d67f2c05..69453ccbb 100644 --- a/docs/commands/get-type.md +++ b/docs/commands/get-type.md @@ -65,7 +65,7 @@ json Special variables reserved by Murex * [Shell Runtime (`runtime`)](../commands/runtime.md): Returns runtime information on the internal state of Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex
      diff --git a/docs/commands/global.md b/docs/commands/global.md index 40f0be19d..4101fc045 100644 --- a/docs/commands/global.md +++ b/docs/commands/global.md @@ -267,7 +267,7 @@ bar Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/commands/is-null.md b/docs/commands/is-null.md index 27792738d..87294657b 100644 --- a/docs/commands/is-null.md +++ b/docs/commands/is-null.md @@ -59,7 +59,7 @@ if { is-null foobar } then { Define a variable (typically local) and set it's value * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`??` Null Coalescing Operator](../parser/null-coalescing.md): Returns the right operand if the left operand is empty / undefined (expression) diff --git a/docs/commands/let.md b/docs/commands/let.md index bfa68b054..58ecbe958 100644 --- a/docs/commands/let.md +++ b/docs/commands/let.md @@ -411,7 +411,7 @@ bar Conditional statement to execute different blocks of code depending on the result of the condition * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/commands/set.md b/docs/commands/set.md index aaf2ed852..e9a41be99 100644 --- a/docs/commands/set.md +++ b/docs/commands/set.md @@ -269,7 +269,7 @@ bar Checks if a variable is null or undefined * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/integrations/README.md b/docs/integrations/README.md index 7eb4403f4..215100ae3 100644 --- a/docs/integrations/README.md +++ b/docs/integrations/README.md @@ -38,26 +38,3 @@ Murex's base install. Working with `yarn` and `package.json` * [iTerm2 Integrations](../integrations/iterm2.md): Get more out of iTerm2 terminal emulator - -## Pages - -* [ChatGPT](../integrations/chatgpt.md): - How to enable ChatGPT hints -* [Cheat.sh](../integrations/cheatsh.md): - Cheatsheets provided by cheat.sh -* [Kitty Integrations](../integrations/kitty.md): - Get more out of Kitty terminal emulator -* [Makefiles / `make`](../integrations/make.md): - `make` integrations -* [Man Pages (POSIX)](../integrations/man-pages.md): - Linux/UNIX `man` page integrations -* [Spellcheck](../integrations/spellcheck.md): - How to enable inline spellchecking -* [Terminology Integrations](../integrations/terminology.md): - Get more out of Terminology terminal emulator -* [`direnv` Integrations](../integrations/direnv.md): - Directory specific environmental variables -* [`yarn` Integrations](../integrations/yarn.md): - Working with `yarn` and `package.json` -* [iTerm2 Integrations](../integrations/iterm2.md): - Get more out of iTerm2 terminal emulator \ No newline at end of file diff --git a/docs/parser/equ.md b/docs/parser/equ.md index 9f4c549ae..e71de8641 100644 --- a/docs/parser/equ.md +++ b/docs/parser/equ.md @@ -206,7 +206,7 @@ Murex uses the [govaluate package](https://github.com/Knetic/govaluate). More in Conditional statement to execute different blocks of code depending on the result of the condition * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`%(Brace Quote)`](../parser/brace-quote.md): Initiates or terminates a string (variables expanded) diff --git a/docs/parser/scalar.md b/docs/parser/scalar.md index cc051defb..c46a4faed 100644 --- a/docs/parser/scalar.md +++ b/docs/parser/scalar.md @@ -14,11 +14,11 @@ spaces as any other printable character character. ## Variable Syntax -There are two basic syntaxes. Bare an enclosed. +There are two basic syntaxes. _Bare_ and _enclosed_. ### Bare Syntax -Bare syntax looks like the following: +_Bare_ syntax looks like the following: ``` $scalar @@ -30,13 +30,13 @@ alpha (`a` to `z`, upper and lower case), numeric (`0` to `1`), underscore ### Enclosed Syntax -Enclosed syntax looks like the following: +_Enclosed_ syntax looks like the following: ``` $(scalar) ``` -Enclosed syntax supports any unicode characters however the variable name +_Enclosed_ syntax supports any unicode characters however the variable name needs to be surrounded by parenthesis. See examples below. diff --git a/docs/types/README.md b/docs/types/README.md index 99857ff66..6ce5f0cdd 100644 --- a/docs/types/README.md +++ b/docs/types/README.md @@ -12,19 +12,32 @@ Read the [Language Tour](/docs/tour.md) for more detail on this topic. For clarity, it is worth explaining a couple of terms: -1. "Data-types" in Murex are a description of the format of data. This -means that while any stdio stream in UNIX will by "bytes", Murex might -label that data as being a JSON string or CSV file (for example) which -means any builtins that parse that stdio stream, for example to return -the first 8 items, would need to parse those types differently. Thus a -"data-type" in Murex is actually more than just a description of a data -structure; it is a series of APIs to marshall and unmarshall data from -complex file formats. This enables you to use the same command line tools -to query any type of output. +1. _Data-types_ in Murex _data-types_ are an annotation describing the format + of data contained in a pipe or variable. _Data-types_ can be _primitives_ or + structured documents like JSON, CSV, and s-expressions. -2. "Primitive" data-types refer to types that are the required by Murex -to function. These will be `int`, `float` / `number`, `bool`, `string`, -`generic`, and `null`. + Objects like maps and arrays are just documents (typically JSON) however + because Murex's builtin commands and expressions work consistently across a + multitude of different document types, those JSON objects and CSV tables + (et al) feel as native as Murex _data-types_, as strings do in Bash, s-expr + in LISP and JSON in JavaScript. + +2. _Primitives_ refer to the atomic component of a _data-type_. In other words, + the smallest possible format for a piece of data. Where a JSON file might + arrays and maps, the values for those objects cannot be divided any smaller + than numbers, strings or a small number of constants like `true`, `false`, + and `null`. + + In Murex, these are defined as _primitives_ and the following _data-types_ + are considered to be _primitive types_: + + * Numeric: `int`, `float` and `num` + + * Boolean: `bool` + + * Text: `string` and `*` (generic) + + * Null: `null` ## Feature Sets diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 82dea5f52..e1250b4e4 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -64,7 +64,7 @@ The [Language Tour](/tour.md) is a great introduction into the Murex language. Expressions can auto-convert types or strictly honour data types * [Terminal Hotkeys](../user-guide/terminal-keys.md): A list of all the terminal hotkeys and their uses -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex ## Operators And Tokens diff --git a/docs/user-guide/reserved-vars.md b/docs/user-guide/reserved-vars.md index febc4ed4f..b27b76a9c 100644 --- a/docs/user-guide/reserved-vars.md +++ b/docs/user-guide/reserved-vars.md @@ -34,7 +34,7 @@ Error in `set` (0,1): cannot set a reserved variable: SELF An introduction to Murex modules and packages * [Pipeline](../user-guide/pipeline.md): Overview of what a "pipeline" is -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex
      diff --git a/docs/user-guide/scoping.md b/docs/user-guide/scoping.md index d70519add..eb26eb69a 100644 --- a/docs/user-guide/scoping.md +++ b/docs/user-guide/scoping.md @@ -1,10 +1,10 @@ -# Variable and Config Scoping +# Variable And Config Scoping > How scoping works within Murex ## Description -A 'scope' in Murex is a collection of code blocks to which variables and +A _scope_ in Murex is a collection of code blocks to which variables and config are persistent within. In Murex, a variable declared inside an `if` or `foreach` block will be persistent outside of their blocks as long as you're still inside the same function. @@ -21,7 +21,7 @@ function example { In here the value is getting set inside an `if` block but its value is is retrieved outside of that block. `out` and `set` have different parents but -the same scoping. +the same _scoping_. Then lets set **foo** outside of that function and see what happens: @@ -38,16 +38,16 @@ oof ``` Despite setting a variable named **foo**, the value inside **example** does not -overwrite the value outside **example** because they occupy different scoping. +overwrite the value outside **example** because they occupy different _scoping_. ## What Instantiates A New Scope? -A new scope is instantiated by anything which resembles a function. This would -be code inside events, dynamic autocompletes, open agents, any code blocks -defined in `config`, as well as public and private functions too. +A new _scope_ is instantiated by anything which resembles a function. This +would be code inside events, dynamic autocompletes, open agents, any code +blocks defined in `config`, as well as public and private functions too. Code inside an `if`, `switch`, `foreach` and `source` do not create a new -scope. Subshells also do not create a new scope either. +_scope_. Sub-shells also do not create a new _scope_ either. ## See Also diff --git a/docs/user-guide/strict-types.md b/docs/user-guide/strict-types.md index 06358b040..5dc70d609 100644 --- a/docs/user-guide/strict-types.md +++ b/docs/user-guide/strict-types.md @@ -56,7 +56,7 @@ changing this option will not cause accidental side-effects in other functions. Getting started with Murex: a quick tour of the next generation of shell scripting * [Shell Configuration And Settings (`config`)](../commands/config.md): Query or define Murex runtime settings -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex
      diff --git a/docs/variables/argv.md b/docs/variables/argv.md index 6e6140ac4..fcd9383b8 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -83,7 +83,7 @@ deprecated and may be removed from future releases. Special variables reserved by Murex * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`@Array` Sigil](../parser/array.md): Expand values as an array diff --git a/docs/variables/params.md b/docs/variables/params.md index e7235d7fa..44f527d91 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -71,7 +71,7 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Special variables reserved by Murex * [Tab Autocompletion (`autocomplete`)](../commands/autocomplete.md): Set definitions for tab-completion in the command line -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`@Array` Sigil](../parser/array.md): Expand values as an array diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index 86bad8bb4..c69981a2b 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -62,7 +62,7 @@ It is updated via `cd` however you can overwrite its value manually via `set`. Overview of what a "pipeline" is * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`@Array` Sigil](../parser/array.md): Expand values as an array diff --git a/docs/variables/self.md b/docs/variables/self.md index 56a9d620b..d0c54bff4 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -121,7 +121,7 @@ terminal (TTY) or a pipe?) Define a function block * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [Variable and Config Scoping](../user-guide/scoping.md): +* [Variable And Config Scoping](../user-guide/scoping.md): How scoping works within Murex * [`json`](../types/json.md): JavaScript Object Notation (JSON) diff --git a/gen/blog-md-cat.tmpl b/gen/blog-md-cat.tmpl index 660ba68fc..3f4ff09e9 100644 --- a/gen/blog-md-cat.tmpl +++ b/gen/blog-md-cat.tmpl @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} index: true icon: comment category: {{ .ID }} diff --git a/gen/changelog-md-cat.tmpl b/gen/changelog-md-cat.tmpl index 172984128..6be0f7dd0 100644 --- a/gen/changelog-md-cat.tmpl +++ b/gen/changelog-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true title: {{ .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} icon: laptop-code category: {{ .ID }} --- diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index 84708f119..f2f0d2d6b 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true title: {{ .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} icon: cubes category: {{ .ID }} --- diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 854ed865d..799e807b7 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -14,6 +14,8 @@ Categories: - ID: commands Title: Builtin Commands + Summary: >- + Write portable scripts knowing that Murex ships it's own coreutils. Better still, have the power of `jq`, `awk`, `sed` (etc) against any data format you wish (YAML, CSV, etc) and using the same basic syntax and commands Description: |- {{ include "gen/commands-md-cat.inc.md" }} @@ -111,6 +113,7 @@ Categories: - ID: mkarray Title: mkarray + Summary: Description: Templates: - OutputPath: docs/mkarray @@ -123,6 +126,8 @@ Categories: - ID: optional Title: Optional Builtins Reference + Summary: >- + {{ include "gen/optionals-md-cat.inc.md" }} Description: |- {{ include "gen/optionals-md-cat.inc.md" }} @@ -135,6 +140,8 @@ Categories: - ID: parser Title: Parser Reference + Summary: >- + Murex supports both expressions and statements. Thus you have a flexible language that is both highly readable and yet still concise. No other shell offers the best of both these worlds as well as Murex does Description: |- {{ include "gen/parser-md-cat.inc.md" }} @@ -194,6 +201,8 @@ Categories: # events: - ID: events Title: events + Summary: >- + Murex's event system allows for easy and flexible code. You can extend upon the shell in a multitude of ways. Description: Templates: - OutputPath: docs/events @@ -205,6 +214,8 @@ Categories: # types: - ID: types Title: Data-Type Reference + Summary: >- + Murex's builtin commands and expressions work consistently across a multitude of different document types, those JSON objects and CSV tables (et al) feel as native as Murex _data-types_, as strings do in Bash, s-expr in LISP and JSON in JavaScript. Description: |- {{ include "gen/types-md-cat.inc.md" }} @@ -219,6 +230,8 @@ Categories: - ID: variables Title: Special Variables + Summary: >- + Variables are tokenised, so to avoid accidental bugs caused by (for example) spaces in file names. Enhancements like these are what makes Murex a much safer language than traditional shells Description: Templates: - OutputPath: docs/variables @@ -254,6 +267,8 @@ Categories: # apis: - ID: apis Title: API Reference + Summary: >- + These APIs are provided for reference for any developers wishing to write their own Murex builtins. Description: |- {{ include "gen/apis-md-cat.inc.md" }} @@ -267,6 +282,8 @@ Categories: # user guide: - ID: user-guide Title: User Guide + Summary: >- + Murex doesn't just aim to be a well thought out language, the interactive shell boast an excellent out-of-the-box experience with makes other shells feel stone age in comparison Description: |- This section contains miscellaneous documents on using and configuring the shell and Murex's numerous features. @@ -280,6 +297,8 @@ Categories: # integrations - ID: integrations Title: Integrations + Summary: >- + Murex aims to provide you with the best support for your wider command line needs, in its "out-of-the-box" configuration Description: Templates: - OutputPath: docs/integrations @@ -291,8 +310,10 @@ Categories: # blog - ID: blog Title: Blog + Summary: >- + A collection of Murex related documents and personal thoughts Description: |- - Collection of Murex related documents and personal thoughts. + A collection of Murex related documents and personal thoughts. Templates: - OutputPath: docs/blog CategoryFile: README.md @@ -303,6 +324,8 @@ Categories: # changelog - ID: changelog Title: Change Log + Summary: >- + Murex is committed to backwards compatibility. While we do want to continue to grow and improve the shell, this will not come at the expense of long term usability. Read more about the latest enhancements and bug fixes Description: |- Track new features, any breaking changes, and the release history here. Templates: diff --git a/gen/events-md-cat.tmpl b/gen/events-md-cat.tmpl index ba7a105fa..279bbc485 100644 --- a/gen/events-md-cat.tmpl +++ b/gen/events-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true title: {{ .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} category: {{ .ID }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} diff --git a/gen/integrations-md-cat.tmpl b/gen/integrations-md-cat.tmpl index 143389589..6c48ae453 100644 --- a/gen/integrations-md-cat.tmpl +++ b/gen/integrations-md-cat.tmpl @@ -2,16 +2,10 @@ index: true icon: puzzle-piece title: {{ quote .Title }} -description: {{ quote $doc.Summary }} +description: {{ quote .Summary }} category: {{ .ID }} --- {{ end }}# {{ .Title }} {{ include $doc.Description }} - -## Pages - -{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} -{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): - {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/murex-md-cat.tmpl b/gen/murex-md-cat.tmpl index 7fc6bc0f2..22e8a0591 100644 --- a/gen/murex-md-cat.tmpl +++ b/gen/murex-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true title: {{ md .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} category: {{ .ID }} --- diff --git a/gen/parser-md-cat.tmpl b/gen/parser-md-cat.tmpl index f179613e3..79a952006 100644 --- a/gen/parser-md-cat.tmpl +++ b/gen/parser-md-cat.tmpl @@ -1,6 +1,6 @@ {{ $doc := doct "" "operators-and-tokens" }}{{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ $doc.Title }} -description: {{ quote $doc.Summary }} +description: {{ quote .Summary }} index: true category: {{ .ID }} --- diff --git a/gen/parser/variables_doc.yaml b/gen/parser/variables_doc.yaml index 2bcf81d61..558c93329 100644 --- a/gen/parser/variables_doc.yaml +++ b/gen/parser/variables_doc.yaml @@ -16,11 +16,11 @@ ## Variable Syntax - There are two basic syntaxes. Bare an enclosed. + There are two basic syntaxes. _Bare_ and _enclosed_. ### Bare Syntax - Bare syntax looks like the following: + _Bare_ syntax looks like the following: ``` $scalar @@ -32,13 +32,13 @@ ### Enclosed Syntax - Enclosed syntax looks like the following: + _Enclosed_ syntax looks like the following: ``` $(scalar) ``` - Enclosed syntax supports any unicode characters however the variable name + _Enclosed_ syntax supports any unicode characters however the variable name needs to be surrounded by parenthesis. See examples below. Examples: |- diff --git a/gen/types-md-cat.inc.md b/gen/types-md-cat.inc.md index ea3a12be6..c8c649c91 100644 --- a/gen/types-md-cat.inc.md +++ b/gen/types-md-cat.inc.md @@ -10,19 +10,32 @@ Read the [Language Tour]({{if env "DOCGEN_TARGET="}}/docs{{end}}/tour.md) for mo For clarity, it is worth explaining a couple of terms: -1. "Data-types" in Murex are a description of the format of data. This -means that while any stdio stream in UNIX will by "bytes", Murex might -label that data as being a JSON string or CSV file (for example) which -means any builtins that parse that stdio stream, for example to return -the first 8 items, would need to parse those types differently. Thus a -"data-type" in Murex is actually more than just a description of a data -structure; it is a series of APIs to marshall and unmarshall data from -complex file formats. This enables you to use the same command line tools -to query any type of output. - -2. "Primitive" data-types refer to types that are the required by Murex -to function. These will be `int`, `float` / `number`, `bool`, `string`, -`generic`, and `null`. +1. _Data-types_ in Murex _data-types_ are an annotation describing the format + of data contained in a pipe or variable. _Data-types_ can be _primitives_ or + structured documents like JSON, CSV, and s-expressions. + + Objects like maps and arrays are just documents (typically JSON) however + because Murex's builtin commands and expressions work consistently across a + multitude of different document types, those JSON objects and CSV tables + (et al) feel as native as Murex _data-types_, as strings do in Bash, s-expr + in LISP and JSON in JavaScript. + +2. _Primitives_ refer to the atomic component of a _data-type_. In other words, + the smallest possible format for a piece of data. Where a JSON file might + arrays and maps, the values for those objects cannot be divided any smaller + than numbers, strings or a small number of constants like `true`, `false`, + and `null`. + + In Murex, these are defined as _primitives_ and the following _data-types_ + are considered to be _primitive types_: + + * Numeric: `int`, `float` and `num` + + * Boolean: `bool` + + * Text: `string` and `*` (generic) + + * Null: `null` ## Feature Sets diff --git a/gen/user-guide/scoping_doc.yaml b/gen/user-guide/scoping_doc.yaml index ddc004702..c03dee9b5 100644 --- a/gen/user-guide/scoping_doc.yaml +++ b/gen/user-guide/scoping_doc.yaml @@ -1,13 +1,13 @@ - DocumentID: scoping Title: >- - Variable and Config Scoping + Variable And Config Scoping CategoryID: user-guide Summary: >- How scoping works within Murex Description: |- ## Description - A 'scope' in Murex is a collection of code blocks to which variables and + A _scope_ in Murex is a collection of code blocks to which variables and config are persistent within. In Murex, a variable declared inside an `if` or `foreach` block will be persistent outside of their blocks as long as you're still inside the same function. @@ -24,7 +24,7 @@ In here the value is getting set inside an `if` block but its value is is retrieved outside of that block. `out` and `set` have different parents but - the same scoping. + the same _scoping_. Then lets set **foo** outside of that function and see what happens: @@ -41,16 +41,16 @@ ``` Despite setting a variable named **foo**, the value inside **example** does not - overwrite the value outside **example** because they occupy different scoping. + overwrite the value outside **example** because they occupy different _scoping_. ## What Instantiates A New Scope? - A new scope is instantiated by anything which resembles a function. This would - be code inside events, dynamic autocompletes, open agents, any code blocks - defined in `config`, as well as public and private functions too. + A new _scope_ is instantiated by anything which resembles a function. This + would be code inside events, dynamic autocompletes, open agents, any code + blocks defined in `config`, as well as public and private functions too. Code inside an `if`, `switch`, `foreach` and `source` do not create a new - scope. Subshells also do not create a new scope either. + _scope_. Sub-shells also do not create a new _scope_ either. Synonyms: Related: - set diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index 7ad20b59c..11555d8e1 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- title: {{ md .Title }} -description: {{ quote .Description }} +description: {{ quote .Summary }} index: true icon: book category: {{ .ID }} diff --git a/gen/variables-md-cat.tmpl b/gen/variables-md-cat.tmpl index 3e8fd2410..a185786dc 100644 --- a/gen/variables-md-cat.tmpl +++ b/gen/variables-md-cat.tmpl @@ -1,6 +1,6 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true -description: {{ quote .Description }} +description: {{ quote .Summary }} category: {{ .ID }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} diff --git a/utils/docgen/api/category.go b/utils/docgen/api/category.go index 79c0269ea..6c297f7b5 100644 --- a/utils/docgen/api/category.go +++ b/utils/docgen/api/category.go @@ -13,9 +13,12 @@ type category struct { // Name of the category Title string `yaml:"Title"` + Summary string `yaml:"Summary"` + // Description of the category Description string `yaml:"Description"` + // VueIcon is the Font Awesome icon used in VuePress VueIcon string `yaml:"VueIcon"` SubCategories []*category `yaml:"SubCategories"` @@ -33,7 +36,7 @@ func (c *category) SubCategoryByID(id string) (*category, error) { return nil, fmt.Errorf("cannot find a sub-category with the id '%s'", id) } -func (c *category) getSubCategoryTitle(id string) string { +/*func (c *category) getSubCategoryTitle(id string) string { sub, err := c.SubCategoryByID(id) if err != nil { return "" @@ -49,7 +52,7 @@ func (c *category) getSubCategoryDescription(id string) string { } return sub.Description -} +}*/ type templates struct { // OutputPath to write the rendered documents @@ -99,6 +102,7 @@ func (t templates) CategoryValues(docs documents) *categoryValues { return &categoryValues{ ID: t.ref.ID, Title: t.ref.Title, + Summary: t.ref.Summary, Description: t.ref.Description, Documents: dv, DateTime: dt, @@ -150,6 +154,7 @@ func (t templates) subCategoryValues(docs documents, cat *category) *categoryVal return &categoryValues{ ID: cat.ID, Title: cat.Title, + Summary: cat.Summary, Description: cat.Description, Documents: dv, DateTime: dt, @@ -160,6 +165,7 @@ func (t templates) subCategoryValues(docs documents, cat *category) *categoryVal type categoryValues struct { ID string Title string + Summary string Description string Documents []*documentValues DateTime []*documentValues diff --git a/utils/docgen/main.go b/utils/docgen/main.go index db72e7321..0b506978e 100644 --- a/utils/docgen/main.go +++ b/utils/docgen/main.go @@ -11,7 +11,7 @@ import ( const ( // Version is the release ID of docgen - Version = "4.0.0" + Version = "4.1.0" // Copyright is the copyright owner string Copyright = "(c) 2018-2024 Laurence Morgan" diff --git a/version.svg b/version.svg index c3d48d982..e020c2383 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4170Version6.3.4170 +Version: 6.3.4172Version6.3.4172 From ba86fa4213b6439c7e3e60f43e3787025cae62f7 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 19:17:32 +0100 Subject: [PATCH 135/142] websote: fix typos --- app/app.go | 4 ++-- docs/tour.md | 4 ++-- gen/docgen.yaml | 2 +- gen/root/tour.inc.md | 4 ++-- version.svg | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/app.go b/app/app.go index 935a68623..2fc287c6b 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4172 + Revision = 4173 Branch = "develop" - BuildDate = "2024-09-15 19:10:50" + BuildDate = "2024-09-15 19:17:35" ) // Copyright is the copyright owner string diff --git a/docs/tour.md b/docs/tour.md index 09208bae2..708d6bd4d 100644 --- a/docs/tour.md +++ b/docs/tour.md @@ -69,8 +69,8 @@ and UNIX over the last 50 years. Murex doesn't just aim to be a well thought out language, the interactive shell -boast an excellent out-of-the-box experience with makes other shells feel stone -age in comparison. +boasts an excellent out-of-the-box experience which makes other shells feel +stone age in comparison. If you want to learn more about the interactive shell then there is a dedicated document detailing [Murex's REPL features](/docs/user-guide/interactive-shell.md). diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 799e807b7..648c9eb24 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -283,7 +283,7 @@ Categories: - ID: user-guide Title: User Guide Summary: >- - Murex doesn't just aim to be a well thought out language, the interactive shell boast an excellent out-of-the-box experience with makes other shells feel stone age in comparison + Murex doesn't just aim to be a well thought out language, the interactive shell boasts an excellent out-of-the-box experience which makes other shells feel stone age in comparison Description: |- This section contains miscellaneous documents on using and configuring the shell and Murex's numerous features. diff --git a/gen/root/tour.inc.md b/gen/root/tour.inc.md index a9ab076cc..0cc862c14 100644 --- a/gen/root/tour.inc.md +++ b/gen/root/tour.inc.md @@ -77,8 +77,8 @@ and UNIX over the last 50 years. {{ end }} Murex doesn't just aim to be a well thought out language, the interactive shell -boast an excellent out-of-the-box experience with makes other shells feel stone -age in comparison. +boasts an excellent out-of-the-box experience which makes other shells feel +stone age in comparison. If you want to learn more about the interactive shell then there is a dedicated document detailing {{ link "Murex's REPL features" "interactive-shell" }}. diff --git a/version.svg b/version.svg index e020c2383..d2f7c4e43 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4172Version6.3.4172 +Version: 6.3.4173Version6.3.4173 From d5c09befade29610ce402a5bd673f948d6e8511f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Sun, 15 Sep 2024 22:11:01 +0100 Subject: [PATCH 136/142] website: vue index page --- app/app.go | 4 +-- gen/vuepress/commands_generated.json | 9 +++++++ gen/vuepress/parser_generated.json | 8 ++++++ utils/docgen/api/functions.go | 37 +++++++++++++++++++--------- utils/docgen/main.go | 2 +- version.svg | 2 +- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/app/app.go b/app/app.go index 2fc287c6b..6e9613caa 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4173 + Revision = 4176 Branch = "develop" - BuildDate = "2024-09-15 19:17:35" + BuildDate = "2024-09-15 22:16:10" ) // Copyright is the copyright owner string diff --git a/gen/vuepress/commands_generated.json b/gen/vuepress/commands_generated.json index 381165622..1a10cb638 100644 --- a/gen/vuepress/commands_generated.json +++ b/gen/vuepress/commands_generated.json @@ -1,4 +1,10 @@ [ + { + "icon": "file-lines", + "index": true, + "link": "/commands/", + "text": "Builtin Commands" + }, { "children": [ { @@ -875,14 +881,17 @@ "text": "Help and Hint Tools" }, { + "icon": "file-lines", "link": "commands/die.html", "text": "die" }, { + "icon": "file-lines", "link": "commands/let.html", "text": "let" }, { + "icon": "file-lines", "link": "commands/murex-parser.html", "text": "murex-parser" } diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json index 949784d21..ee556df97 100644 --- a/gen/vuepress/parser_generated.json +++ b/gen/vuepress/parser_generated.json @@ -1,4 +1,10 @@ [ + { + "icon": "file-lines", + "index": true, + "link": "/parser/", + "text": "Parser Reference" + }, { "children": [ { @@ -258,10 +264,12 @@ "text": "Pipes" }, { + "icon": "file-lines", "link": "parser/equ.html", "text": "= (arithmetic evaluation)" }, { + "icon": "file-lines", "link": "parser/pipe-err.html", "text": "? stderr Pipe" } diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index 782740e32..c577d526a 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -337,24 +337,39 @@ func funcFunctions(s string) string { * VuePress * ************/ +const ( + _VUE_TEXT = "text" + _VUE_LINK = "link" + _VUE_ICON = "icon" + _VUE_INDEX = "index" + _VUE_CHILDREN = "children" + _VUE_COLLAPSIBLE = "collapsible" +) + // Takes: string, category ID // Returns: JSON string func funcVuePressMenu(catID string) string { - //var menu vuePressMenuItem cat := Config.Categories.ByID(catID) if cat == nil { panic(fmt.Sprintf("cannot find category with ID '%s'", catID)) } - menu := vuePressSubMenu(cat) + index := map[string]any{ + _VUE_TEXT: vueTitle(cat.Title), + _VUE_ICON: "file-lines", + _VUE_INDEX: true, + _VUE_LINK: fmt.Sprintf("/%s/", cat.ID), + } + menu := append([]map[string]any{index}, vuePressSubMenu(cat)...) for i := range Documents { if Documents[i].CategoryID != cat.ID || len(Documents[i].SubCategoryIDs) > 0 { continue } menu = append(menu, map[string]any{ - "text": vueTitle(Documents[i].Title), - "link": Documents[i].Hierarchy() + ".html", + _VUE_TEXT: vueTitle(Documents[i].Title), + _VUE_LINK: Documents[i].Hierarchy() + ".html", + _VUE_ICON: "file-lines", //cat.VueIcon, }) } @@ -373,17 +388,17 @@ func vuePressSubMenu(cat *category) []map[string]any { for i := range Documents { if Documents[i].IsInSubCategory(sub.ID) { subMenu = append(subMenu, map[string]any{ - "text": vueTitle(Documents[i].Title), - "link": Documents[i].Hierarchy() + ".html", - "icon": "file-lines", + _VUE_TEXT: vueTitle(Documents[i].Title), + _VUE_LINK: Documents[i].Hierarchy() + ".html", + _VUE_ICON: "file-lines", }) } } menu = append(menu, map[string]any{ - "text": vueTitle(sub.Title), - "icon": "folder-closed", //"angles-right", //sub.VueIcon, - "children": subMenu, - "collapsible": true, + _VUE_TEXT: vueTitle(sub.Title), + _VUE_ICON: "folder-closed", //"angles-right", //sub.VueIcon, + _VUE_CHILDREN: subMenu, + _VUE_COLLAPSIBLE: true, }) } diff --git a/utils/docgen/main.go b/utils/docgen/main.go index 0b506978e..80dad809f 100644 --- a/utils/docgen/main.go +++ b/utils/docgen/main.go @@ -11,7 +11,7 @@ import ( const ( // Version is the release ID of docgen - Version = "4.1.0" + Version = "4.1.1" // Copyright is the copyright owner string Copyright = "(c) 2018-2024 Laurence Morgan" diff --git a/version.svg b/version.svg index d2f7c4e43..7d0b1069a 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4173Version6.3.4173 +Version: 6.3.4176Version6.3.4176 From ffbe8b9ef8938ea1b30171f0a8e7b695c92991a9 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 17 Sep 2024 15:56:49 +0100 Subject: [PATCH 137/142] #873 POSIX variables + docs --- app/app.go | 4 +- docs/parser/tilde.md | 23 +++- docs/variables/argv.md | 12 +- docs/variables/columns.md | 20 +++- docs/variables/event_return.md | 10 ++ docs/variables/home.md | 64 +++++++++++ docs/variables/hostname.md | 14 ++- docs/variables/lines.md | 90 +++++++++++++++ docs/variables/logname.md | 116 ++++++++++++++++++++ docs/variables/meta-values.md | 10 ++ docs/variables/murex_argv.md | 10 ++ docs/variables/murex_exe.md | 10 ++ docs/variables/numeric.md | 12 +- docs/variables/oldpwd.md | 89 +++++++++++++++ docs/variables/params.md | 12 +- docs/variables/pwd.md | 10 ++ docs/variables/pwdhist.md | 14 ++- docs/variables/random.md | 64 +++++++++++ docs/variables/self.md | 12 +- docs/variables/shell.md | 12 +- docs/variables/tmpdir.md | 61 ++++++++++ docs/variables/user.md | 61 ++++++++++ gen/docgen.yaml | 8 +- gen/includes/autogenerated.variables.inc.md | 12 +- gen/parser/logical_ops_doc.yaml | 6 +- gen/parser/variables_doc.yaml | 24 +++- gen/variables/ARGV_doc.yaml | 2 +- gen/variables/COLUMNS_doc.yaml | 5 +- gen/variables/HOME_doc.yaml | 24 ++++ gen/variables/HOSTNAME_doc.yaml | 2 - gen/variables/LINES_doc.yaml | 42 +++++++ gen/variables/LOGNAME_doc.yaml | 72 ++++++++++++ gen/variables/OLDPWD_doc.yaml | 45 ++++++++ gen/variables/PARAMS_doc.yaml | 2 +- gen/variables/PWDHIST_doc.yaml | 2 +- gen/variables/RANDOM_doc.yaml | 24 ++++ gen/variables/SELF_doc.yaml | 2 +- gen/variables/SHELL_doc.yaml | 2 +- gen/variables/TMPDIR_doc.yaml | 21 ++++ gen/variables/USER_doc.yaml | 19 ++++ gen/variables/numeric_doc.yaml | 2 +- gen/vuepress/parser_generated.json | 21 +--- version.svg | 2 +- 43 files changed, 1006 insertions(+), 63 deletions(-) create mode 100644 docs/variables/home.md create mode 100644 docs/variables/lines.md create mode 100644 docs/variables/logname.md create mode 100644 docs/variables/oldpwd.md create mode 100644 docs/variables/random.md create mode 100644 docs/variables/tmpdir.md create mode 100644 docs/variables/user.md create mode 100644 gen/variables/HOME_doc.yaml create mode 100644 gen/variables/LINES_doc.yaml create mode 100644 gen/variables/LOGNAME_doc.yaml create mode 100644 gen/variables/OLDPWD_doc.yaml create mode 100644 gen/variables/RANDOM_doc.yaml create mode 100644 gen/variables/TMPDIR_doc.yaml create mode 100644 gen/variables/USER_doc.yaml diff --git a/app/app.go b/app/app.go index 6e9613caa..eda305757 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4176 + Revision = 4182 Branch = "develop" - BuildDate = "2024-09-15 22:16:10" + BuildDate = "2024-09-17 15:56:52" ) // Copyright is the copyright owner string diff --git a/docs/parser/tilde.md b/docs/parser/tilde.md index 1a3b8e756..abbf16e96 100644 --- a/docs/parser/tilde.md +++ b/docs/parser/tilde.md @@ -4,7 +4,14 @@ ## Description -The tilde token is used as a lazy reference to the users home directory. +The tilde token is used as a convenience shortcut to users home directory. + +By itself, `~` will point to the current users home directory. + +If a username follows, eg `~joe.bloggs`, then the home directory for that user +is returned irrespective of who is presently logged in. Characters supported by +tilde usernames are alpha upper and lower case, numeric, underscore, full stop +(period), and hyphens. @@ -41,6 +48,8 @@ Assuming "foobar" isn't a valid local user: ## Detail +### Infixing + Tilde can be expanded inside double quotes, brace quotes as well as used naked. But it cannot be expanded inside single quotes. @@ -58,6 +67,16 @@ But it cannot be expanded inside single quotes. /home/bob ``` +### Error Handling + +If a username is supplied that that user doesn't exist, the tilde will raise an +error. For example: + +``` +» ~joe.bloggs +Error in `expr` (0,1): cannot expand variable `~joe.bloggs`: user: unknown user joe.bloggs +``` + ## See Also * [Create JSON Array (`ja`)](../commands/ja.md): @@ -78,6 +97,8 @@ But it cannot be expanded inside single quotes. Write a string to the stdout without new line (deprecated) * [`@Array` Sigil](../parser/array.md): Expand values as an array +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`string` (stringing)](../types/str.md): string (primitive) diff --git a/docs/variables/argv.md b/docs/variables/argv.md index fcd9383b8..48c114342 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -44,16 +44,24 @@ deprecated and may be removed from future releases. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -64,6 +72,8 @@ deprecated and may be removed from future releases. Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -91,7 +101,7 @@ deprecated and may be removed from future releases. Array of the parameters within a given scope * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`string` (stringing)](../types/str.md): +* [`str` (string)](../types/str.md): string (primitive)
      diff --git a/docs/variables/columns.md b/docs/variables/columns.md index 1642493a0..196e3c10c 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -20,16 +20,24 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -40,19 +48,19 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also -* [Define Variable (`set`)](../commands/set.md): - Define a variable (typically local) and set it's value * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`str` (string)](../types/str.md): - string (primitive) -* [`string` (stringing)](../types/str.md): - string (primitive) +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`int`](../types/int.md): + Whole number (primitive)
      diff --git a/docs/variables/event_return.md b/docs/variables/event_return.md index 933fdcfe1..fff53da07 100644 --- a/docs/variables/event_return.md +++ b/docs/variables/event_return.md @@ -31,16 +31,24 @@ the respective event document for details on using this variable. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -51,6 +59,8 @@ the respective event document for details on using this variable. Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also diff --git a/docs/variables/home.md b/docs/variables/home.md new file mode 100644 index 000000000..c0012f480 --- /dev/null +++ b/docs/variables/home.md @@ -0,0 +1,64 @@ +# `HOME` (path) + +> Return the home directory for the current session user + +## Description + +`$HOME` returns the home directory for the current session user. + +This variable duplicates functionality from `~` and thus is only provided for +POSIX support. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`path`](../types/path.md): + Structured object for working with file and directory paths +* [`~` Home Sigil](../parser/tilde.md): + Home directory path variable + +
      + +This document was generated from [gen/variables/HOME_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/HOME_doc.yaml). \ No newline at end of file diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index ee51079e7..64d496309 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -17,16 +17,24 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -37,17 +45,15 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also -* [Define Variable (`set`)](../commands/set.md): - Define a variable (typically local) and set it's value * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex * [`str` (string)](../types/str.md): string (primitive) -* [`string` (stringing)](../types/str.md): - string (primitive)
      diff --git a/docs/variables/lines.md b/docs/variables/lines.md new file mode 100644 index 000000000..108ad1a78 --- /dev/null +++ b/docs/variables/lines.md @@ -0,0 +1,90 @@ +# `COLUMNS` (int) + +> Character height of terminal + +## Description + +`LINES` returns the cell height of the terminal. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Detail + +The Murex controlling terminal is assumed to be the terminal. If Stdout cannot +be successfully queried for its dimensions, for example Murex is a piped rather +than controlling a TTY, then `$LINES` will generate an error: + +``` +» exec $MUREX_EXE -c 'out $LINES' -> cat +Error in `out` ( 1,1): + Command: out $LINES + Error: cannot assign value to $LINES: inappropriate ioctl for device + > Expression: out $LINES + > : ^ + > Character : 9 +Error in `/Users/laurencemorgan/dev/go/src/github.com/lmorg/murex/murex` (0,1): exit status 1 +``` + +This error can be caught via `||`, `try` et al. + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Execute External Command (`exec`)](../commands/exec.md): + Runs an executable +* [Interactive Shell](../user-guide/interactive-shell.md): + What's different about Murex's interactive shell? +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [Try Block (`try`)](../commands/try.md): + Handles non-zero exits inside a block of code +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`int`](../types/int.md): + Whole number (primitive) +* [`||` Or Logical Operator](../parser/logical-or.md): + Continues next operation only if previous operation fails + +
      + +This document was generated from [gen/variables/LINES_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/LINES_doc.yaml). \ No newline at end of file diff --git a/docs/variables/logname.md b/docs/variables/logname.md new file mode 100644 index 000000000..87b84ac29 --- /dev/null +++ b/docs/variables/logname.md @@ -0,0 +1,116 @@ +# `LOGNAME` (str) + +> Username for the current session (historic) + +## Description + +`LOGNAME` returns the user name of the current Murex session. It's behaviour is +identical to `USER`. + +> `LOGNAME` is a historical relic. Please use `USER` in your scripts instead. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Detail + +### USER vs LOGNAME + +The `$USER` and `$LOGNAME` environment variables serve similar but slightly +different purposes. Plus and their distinctions stem from historical and +compatibility reasons. + +1. Historical Context: + + * `$LOGNAME` originates from early AT&T UNIX systems and was intended to + hold the user’s login name, particularly for system utilities that relied + on it. + + It has been part of POSIX since early UNIX specifications, which is why it + is a required variable in POSIX-compliant systems. + + * `$USER` came from BSD UNIX and was commonly used by shells and more user- + focused applications. This variable has been adopted widely in modern + systems like Linux to refer to the current user within shell scripts and + interactive environments. + +2. Functional Difference: + + Both variables typically hold the same value, representing the current + user's login name. However, in certain contexts in POSIX environments, + (such as running `sudo` from Bash), their behavior may differ: + + * `$LOGNAME` is more tightly bound to the user who originally logged in, + + * while `$USER` may be altered during a session. + + **With regards to Murex, both variables call the same underlying function + and thus will always return the same values under all circumstances.** + +3. Why Two Variables?: + + * In POSIX shells like Bash, the existence of both `$LOGNAME` and `$USER` + reflects the integration of features from both AT&T UNIX and BSD UNIX. + Although they usually return the same value, POSIX mandates `$LOGNAME` + for broader system compatibility, especially with utilities that depend + on login information. + + * However with Murex, there isn't any requirement to maintain POSIX + compatibility with AT&T UNIX. What's more, neither of these two variables + are defined as environmental variables. + + The reason Murex retains supports for `$LOGNAME` as a reserved variable is + simply to ensure nobody accidentally uses `$LOGNAME` for any other + purposes (such as logging) and then get confused why other utilities might + break after they've overwritten the contents of `$LOGNAME` + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`USER` (str)](../variables/user.md): + Username for the current session +* [`str` (string)](../types/str.md): + string (primitive) + +
      + +This document was generated from [gen/variables/LOGNAME_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/LOGNAME_doc.yaml). \ No newline at end of file diff --git a/docs/variables/meta-values.md b/docs/variables/meta-values.md index 79040046b..c9943f619 100644 --- a/docs/variables/meta-values.md +++ b/docs/variables/meta-values.md @@ -30,16 +30,24 @@ iteration structure's documentation to check what information is exposed via State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -50,6 +58,8 @@ iteration structure's documentation to check what information is exposed via Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also diff --git a/docs/variables/murex_argv.md b/docs/variables/murex_argv.md index 474d4c543..0468b056e 100644 --- a/docs/variables/murex_argv.md +++ b/docs/variables/murex_argv.md @@ -29,16 +29,24 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -49,6 +57,8 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index 8ceca553b..26bc6a718 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -18,16 +18,24 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -38,6 +46,8 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index f83375973..92dc9da5f 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -37,16 +37,24 @@ then variables `$1` through to `$19` (inclusive) will all be set. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -57,6 +65,8 @@ then variables `$1` through to `$19` (inclusive) will all be set. Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -74,7 +84,7 @@ then variables `$1` through to `$19` (inclusive) will all be set. Array of the command name and parameters within a given scope * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope -* [`string` (stringing)](../types/str.md): +* [`str` (string)](../types/str.md): string (primitive)
      diff --git a/docs/variables/oldpwd.md b/docs/variables/oldpwd.md new file mode 100644 index 000000000..4eb913af9 --- /dev/null +++ b/docs/variables/oldpwd.md @@ -0,0 +1,89 @@ +# `OLDPWD` (path) + +> Return the home directory for the current session user + +## Description + +`OLDPWD` return the previous directory. + +This variable exists to support POSIX, however the idiomatic way to access this +same data is via `$PWDHIST`. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Detail + +### Comparison With PWDHIST + +`PWDHIST` is an array that holds the entire `PWD` history rather than just the +previously accessed path. + +`OLDPWD` reads `PWDHIST`, so if `PWDHIST` is overwritten, this will affect the +value of `OLDPWD` as well. + +### Error Handling + +If a previous directory cannot be determined, then `OLDPWD` will error. For +example: + +``` +» cd $OLDPWD +Error in `cd` (0,1): cannot assign value to $OLDPWD: already at oldest entry in $PWDHIST + > Expression: cd $OLDPWD + > : ^ + > Character : 9 +``` + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`path`](../types/path.md): + Structured object for working with file and directory paths + +
      + +This document was generated from [gen/variables/OLDPWD_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/OLDPWD_doc.yaml). \ No newline at end of file diff --git a/docs/variables/params.md b/docs/variables/params.md index 44f527d91..56fdecd89 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -32,16 +32,24 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -52,6 +60,8 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -79,7 +89,7 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be Array of the command name and parameters within a given scope * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`string` (stringing)](../types/str.md): +* [`str` (string)](../types/str.md): string (primitive)
      diff --git a/docs/variables/pwd.md b/docs/variables/pwd.md index 81ad014b0..6d711c02c 100644 --- a/docs/variables/pwd.md +++ b/docs/variables/pwd.md @@ -16,16 +16,24 @@ It is updated via `cd` however you can overwrite its value manually via `export` State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -36,6 +44,8 @@ It is updated via `cd` however you can overwrite its value manually via `export` Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index c69981a2b..5d56ceaf7 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -29,16 +29,24 @@ It is updated via `cd` however you can overwrite its value manually via `set`. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -49,6 +57,8 @@ It is updated via `cd` however you can overwrite its value manually via `set`. Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -66,14 +76,14 @@ It is updated via `cd` however you can overwrite its value manually via `set`. How scoping works within Murex * [`@Array` Sigil](../parser/array.md): Expand values as an array +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PWD` (path)](../variables/pwd.md): Current working directory * [`json`](../types/json.md): JavaScript Object Notation (JSON) * [`path`](../types/path.md): Structured object for working with file and directory paths -* [`string` (stringing)](../types/str.md): - string (primitive)
      diff --git a/docs/variables/random.md b/docs/variables/random.md new file mode 100644 index 000000000..e61186fc2 --- /dev/null +++ b/docs/variables/random.md @@ -0,0 +1,64 @@ +# `RANDOM` (int) + +> Return a random 32-bit integer (historical) + +## Description + +`$RANDOM` returns a number between 0 and 32767 (inclusive). + +`$RANDOM` was included for POSIX support however the idiomatic way to generate +random tokens in Murex is via the [`rand` builtin](/docs/commands/rand.md). + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Generate Random Sequence (`rand`)](../commands/rand.md): + Random field generator +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`int`](../types/int.md): + Whole number (primitive) + +
      + +This document was generated from [gen/variables/RANDOM_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/RANDOM_doc.yaml). \ No newline at end of file diff --git a/docs/variables/self.md b/docs/variables/self.md index d0c54bff4..7beaa9632 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -88,16 +88,24 @@ terminal (TTY) or a pipe?) State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -108,6 +116,8 @@ terminal (TTY) or a pipe?) Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -125,7 +135,7 @@ terminal (TTY) or a pipe?) How scoping works within Murex * [`json`](../types/json.md): JavaScript Object Notation (JSON) -* [`string` (stringing)](../types/str.md): +* [`str` (string)](../types/str.md): string (primitive)
      diff --git a/docs/variables/shell.md b/docs/variables/shell.md index db951f367..c1742ac04 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -21,16 +21,24 @@ reserved variable, and thus read only, if you require precision and safety. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -41,6 +49,8 @@ reserved variable, and thus read only, if you require precision and safety. Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session ## See Also @@ -48,7 +58,7 @@ reserved variable, and thus read only, if you require precision and safety. Define an environmental variable and set it's value * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell -* [`string` (stringing)](../types/str.md): +* [`str` (string)](../types/str.md): string (primitive)
      diff --git a/docs/variables/tmpdir.md b/docs/variables/tmpdir.md new file mode 100644 index 000000000..d8f876599 --- /dev/null +++ b/docs/variables/tmpdir.md @@ -0,0 +1,61 @@ +# `TMPDIR` (path) + +> Return the temporary directory + +## Description + +`TMPDIR` returns the temporary directory. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`path`](../types/path.md): + Structured object for working with file and directory paths +* [`~` Home Sigil](../parser/tilde.md): + Home directory path variable + +
      + +This document was generated from [gen/variables/TMPDIR_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/TMPDIR_doc.yaml). \ No newline at end of file diff --git a/docs/variables/user.md b/docs/variables/user.md new file mode 100644 index 000000000..de0d8e77d --- /dev/null +++ b/docs/variables/user.md @@ -0,0 +1,61 @@ +# `USER` (str) + +> Username for the current session + +## Description + +`USER` returns the user name of the current Murex session. + +This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. + +## Other Reserved Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session + +## See Also + +* [Reserved Variables](../user-guide/reserved-vars.md): + Special variables reserved by Murex +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`str` (string)](../types/str.md): + string (primitive) + +
      + +This document was generated from [gen/variables/USER_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/variables/USER_doc.yaml). \ No newline at end of file diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 648c9eb24..125638223 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -139,7 +139,7 @@ Categories: DocumentTemplate: gen/commands-md-doc.tmpl - ID: parser - Title: Parser Reference + Title: Operators And Tokens Summary: >- Murex supports both expressions and statements. Thus you have a flexible language that is both highly readable and yet still concise. No other shell offers the best of both these worlds as well as Murex does Description: |- @@ -174,7 +174,7 @@ Categories: VueIcon: angles-right Description: - ID: parser.conditionals - Title: Conditionals + Title: Conditionals & Boolean VueIcon: angles-right Description: - ID: parser.sigils @@ -189,10 +189,6 @@ Categories: Title: Sub-Shells VueIcon: angles-right Description: - - ID: parser.boolean - Title: Boolean Operations - VueIcon: angles-right - Description: - ID: parser.pipes Title: Pipes VueIcon: angles-right diff --git a/gen/includes/autogenerated.variables.inc.md b/gen/includes/autogenerated.variables.inc.md index 06b1859b3..954f2e47f 100644 --- a/gen/includes/autogenerated.variables.inc.md +++ b/gen/includes/autogenerated.variables.inc.md @@ -4,16 +4,24 @@ State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user * [`HOSTNAME` (str)](../variables/hostname.md): Hostname of the current machine +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) * [`MUREX_ARGV` (json)](../variables/murex_argv.md): Array of the command name and parameters passed to the current shell * [`MUREX_EXE` (path)](../variables/murex_exe.md): Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user * [`PARAMS` (json)](../variables/params.md): Array of the parameters within a given scope * [`PWDHIST` (json)](../variables/pwdhist.md): @@ -23,4 +31,6 @@ * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): - Path of current shell \ No newline at end of file + Path of current shell +* [`USER` (str)](../variables/user.md): + Username for the current session \ No newline at end of file diff --git a/gen/parser/logical_ops_doc.yaml b/gen/parser/logical_ops_doc.yaml index ae7413a8c..2429c020a 100644 --- a/gen/parser/logical_ops_doc.yaml +++ b/gen/parser/logical_ops_doc.yaml @@ -2,7 +2,7 @@ Title: >- `&&` And Logical Operator CategoryID: parser - SubCategoryIDs: [ parser.boolean ] + SubCategoryIDs: [ parser.conditional ] Summary: >- Continues next operation if previous operation passes Description: |- @@ -57,7 +57,7 @@ Title: >- `||` Or Logical Operator CategoryID: parser - SubCategoryIDs: [ parser.boolean ] + SubCategoryIDs: [ parser.conditional ] Summary: >- Continues next operation only if previous operation fails Description: |- @@ -107,4 +107,4 @@ - try - trypipe - logical-and - - elvis \ No newline at end of file + - elvis diff --git a/gen/parser/variables_doc.yaml b/gen/parser/variables_doc.yaml index 558c93329..01baad60d 100644 --- a/gen/parser/variables_doc.yaml +++ b/gen/parser/variables_doc.yaml @@ -138,7 +138,14 @@ Summary: >- Home directory path variable Description: |- - The tilde token is used as a lazy reference to the users home directory. + The tilde token is used as a convenience shortcut to users home directory. + + By itself, `~` will point to the current users home directory. + + If a username follows, eg `~joe.bloggs`, then the home directory for that user + is returned irrespective of who is presently logged in. Characters supported by + tilde usernames are alpha upper and lower case, numeric, underscore, full stop + (period), and hyphens. Examples: |- ### Current user @@ -169,6 +176,8 @@ / ``` Detail: |- + ### Infixing + Tilde can be expanded inside double quotes, brace quotes as well as used naked. But it cannot be expanded inside single quotes. @@ -185,6 +194,16 @@ » out %(~) /home/bob ``` + + ### Error Handling + + If a username is supplied that that user doesn't exist, the tilde will raise an + error. For example: + + ``` + » ~joe.bloggs + Error in `expr` (0,1): cannot expand variable `~joe.bloggs`: user: unknown user joe.bloggs + ``` Related: - string - array @@ -195,4 +214,5 @@ - set - ja - brace-quote-func - - reserved-vars \ No newline at end of file + - reserved-vars + - home \ No newline at end of file diff --git a/gen/variables/ARGV_doc.yaml b/gen/variables/ARGV_doc.yaml index c61dc2d2f..9807c8eca 100644 --- a/gen/variables/ARGV_doc.yaml +++ b/gen/variables/ARGV_doc.yaml @@ -41,7 +41,7 @@ Related: - params - json - - string + - str - array - set - function diff --git a/gen/variables/COLUMNS_doc.yaml b/gen/variables/COLUMNS_doc.yaml index 4342165f1..db61f7aa0 100644 --- a/gen/variables/COLUMNS_doc.yaml +++ b/gen/variables/COLUMNS_doc.yaml @@ -17,9 +17,8 @@ - columns - COLUMNS Related: - - str - - set - - string + - int - reserved-vars - interactive-shell + - lines diff --git a/gen/variables/HOME_doc.yaml b/gen/variables/HOME_doc.yaml new file mode 100644 index 000000000..2ed95b5ae --- /dev/null +++ b/gen/variables/HOME_doc.yaml @@ -0,0 +1,24 @@ +- DocumentID: home + Title: >- + `HOME` (path) + CategoryID: variables + SubCategoryIDs: [ vars.posix ] + Summary: >- + Return the home directory for the current session user + Description: |- + `$HOME` returns the home directory for the current session user. + + This variable duplicates functionality from `~` and thus is only provided for + POSIX support. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: + Synonyms: + - home + - HOME + Related: + - path + - reserved-vars + - tilde + + diff --git a/gen/variables/HOSTNAME_doc.yaml b/gen/variables/HOSTNAME_doc.yaml index e55f03fb9..ddcacc885 100644 --- a/gen/variables/HOSTNAME_doc.yaml +++ b/gen/variables/HOSTNAME_doc.yaml @@ -15,7 +15,5 @@ - HOSTNAME Related: - str - - set - - string - reserved-vars diff --git a/gen/variables/LINES_doc.yaml b/gen/variables/LINES_doc.yaml new file mode 100644 index 000000000..0c97c80a1 --- /dev/null +++ b/gen/variables/LINES_doc.yaml @@ -0,0 +1,42 @@ +- DocumentID: lines + Title: >- + `COLUMNS` (int) + CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.posix ] + Summary: >- + Character height of terminal + Description: |- + `LINES` returns the cell height of the terminal. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: |- + The Murex controlling terminal is assumed to be the terminal. If Stdout cannot + be successfully queried for its dimensions, for example Murex is a piped rather + than controlling a TTY, then `$LINES` will generate an error: + + ``` + » exec $MUREX_EXE -c 'out $LINES' -> cat + Error in `out` ( 1,1): + Command: out $LINES + Error: cannot assign value to $LINES: inappropriate ioctl for device + > Expression: out $LINES + > : ^ + > Character : 9 + Error in `/Users/laurencemorgan/dev/go/src/github.com/lmorg/murex/murex` (0,1): exit status 1 + ``` + + This error can be caught via `||`, `try` et al. + Synonyms: + - lines + - LINES + Related: + - int + - reserved-vars + - interactive-shell + - columns + - exec + - murex_exe + - logical-or + - try + + diff --git a/gen/variables/LOGNAME_doc.yaml b/gen/variables/LOGNAME_doc.yaml new file mode 100644 index 000000000..63957bebb --- /dev/null +++ b/gen/variables/LOGNAME_doc.yaml @@ -0,0 +1,72 @@ +- DocumentID: logname + Title: >- + `LOGNAME` (str) + CategoryID: variables + SubCategoryIDs: [ vars.posix ] + Summary: >- + Username for the current session (historic) + Description: |- + `LOGNAME` returns the user name of the current Murex session. It's behaviour is + identical to `USER`. + + > `LOGNAME` is a historical relic. Please use `USER` in your scripts instead. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: |- + ### USER vs LOGNAME + + The `$USER` and `$LOGNAME` environment variables serve similar but slightly + different purposes. Plus and their distinctions stem from historical and + compatibility reasons. + + 1. Historical Context: + + * `$LOGNAME` originates from early AT&T UNIX systems and was intended to + hold the user’s login name, particularly for system utilities that relied + on it. + + It has been part of POSIX since early UNIX specifications, which is why it + is a required variable in POSIX-compliant systems. + + * `$USER` came from BSD UNIX and was commonly used by shells and more user- + focused applications. This variable has been adopted widely in modern + systems like Linux to refer to the current user within shell scripts and + interactive environments. + + 2. Functional Difference: + + Both variables typically hold the same value, representing the current + user's login name. However, in certain contexts in POSIX environments, + (such as running `sudo` from Bash), their behavior may differ: + + * `$LOGNAME` is more tightly bound to the user who originally logged in, + + * while `$USER` may be altered during a session. + + **With regards to Murex, both variables call the same underlying function + and thus will always return the same values under all circumstances.** + + 3. Why Two Variables?: + + * In POSIX shells like Bash, the existence of both `$LOGNAME` and `$USER` + reflects the integration of features from both AT&T UNIX and BSD UNIX. + Although they usually return the same value, POSIX mandates `$LOGNAME` + for broader system compatibility, especially with utilities that depend + on login information. + + * However with Murex, there isn't any requirement to maintain POSIX + compatibility with AT&T UNIX. What's more, neither of these two variables + are defined as environmental variables. + + The reason Murex retains supports for `$LOGNAME` as a reserved variable is + simply to ensure nobody accidentally uses `$LOGNAME` for any other + purposes (such as logging) and then get confused why other utilities might + break after they've overwritten the contents of `$LOGNAME` + Synonyms: + - logname + - LOGNAME + Related: + - str + - reserved-vars + - user + diff --git a/gen/variables/OLDPWD_doc.yaml b/gen/variables/OLDPWD_doc.yaml new file mode 100644 index 000000000..d2fab7299 --- /dev/null +++ b/gen/variables/OLDPWD_doc.yaml @@ -0,0 +1,45 @@ +- DocumentID: oldpwd + Title: >- + `OLDPWD` (path) + CategoryID: variables + SubCategoryIDs: [ vars.posix ] + Summary: >- + Return the home directory for the current session user + Description: |- + `OLDPWD` return the previous directory. + + This variable exists to support POSIX, however the idiomatic way to access this + same data is via `$PWDHIST`. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: |- + ### Comparison With PWDHIST + + `PWDHIST` is an array that holds the entire `PWD` history rather than just the + previously accessed path. + + `OLDPWD` reads `PWDHIST`, so if `PWDHIST` is overwritten, this will affect the + value of `OLDPWD` as well. + + ### Error Handling + + If a previous directory cannot be determined, then `OLDPWD` will error. For + example: + + ``` + » cd $OLDPWD + Error in `cd` (0,1): cannot assign value to $OLDPWD: already at oldest entry in $PWDHIST + > Expression: cd $OLDPWD + > : ^ + > Character : 9 + ``` + Synonyms: + - oldpwd + - OLDPWD + Related: + - path + - reserved-vars + - pwd + - pwdhist + + diff --git a/gen/variables/PARAMS_doc.yaml b/gen/variables/PARAMS_doc.yaml index 228faf8a5..cb0266a94 100644 --- a/gen/variables/PARAMS_doc.yaml +++ b/gen/variables/PARAMS_doc.yaml @@ -30,7 +30,7 @@ - argv - set - json - - string + - str - array - function - private diff --git a/gen/variables/PWDHIST_doc.yaml b/gen/variables/PWDHIST_doc.yaml index 0034a6102..5f4674e42 100644 --- a/gen/variables/PWDHIST_doc.yaml +++ b/gen/variables/PWDHIST_doc.yaml @@ -27,7 +27,6 @@ - path - json - pwd - - string - array - set - cd @@ -35,3 +34,4 @@ - pipeline - modules - reserved-vars + - oldpwd diff --git a/gen/variables/RANDOM_doc.yaml b/gen/variables/RANDOM_doc.yaml new file mode 100644 index 000000000..533f575a0 --- /dev/null +++ b/gen/variables/RANDOM_doc.yaml @@ -0,0 +1,24 @@ +- DocumentID: random + Title: >- + `RANDOM` (int) + CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.posix ] + Summary: >- + Return a random 32-bit integer (historical) + Description: |- + `$RANDOM` returns a number between 0 and 32767 (inclusive). + + `$RANDOM` was included for POSIX support however the idiomatic way to generate + random tokens in Murex is via the {{link "`rand` builtin" "rand"}}. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: + Synonyms: + - tmpdir + - TMPDIR + Related: + - int + - reserved-vars + - rand + + diff --git a/gen/variables/SELF_doc.yaml b/gen/variables/SELF_doc.yaml index 9177d90ff..3a045192f 100644 --- a/gen/variables/SELF_doc.yaml +++ b/gen/variables/SELF_doc.yaml @@ -83,7 +83,7 @@ - SELF Related: - json - - string + - str - function - scoping - pipeline diff --git a/gen/variables/SHELL_doc.yaml b/gen/variables/SHELL_doc.yaml index cc8da84a4..ae2c0e72a 100644 --- a/gen/variables/SHELL_doc.yaml +++ b/gen/variables/SHELL_doc.yaml @@ -20,6 +20,6 @@ - SHELL Related: - murex_exe - - string + - str - export diff --git a/gen/variables/TMPDIR_doc.yaml b/gen/variables/TMPDIR_doc.yaml new file mode 100644 index 000000000..8eed952fa --- /dev/null +++ b/gen/variables/TMPDIR_doc.yaml @@ -0,0 +1,21 @@ +- DocumentID: tmpdir + Title: >- + `TMPDIR` (path) + CategoryID: variables + SubCategoryIDs: [ vars.posix ] + Summary: >- + Return the temporary directory + Description: |- + `TMPDIR` returns the temporary directory. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Detail: + Synonyms: + - tmpdir + - TMPDIR + Related: + - path + - reserved-vars + - tilde + + diff --git a/gen/variables/USER_doc.yaml b/gen/variables/USER_doc.yaml new file mode 100644 index 000000000..dd9251f6e --- /dev/null +++ b/gen/variables/USER_doc.yaml @@ -0,0 +1,19 @@ +- DocumentID: user + Title: >- + `USER` (str) + CategoryID: variables + SubCategoryIDs: [ vars.reserved, vars.posix ] + Summary: >- + Username for the current session + Description: |- + `USER` returns the user name of the current Murex session. + + {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} + Synonyms: + - user + - USER + Related: + - str + - reserved-vars + - logname + diff --git a/gen/variables/numeric_doc.yaml b/gen/variables/numeric_doc.yaml index f56d101bf..c2eaf9c21 100644 --- a/gen/variables/numeric_doc.yaml +++ b/gen/variables/numeric_doc.yaml @@ -31,7 +31,7 @@ - argv - params - set - - string + - str - function - private - autocomplete diff --git a/gen/vuepress/parser_generated.json b/gen/vuepress/parser_generated.json index ee556df97..7ce170ca6 100644 --- a/gen/vuepress/parser_generated.json +++ b/gen/vuepress/parser_generated.json @@ -3,7 +3,7 @@ "icon": "file-lines", "index": true, "link": "/parser/", - "text": "Parser Reference" + "text": "Operators And Tokens" }, { "children": [ @@ -116,7 +116,7 @@ ], "collapsible": true, "icon": "folder-closed", - "text": "Conditionals" + "text": "Conditionals \u0026 Boolean" }, { "children": [ @@ -199,23 +199,6 @@ "icon": "folder-closed", "text": "Sub-Shells" }, - { - "children": [ - { - "icon": "file-lines", - "link": "parser/logical-and.html", - "text": "\u0026\u0026 And Logical Operator" - }, - { - "icon": "file-lines", - "link": "parser/logical-or.html", - "text": "|| Or Logical Operator" - } - ], - "collapsible": true, - "icon": "folder-closed", - "text": "Boolean Operations" - }, { "children": [ { diff --git a/version.svg b/version.svg index 7d0b1069a..392ec9335 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4176Version6.3.4176 +Version: 6.3.4182Version6.3.4182 From f6e6a25f4df04710ff8ad01412d9db54495958a9 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 17 Sep 2024 15:57:34 +0100 Subject: [PATCH 138/142] #874 trim whitespace when converting strings to numbers --- app/app.go | 4 +- builtins/docs/summaries.go | 21 ++ docs/variables/argv.md | 8 +- docs/variables/columns.md | 8 +- docs/variables/event_return.md | 8 +- docs/variables/home.md | 8 +- docs/variables/hostname.md | 8 +- docs/variables/lines.md | 8 +- docs/variables/logname.md | 8 +- docs/variables/meta-values.md | 8 +- docs/variables/murex_argv.md | 8 +- docs/variables/murex_exe.md | 8 +- docs/variables/numeric.md | 8 +- docs/variables/oldpwd.md | 8 +- docs/variables/params.md | 8 +- docs/variables/pwd.md | 8 +- docs/variables/pwdhist.md | 8 +- docs/variables/random.md | 8 +- docs/variables/self.md | 8 +- docs/variables/shell.md | 8 +- docs/variables/tmpdir.md | 8 +- docs/variables/user.md | 8 +- gen/includes/autogenerated.variables.inc.md | 8 +- gen/variables/RANDOM_doc.yaml | 4 +- lang/expressions/parse_vars.go | 2 +- lang/types/convert.go | 36 ++- ...oolean_test.go => convert_boolean_test.go} | 0 ...lock_test.go => convert_codeblock_test.go} | 0 ...g_test.go => convert_float2string_test.go} | 0 ...st_float_test.go => convert_float_test.go} | 0 ...eneric_test.go => convert_generic_test.go} | 0 lang/types/flatten.go | 34 +++ lang/variables.go | 206 ++++++++++++------ lang/variables_module.go | 2 +- lang/variables_reserved.go | 57 ++++- lang/variables_reserved_test.go | 46 +++- version.svg | 2 +- 37 files changed, 457 insertions(+), 125 deletions(-) rename lang/types/{cast_boolean_test.go => convert_boolean_test.go} (100%) rename lang/types/{cast_codeblock_test.go => convert_codeblock_test.go} (100%) rename lang/types/{cast_float2string_test.go => convert_float2string_test.go} (100%) rename lang/types/{cast_float_test.go => convert_float_test.go} (100%) rename lang/types/{cast_generic_test.go => convert_generic_test.go} (100%) create mode 100644 lang/types/flatten.go diff --git a/app/app.go b/app/app.go index eda305757..d4143e685 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4182 + Revision = 4189 Branch = "develop" - BuildDate = "2024-09-17 15:56:52" + BuildDate = "2024-09-17 21:23:36" ) // Copyright is the copyright owner string diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 5c8cd8cd4..b578c805c 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -333,15 +333,22 @@ func init() { "variables/meta-values": "State information for iteration blocks", "variables/argv": "Array of the command name and parameters within a given scope", "variables/columns": "Character width of terminal", + "variables/lines": "Character height of terminal", "variables/event_return": "Return values for events", + "variables/home": "Return the home directory for the current session user", "variables/hostname": "Hostname of the current machine", + "variables/logname": "Username for the current session (historic)", "variables/murex_argv": "Array of the command name and parameters passed to the current shell", "variables/murex_exe": "Absolute path to running shell", + "variables/oldpwd": "Return the home directory for the current session user", "variables/params": "Array of the parameters within a given scope", "variables/pwdhist": "History of each change to the sessions working directory", "variables/pwd": "Current working directory", + "variables/random": "Return a random 32-bit integer (historical)", "variables/self": "Meta information about the running scope.", "variables/shell": "Path of current shell", + "variables/tmpdir": "Return the temporary directory", + "variables/user": "Username for the current session", "apis/Marshal": "Converts structured memory into a structured file format (eg for stdio)", "apis/ReadArray": "Read from a data type one array element at a time", "apis/ReadArrayWithType": "Read from a data type one array element at a time and return the elements contents and data type", @@ -942,25 +949,39 @@ func init() { "variables/ARGS": "variables/argv", "variables/columns": "variables/columns", "variables/COLUMNS": "variables/columns", + "variables/lines": "variables/lines", + "variables/LINES": "variables/lines", "variables/event_return": "variables/event_return", "variables/EVENT_RETURN": "variables/event_return", + "variables/home": "variables/home", + "variables/HOME": "variables/home", "variables/hostname": "variables/hostname", "variables/HOSTNAME": "variables/hostname", + "variables/logname": "variables/logname", + "variables/LOGNAME": "variables/logname", "variables/murex_argv": "variables/murex_argv", "variables/MUREX_ARGV": "variables/murex_argv", "variables/MUREX_ARGS": "variables/murex_argv", "variables/murex_exe": "variables/murex_exe", "variables/MUREX_EXE": "variables/murex_exe", + "variables/oldpwd": "variables/oldpwd", + "variables/OLDPWD": "variables/oldpwd", "variables/params": "variables/params", "variables/PARAMS": "variables/params", "variables/pwdhist": "variables/pwdhist", "variables/PWDHIST": "variables/pwdhist", "variables/pwd": "variables/pwd", "variables/PWD": "variables/pwd", + "variables/random": "variables/random", + "variables/RANDOM": "variables/random", "variables/self": "variables/self", "variables/SELF": "variables/self", "variables/shell": "variables/shell", "variables/SHELL": "variables/shell", + "variables/tmpdir": "variables/tmpdir", + "variables/TMPDIR": "variables/tmpdir", + "variables/user": "variables/user", + "variables/USER": "variables/user", "apis/Marshal": "apis/Marshal", "apis/ReadArray": "apis/ReadArray", "apis/ReadArrayWithType": "apis/ReadArrayWithType", diff --git a/docs/variables/argv.md b/docs/variables/argv.md index 48c114342..2b0ee0c45 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -44,10 +44,10 @@ deprecated and may be removed from future releases. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -68,10 +68,14 @@ deprecated and may be removed from future releases. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/columns.md b/docs/variables/columns.md index 196e3c10c..b35a8ee9e 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -20,10 +20,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -44,10 +44,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/event_return.md b/docs/variables/event_return.md index fff53da07..9f2c3f0c7 100644 --- a/docs/variables/event_return.md +++ b/docs/variables/event_return.md @@ -31,10 +31,10 @@ the respective event document for details on using this variable. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -55,10 +55,14 @@ the respective event document for details on using this variable. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/home.md b/docs/variables/home.md index c0012f480..ca68eb558 100644 --- a/docs/variables/home.md +++ b/docs/variables/home.md @@ -19,10 +19,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -43,10 +43,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index 64d496309..f7503c62e 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -17,10 +17,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -41,10 +41,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/lines.md b/docs/variables/lines.md index 108ad1a78..a29f336b4 100644 --- a/docs/variables/lines.md +++ b/docs/variables/lines.md @@ -35,10 +35,10 @@ This error can be caught via `||`, `try` et al. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -59,10 +59,14 @@ This error can be caught via `||`, `try` et al. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/logname.md b/docs/variables/logname.md index 87b84ac29..8c8826561 100644 --- a/docs/variables/logname.md +++ b/docs/variables/logname.md @@ -71,10 +71,10 @@ compatibility reasons. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -95,10 +95,14 @@ compatibility reasons. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/meta-values.md b/docs/variables/meta-values.md index c9943f619..9e55e9dae 100644 --- a/docs/variables/meta-values.md +++ b/docs/variables/meta-values.md @@ -30,10 +30,10 @@ iteration structure's documentation to check what information is exposed via State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -54,10 +54,14 @@ iteration structure's documentation to check what information is exposed via History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/murex_argv.md b/docs/variables/murex_argv.md index 0468b056e..96d74a373 100644 --- a/docs/variables/murex_argv.md +++ b/docs/variables/murex_argv.md @@ -29,10 +29,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -53,10 +53,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index 26bc6a718..be9d7b166 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -18,10 +18,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -42,10 +42,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index 92dc9da5f..0e179b990 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -37,10 +37,10 @@ then variables `$1` through to `$19` (inclusive) will all be set. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -61,10 +61,14 @@ then variables `$1` through to `$19` (inclusive) will all be set. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/oldpwd.md b/docs/variables/oldpwd.md index 4eb913af9..4d04f2268 100644 --- a/docs/variables/oldpwd.md +++ b/docs/variables/oldpwd.md @@ -42,10 +42,10 @@ Error in `cd` (0,1): cannot assign value to $OLDPWD: already at oldest entry in State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -66,10 +66,14 @@ Error in `cd` (0,1): cannot assign value to $OLDPWD: already at oldest entry in History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/params.md b/docs/variables/params.md index 56fdecd89..ff109cf17 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -32,10 +32,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -56,10 +56,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/pwd.md b/docs/variables/pwd.md index 6d711c02c..66240e077 100644 --- a/docs/variables/pwd.md +++ b/docs/variables/pwd.md @@ -16,10 +16,10 @@ It is updated via `cd` however you can overwrite its value manually via `export` State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -40,10 +40,14 @@ It is updated via `cd` however you can overwrite its value manually via `export` History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index 5d56ceaf7..c51fabac1 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -29,10 +29,10 @@ It is updated via `cd` however you can overwrite its value manually via `set`. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -53,10 +53,14 @@ It is updated via `cd` however you can overwrite its value manually via `set`. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/random.md b/docs/variables/random.md index e61186fc2..d8b95ee9c 100644 --- a/docs/variables/random.md +++ b/docs/variables/random.md @@ -19,10 +19,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -43,10 +43,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/self.md b/docs/variables/self.md index 7beaa9632..156ca47e1 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -88,10 +88,10 @@ terminal (TTY) or a pipe?) State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -112,10 +112,14 @@ terminal (TTY) or a pipe?) History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/shell.md b/docs/variables/shell.md index c1742ac04..5748a3f33 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -21,10 +21,10 @@ reserved variable, and thus read only, if you require precision and safety. State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -45,10 +45,14 @@ reserved variable, and thus read only, if you require precision and safety. History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/tmpdir.md b/docs/variables/tmpdir.md index d8f876599..177fe97a6 100644 --- a/docs/variables/tmpdir.md +++ b/docs/variables/tmpdir.md @@ -16,10 +16,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -40,10 +40,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/docs/variables/user.md b/docs/variables/user.md index de0d8e77d..fe879a796 100644 --- a/docs/variables/user.md +++ b/docs/variables/user.md @@ -16,10 +16,10 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -40,10 +40,14 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session diff --git a/gen/includes/autogenerated.variables.inc.md b/gen/includes/autogenerated.variables.inc.md index 954f2e47f..365d97794 100644 --- a/gen/includes/autogenerated.variables.inc.md +++ b/gen/includes/autogenerated.variables.inc.md @@ -4,10 +4,10 @@ State information for iteration blocks * [`ARGV` (json)](../variables/argv.md): Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal * [`COLUMNS` (int)](../variables/columns.md): Character width of terminal +* [`COLUMNS` (int)](../variables/lines.md): + Character height of terminal * [`EVENT_RETURN` (json)](../variables/event_return.md): Return values for events * [`HOME` (path)](../variables/home.md): @@ -28,9 +28,13 @@ History of each change to the sessions working directory * [`PWD` (path)](../variables/pwd.md): Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) * [`SELF` (json)](../variables/self.md): Meta information about the running scope. * [`SHELL` (str)](../variables/shell.md): Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory * [`USER` (str)](../variables/user.md): Username for the current session \ No newline at end of file diff --git a/gen/variables/RANDOM_doc.yaml b/gen/variables/RANDOM_doc.yaml index 533f575a0..bfc390f6c 100644 --- a/gen/variables/RANDOM_doc.yaml +++ b/gen/variables/RANDOM_doc.yaml @@ -14,8 +14,8 @@ {{ include "gen/includes/this-is-a-reserved-var.inc.md" }} Detail: Synonyms: - - tmpdir - - TMPDIR + - random + - RANDOM Related: - int - reserved-vars diff --git a/lang/expressions/parse_vars.go b/lang/expressions/parse_vars.go index a4565291d..360395259 100644 --- a/lang/expressions/parse_vars.go +++ b/lang/expressions/parse_vars.go @@ -261,7 +261,7 @@ endRange: } func isUserNameChar(r rune) bool { - return isBareChar(r) || r == '.' || r == '-' + return isBareChar(r) || r == '-' } func (tree *ParserT) parseVarTilde(exec bool) (string, error) { diff --git a/lang/types/convert.go b/lang/types/convert.go index a76232b5a..982b9425a 100644 --- a/lang/types/convert.go +++ b/lang/types/convert.go @@ -16,7 +16,7 @@ const ( // ErrUnexpectedGoType is returned if the Go data type is unhandled ErrUnexpectedGoType = "unexpected Go type" - errCannotConvertToNumeric = "cannot convert data into the numeric type '%s'" + errCannotConvertInterfaceToNumeric = "cannot convert '%T' into the numeric type '%s'" ) // ConvertGoType converts a Go lang variable into a murex variable @@ -172,6 +172,7 @@ func goStringRecast(v string, dataType string) (interface{}, error) { return v, nil case Integer: + v = strings.TrimSpace(v) if v == "" { v = "0" } @@ -183,6 +184,7 @@ func goStringRecast(v string, dataType string) (interface{}, error) { return int(f), nil case Float, Number: + v = strings.TrimSpace(v) if v == "" { v = "0" } @@ -290,10 +292,38 @@ func goDefaultRecast(v interface{}, dataType string) (interface{}, error) { } case Integer: - return 0, fmt.Errorf(errCannotConvertToNumeric, dataType) + s, err := Flatten(v) + if err != nil { + return 0, fmt.Errorf(errCannotConvertInterfaceToNumeric, v, dataType) + } + + s = strings.TrimSpace(s) + if s == "" { + s = "0" + } + + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return int(f), fmt.Errorf("cannot convert '%s' to an integer: %s", s, err.Error()) + } + return int(f), nil case Float, Number: - return 0, fmt.Errorf(errCannotConvertToNumeric, dataType) + s, err := Flatten(v) + if err != nil { + return 0, fmt.Errorf(errCannotConvertInterfaceToNumeric, v, dataType) + } + + s = strings.TrimSpace(s) + if s == "" { + s = "0" + } + + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return f, fmt.Errorf("cannot convert '%s' to a floating point number: %s", s, err.Error()) + } + return f, nil case Boolean: s := fmt.Sprint(v) diff --git a/lang/types/cast_boolean_test.go b/lang/types/convert_boolean_test.go similarity index 100% rename from lang/types/cast_boolean_test.go rename to lang/types/convert_boolean_test.go diff --git a/lang/types/cast_codeblock_test.go b/lang/types/convert_codeblock_test.go similarity index 100% rename from lang/types/cast_codeblock_test.go rename to lang/types/convert_codeblock_test.go diff --git a/lang/types/cast_float2string_test.go b/lang/types/convert_float2string_test.go similarity index 100% rename from lang/types/cast_float2string_test.go rename to lang/types/convert_float2string_test.go diff --git a/lang/types/cast_float_test.go b/lang/types/convert_float_test.go similarity index 100% rename from lang/types/cast_float_test.go rename to lang/types/convert_float_test.go diff --git a/lang/types/cast_generic_test.go b/lang/types/convert_generic_test.go similarity index 100% rename from lang/types/cast_generic_test.go rename to lang/types/convert_generic_test.go diff --git a/lang/types/flatten.go b/lang/types/flatten.go new file mode 100644 index 000000000..d9106485b --- /dev/null +++ b/lang/types/flatten.go @@ -0,0 +1,34 @@ +package types + +import ( + "fmt" + "strings" +) + +// Flatten takes anything that should look like a string, and turns it into a +// single string type. +func Flatten(v any) (string, error) { + switch t := v.(type) { + case string: + return t, nil + + case []byte: + return string(t), nil + + case []rune: + return string(t), nil + + case []string: + return strings.Join(t, "\n"), nil + + case [][]string: + var s string + for i := range t { + s += strings.Join(t[i], "\t") + "\n" + } + return s, nil + + default: + return "", fmt.Errorf("i don't know how to flatten %T", v) + } +} diff --git a/lang/variables.go b/lang/variables.go index e8a9bfb40..7f739cd72 100644 --- a/lang/variables.go +++ b/lang/variables.go @@ -13,6 +13,7 @@ import ( "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/alter" "github.com/lmorg/murex/utils/envvars" + "github.com/lmorg/murex/utils/home" "github.com/lmorg/murex/utils/json" "github.com/lmorg/murex/utils/lists" ) @@ -55,25 +56,37 @@ func errVarCannotStoreVariable(name string, err error) error { // Reserved variable names. Set as constants so any typos of these names within // the code will be raised as compiler errors const ( - DOT = "" - SELF = "SELF" - ARGV = "ARGV" - ARGS = "ARGS" - PARAMS = "PARAMS" - MUREX_EXE = "MUREX_EXE" - MUREX_ARGS = "MUREX_ARGS" - MUREX_ARGV = "MUREX_ARGV" - HOSTNAME = "HOSTNAME" - PWD = "PWD" - ENV = "ENV" - GLOBAL = "GLOBAL" - MODULE = "MOD" - COLUMNS = "COLUMNS" + _VAR_DOT = "" + _VAR_SELF = "SELF" // Scope: function + _VAR_ARGV = "ARGV" // Scope: function + _VAR_ARGS = "ARGS" // Scope: function + _VAR_PARAMS = "PARAMS" // Scope: function + _VAR_MUREX_EXE = "MUREX_EXE" // Scope: global + _VAR_MUREX_ARGS = "MUREX_ARGS" // Scope: global + _VAR_MUREX_ARGV = "MUREX_ARGV" // Scope: global + _VAR_HOSTNAME = "HOSTNAME" // Scope: global + _VAR_MODULE = "MOD" // Scope: module + _VAR_GLOBAL = "GLOBAL" // Scope: global + _VAR_ENV = "ENV" // Scope: session (environmental variable) + _VAR_PWD = "PWD" // POSIX + _VAR_OLDPWD = "OLDPWD" // POSIX (not tested) + _VAR_HOME = "HOME" // POSIX (not tested) + _VAR_TMPDIR = "TMPDIR" // POSIX (not tested) + _VAR_COLUMNS = "COLUMNS" // POSIX + _VAR_LINES = "LINES" // POSIX + _VAR_RANDOM = "RANDOM" // POSIX + _VAR_USER = "USER" // POSIX + _VAR_LOGNAME = "LOGNAME" // POSIX ) var ReservedVariableNames = []string{ - SELF, ARGV, ARGS, PARAMS, MUREX_EXE, MUREX_ARGS, MUREX_ARGV, - HOSTNAME, PWD, ENV, MODULE, GLOBAL, COLUMNS, + _VAR_SELF, _VAR_ARGV, _VAR_ARGS, _VAR_PARAMS, + _VAR_MUREX_EXE, _VAR_MUREX_ARGS, _VAR_MUREX_ARGV, + _VAR_HOSTNAME, + _VAR_MODULE, _VAR_GLOBAL, _VAR_ENV, + _VAR_PWD, _VAR_OLDPWD, _VAR_HOME, _VAR_TMPDIR, + _VAR_COLUMNS, _VAR_LINES, _VAR_RANDOM, + _VAR_USER, _VAR_LOGNAME, } // Variables is a table of all the variables. This will be local to the scope's @@ -118,7 +131,7 @@ type variable struct { // use GetString instead. func (v *Variables) GetValue(path string) (interface{}, error) { if path == "." { - return v.getValue(DOT) + return v.getValue(_VAR_DOT) } split := strings.Split(path, ".") @@ -144,39 +157,57 @@ func (v *Variables) GetValue(path string) (interface{}, error) { func (v *Variables) getValue(name string) (interface{}, error) { switch name { - case ENV: + case _VAR_ENV: return getEnvVarValue(v), nil - case GLOBAL: + case _VAR_GLOBAL: return getGlobalValues(), nil - case MODULE: + case _VAR_MODULE: return ModuleVariables.GetValues(v.process), nil - case SELF: + case _VAR_SELF: return getVarSelf(v.process), nil - case ARGV, ARGS: + case _VAR_ARGV, _VAR_ARGS: return getVarArgs(v.process), nil - case PARAMS: + case _VAR_PARAMS: return v.process.Scope.Parameters.StringArray(), nil - case MUREX_EXE: + case _VAR_MUREX_EXE: return getVarMurexExeValue() - case MUREX_ARGV, MUREX_ARGS: + case _VAR_MUREX_ARGV, _VAR_MUREX_ARGS: return getVarMurexArgs(), nil - case HOSTNAME: + case _VAR_HOSTNAME: return getHostname(), nil - case PWD: + case _VAR_PWD: return getPwdValue() - case COLUMNS: + case _VAR_OLDPWD: + return getVarOldPwdValue() + + case _VAR_HOME: + return home.MyDir, nil + + case _VAR_TMPDIR: + return getVarTmpDirValue(), nil + + case _VAR_COLUMNS: return getVarColumnsValue(), nil + case _VAR_LINES: + return getVarLinesValue() + + case _VAR_RANDOM: + return getVarRandomValue(), nil + + case _VAR_USER, _VAR_LOGNAME: + return getVarUserNameValue() + case "0": return v.process.Scope.Name.String(), nil } @@ -250,7 +281,7 @@ func (v *Variables) getEnvValueValue(name, str string) (interface{}, error) { // GetString returns a string representation of the data stored in the requested variable func (v *Variables) GetString(path string) (string, error) { if path == "." { - return v.getString(DOT) + return v.getString(_VAR_DOT) } split := strings.Split(path, ".") @@ -288,46 +319,65 @@ func (v *Variables) GetString(path string) (string, error) { func (v *Variables) getString(name string) (string, error) { switch name { - case ENV: + case _VAR_ENV: b, err := json.Marshal(getEnvVarString(), v.process.Stdout.IsTTY()) return string(b), err - case GLOBAL: + case _VAR_GLOBAL: b, err := json.Marshal(getGlobalValues(), v.process.Stdout.IsTTY()) return string(b), err - case MODULE: + case _VAR_MODULE: b, err := json.Marshal(ModuleVariables.GetValues(v.process), v.process.Stdout.IsTTY()) return string(b), err - case SELF: + case _VAR_SELF: b, err := json.Marshal(getVarSelf(v.process), v.process.Stdout.IsTTY()) return string(b), err - case ARGV, ARGS: + case _VAR_ARGV, _VAR_ARGS: b, err := json.Marshal(getVarArgs(v.process), v.process.Stdout.IsTTY()) return string(b), err - case PARAMS: + case _VAR_PARAMS: b, err := json.Marshal(v.process.Scope.Parameters.StringArray(), v.process.Stdout.IsTTY()) return string(b), err - case MUREX_EXE: + case _VAR_MUREX_EXE: return os.Executable() - case MUREX_ARGV, MUREX_ARGS: + case _VAR_MUREX_ARGV, _VAR_MUREX_ARGS: b, err := json.Marshal(getVarMurexArgs(), v.process.Stdout.IsTTY()) return string(b), err - case HOSTNAME: + case _VAR_HOSTNAME: return getHostname(), nil - case PWD: + case _VAR_PWD: return os.Getwd() - case COLUMNS: + case _VAR_OLDPWD: + return getVarOldPwdValue() + + case _VAR_HOME: + return home.MyDir, nil + + case _VAR_TMPDIR: + return getVarTmpDirValue(), nil + + case _VAR_COLUMNS: return strconv.Itoa(getVarColumnsValue()), nil + case _VAR_LINES: + i, err := getVarLinesValue() + return strconv.Itoa(i), err + + case _VAR_RANDOM: + return strconv.Itoa(getVarRandomValue()), nil + + case _VAR_USER, _VAR_LOGNAME: + return getVarUserNameValue() + case "0": return v.process.Scope.Name.String(), nil } @@ -389,7 +439,7 @@ func (v *Variables) getStringValue(name string) (string, bool) { // GetDataType returns the data type of the variable stored in the referenced VarTable func (v *Variables) GetDataType(path string) string { if path == "." { - return v.getDataType(DOT) + return v.getDataType(_VAR_DOT) } split := strings.Split(path, ".") @@ -400,11 +450,11 @@ func (v *Variables) GetDataType(path string) string { return v.getDataType(split[0]) default: switch split[0] { - case ENV: + case _VAR_ENV: return getEnvVarDataType(split[1]) - case GLOBAL: + case _VAR_GLOBAL: return getGlobalDataType(split[1]) - case MODULE: + case _VAR_MODULE: return ModuleVariables.GetDataType(v.process, split[1]) } @@ -437,30 +487,33 @@ func (v *Variables) GetDataType(path string) string { func (v *Variables) getDataType(name string) string { switch name { - case ENV, GLOBAL, MODULE: + case _VAR_ENV, _VAR_GLOBAL, _VAR_MODULE: return types.Json - case SELF: + case _VAR_SELF: return types.Json - case ARGV, ARGS: + case _VAR_ARGV, _VAR_ARGS: return types.Json - case PARAMS: + case _VAR_PARAMS: return types.Json - case MUREX_EXE: + case _VAR_MUREX_EXE: return types.Path - case MUREX_ARGV, MUREX_ARGS: + case _VAR_MUREX_ARGV, _VAR_MUREX_ARGS: return types.Json - case PWD: + case _VAR_PWD, _VAR_OLDPWD, _VAR_TMPDIR, _VAR_HOME: return types.Path - case COLUMNS: + case _VAR_COLUMNS, _VAR_LINES, _VAR_RANDOM: return types.Integer + case _VAR_USER, _VAR_LOGNAME: + return types.String + case "0": return types.String } @@ -560,7 +613,7 @@ func (v *Variables) Set(p *Process, path string, value interface{}, dataType str func (v *Variables) getNestedDataType(name string, dataType string) string { switch name { - case GLOBAL, MODULE: + case _VAR_GLOBAL, _VAR_MODULE: return dataType default: return v.GetDataType(name) @@ -570,15 +623,20 @@ func (v *Variables) getNestedDataType(name string, dataType string) string { // Set writes a variable func (v *Variables) set(p *Process, name string, value interface{}, dataType string, changePath []string) error { switch name { - case SELF, ARGV, ARGS, PARAMS, MUREX_EXE, MUREX_ARGS, MUREX_ARGV, HOSTNAME, PWD, COLUMNS, "_": + case _VAR_SELF, _VAR_ARGV, _VAR_ARGS, _VAR_PARAMS, + _VAR_MUREX_EXE, _VAR_MUREX_ARGS, _VAR_MUREX_ARGV, + _VAR_HOSTNAME, _VAR_PWD, _VAR_OLDPWD, _VAR_HOME, _VAR_TMPDIR, + _VAR_COLUMNS, _VAR_LINES, _VAR_RANDOM, + _VAR_USER, _VAR_LOGNAME, + "_": return errVariableReserved(name) - case ENV: + case _VAR_ENV: return setEnvVar(value, changePath) - case GLOBAL: + case _VAR_GLOBAL: return setGlobalVar(value, changePath, dataType) - case MODULE: + case _VAR_MODULE: return ModuleVariables.Set(p, value, changePath, dataType) - case DOT: + case _VAR_DOT: goto notReserved } for _, r := range name { @@ -659,7 +717,7 @@ notReserved: func setGlobalVar(v interface{}, changePath []string, dataType string) (err error) { if len(changePath) == 0 { - return fmt.Errorf("invalid use of $%s. Expecting a global variable name, eg `$%s.example`", GLOBAL, GLOBAL) + return fmt.Errorf("invalid use of $%s. Expecting a global variable name, eg `$%s.example`", _VAR_GLOBAL, _VAR_GLOBAL) } switch t := v.(type) { @@ -675,7 +733,7 @@ func setEnvVar(v interface{}, changePath []string) (err error) { var value interface{} if len(changePath) == 0 { - return fmt.Errorf("invalid use of $%s. Expecting an environmental variable name, eg `$%s.EXAMPLE`", ENV, ENV) + return fmt.Errorf("invalid use of $%s. Expecting an environmental variable name, eg `$%s.EXAMPLE`", _VAR_ENV, _VAR_ENV) } switch t := v.(type) { @@ -826,16 +884,24 @@ func DumpVariables(p *Process) map[string]interface{} { } p.Variables.mutex.Unlock() - m[SELF], _ = p.Variables.GetValue(SELF) - m[ARGV], _ = p.Variables.GetValue(ARGV) - m[PARAMS], _ = p.Variables.GetValue(PARAMS) - m[MUREX_EXE], _ = p.Variables.GetValue(MUREX_EXE) - m[MUREX_ARGV], _ = p.Variables.GetValue(MUREX_ARGV) - m[HOSTNAME], _ = p.Variables.GetValue(HOSTNAME) - m[PWD], _ = p.Variables.GetValue(PWD) - m[ENV], _ = p.Variables.GetValue(ENV) - m[GLOBAL] = ".." - m[COLUMNS], _ = p.Variables.GetValue(COLUMNS) + m[_VAR_SELF], _ = p.Variables.GetValue(_VAR_SELF) + m[_VAR_ARGV], _ = p.Variables.GetValue(_VAR_ARGV) + m[_VAR_PARAMS], _ = p.Variables.GetValue(_VAR_PARAMS) + m[_VAR_MUREX_EXE], _ = p.Variables.GetValue(_VAR_MUREX_EXE) + m[_VAR_MUREX_ARGV], _ = p.Variables.GetValue(_VAR_MUREX_ARGV) + m[_VAR_HOSTNAME], _ = p.Variables.GetValue(_VAR_HOSTNAME) + m[_VAR_PWD], _ = p.Variables.GetValue(_VAR_PWD) + m[_VAR_OLDPWD], _ = p.Variables.GetValue(_VAR_OLDPWD) + m[_VAR_HOME], _ = p.Variables.GetValue(_VAR_HOME) + m[_VAR_TMPDIR], _ = p.Variables.GetValue(_VAR_TMPDIR) + m[_VAR_GLOBAL] = ".." + m[_VAR_MODULE] = ".." + m[_VAR_ENV], _ = p.Variables.GetValue(_VAR_ENV) + m[_VAR_COLUMNS], _ = p.Variables.GetValue(_VAR_COLUMNS) + m[_VAR_LINES], _ = p.Variables.GetValue(_VAR_LINES) + m[_VAR_RANDOM], _ = p.Variables.GetValue(_VAR_RANDOM) + m[_VAR_USER], _ = p.Variables.GetValue(_VAR_USER) + m[_VAR_LOGNAME], _ = p.Variables.GetValue(_VAR_LOGNAME) return m } diff --git a/lang/variables_module.go b/lang/variables_module.go index f1aa1b22d..b09555672 100644 --- a/lang/variables_module.go +++ b/lang/variables_module.go @@ -43,7 +43,7 @@ func (mod *ModuleVars) GetDataType(p *Process, name string) (dt string) { func (mod *ModuleVars) Set(p *Process, value interface{}, changePath []string, dataType string) (err error) { if len(changePath) == 0 { - return fmt.Errorf("invalid use of $%s. Expecting a module variable name, eg `$%s.example`", MODULE, MODULE) + return fmt.Errorf("invalid use of $%s. Expecting a module variable name, eg `$%s.example`", _VAR_MODULE, _VAR_MODULE) } switch t := value.(type) { diff --git a/lang/variables_reserved.go b/lang/variables_reserved.go index 10520379d..cf6fe2456 100644 --- a/lang/variables_reserved.go +++ b/lang/variables_reserved.go @@ -1,7 +1,10 @@ package lang import ( + "fmt" + "math/rand" "os" + "os/user" "github.com/lmorg/murex/lang/types" "github.com/lmorg/murex/utils/envvars" @@ -10,7 +13,7 @@ import ( ) var envDataTypes = map[string][]string{ - types.Path: {"HOME", "PWD", "OLDPWD", "SHELL", "HOMEBREW_CELLAR", "HOMEBREW_PREFIX", "HOMEBREW_REPOSITORY", "GOPATH", "GOROOT", "GOBIN"}, + types.Path: {"HOME", "PWD", "OLDPWD", "SHELL", "TMPDIR", "HOMEBREW_CELLAR", "HOMEBREW_PREFIX", "HOMEBREW_REPOSITORY", "GOPATH", "GOROOT", "GOBIN"}, types.Paths: {"PATH", "LD_LIBRARY_PATH", "MANPATH", "INFOPATH"}, } @@ -93,3 +96,55 @@ func getGlobalValues() interface{} { func getVarColumnsValue() int { return readline.GetTermWidth() } + +func getVarLinesValue() (int, error) { + _, i, err := readline.GetSize(int(os.Stdout.Fd())) + if err != nil { + return 25, fmt.Errorf("cannot assign value to $%s: %v", _VAR_LINES, err) + } + return i, nil +} + +func getVarUserNameValue() (string, error) { + u, err := user.Current() + if err != nil { + return "", fmt.Errorf("cannot assign value to $%s nor $%s: %v", _VAR_USER, _VAR_LOGNAME, err) + } + + return u.Username, nil +} + +func getVarTmpDirValue() string { + return os.TempDir() +} + +func getVarRandomValue() int { + return rand.Intn(32768) +} + +func getVarOldPwdValue() (string, error) { + v, err := ShellProcess.Variables.GetValue("PWDHIST") + if err != nil { + return "", fmt.Errorf("cannot assign value to $%s: %v", _VAR_OLDPWD, err) + } + + slice, ok := v.([]any) + if !ok { + return "", fmt.Errorf("cannot assign value to $%s: $PWDHIST appears to be a %T, expecting []string", _VAR_OLDPWD, v) + } + + switch len(slice) { + case 0: + return "", fmt.Errorf("cannot assign value to $%s: $PWDHIST appears to be a empty", _VAR_OLDPWD) + + case 1: + return "", fmt.Errorf("cannot assign value to $%s: already at oldest entry in $PWDHIST", _VAR_OLDPWD) + + default: + s, ok := slice[len(slice)-2].(string) + if !ok { + return "", fmt.Errorf("cannot assign value to $%s: $PWDHIST[-1] appears to be a %T, expecting string", _VAR_OLDPWD, slice[len(slice)-2]) + } + return s, nil + } +} diff --git a/lang/variables_reserved_test.go b/lang/variables_reserved_test.go index 008e086cb..20bf05764 100644 --- a/lang/variables_reserved_test.go +++ b/lang/variables_reserved_test.go @@ -3,6 +3,7 @@ package lang_test import ( "fmt" "os" + "os/user" "testing" "github.com/lmorg/murex/test" @@ -195,7 +196,7 @@ func TestVarHostname(t *testing.T) { hostname := func() string { s, err := os.Hostname() if err != nil { - t.Errorf(err.Error()) + t.Error(err.Error()) } return s } @@ -214,7 +215,7 @@ func TestVarPwd(t *testing.T) { pwd := func() string { s, err := os.Getwd() if err != nil { - t.Errorf(err.Error()) + t.Error(err.Error()) } return s } @@ -228,3 +229,44 @@ func TestVarPwd(t *testing.T) { test.RunMurexTests(tests, t) } + +func TestVarUser(t *testing.T) { + u, _ := user.Current() + userName := u.Username + tests := []test.MurexTest{ + { + Block: `$USER`, + Stdout: userName, + }, + { + Block: `$LOGNAME`, + Stdout: userName, + }, + ///// + { + Block: `$USER -> debug -> [[/Data-Type/Murex]]`, + Stdout: `str`, + }, + { + Block: `$LOGNAME-> debug -> [[/Data-Type/Murex]]`, + Stdout: `str`, + }, + } + + test.RunMurexTests(tests, t) +} + +func TestVarRandom(t *testing.T) { + tests := []test.MurexTest{ + { + Block: `i = $RANDOM; if { $i > 0 && $i < 32768 } then { true } else { false }`, + Stdout: `true`, + }, + { + Block: `$RANDOM -> debug -> [[/Data-Type/Murex]]`, + Stdout: `int`, + }, + } + + test.RunMurexTests(tests, t) +} diff --git a/version.svg b/version.svg index 392ec9335..8f439d736 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4182Version6.3.4182 +Version: 6.3.4189Version6.3.4189 From 1fc61e439e7acfdc1d035e3e6f2511cb46160b0f Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Tue, 17 Sep 2024 21:33:21 +0100 Subject: [PATCH 139/142] website: tags --- app/app.go | 4 ++-- docs/user-guide/README.md | 2 +- gen/apis-md-doc.tmpl | 4 +++- gen/blog-md-cat.tmpl | 2 +- gen/blog-md-doc.tmpl | 4 +++- gen/changelog-md-cat.tmpl | 2 +- gen/changelog-md-doc.tmpl | 4 +++- gen/commands-md-cat.tmpl | 2 +- gen/commands-md-doc.tmpl | 4 +++- gen/events-md-cat.tmpl | 2 +- gen/events-md-doc.tmpl | 4 +++- gen/integrations-md-cat.tmpl | 2 +- gen/integrations-md-doc.tmpl | 4 +++- gen/mkarray-md-doc.tmpl | 4 +++- gen/murex-md-cat.tmpl | 2 +- gen/parser-md-cat.tmpl | 2 +- gen/parser-md-doc.tmpl | 3 ++- gen/types-md-doc.tmpl | 3 ++- gen/userguide-md-cat.tmpl.md | 4 ++-- gen/userguide-md-doc.tmpl | 3 ++- gen/variables-md-cat.tmpl | 2 +- gen/variables-md-doc.tmpl | 3 ++- utils/docgen/api/category.go | 18 ------------------ utils/docgen/api/document.go | 23 +++++++++++++++-------- version.svg | 2 +- 25 files changed, 58 insertions(+), 51 deletions(-) diff --git a/app/app.go b/app/app.go index d4143e685..ae3279887 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4189 + Revision = 4195 Branch = "develop" - BuildDate = "2024-09-17 21:23:36" + BuildDate = "2024-09-17 22:10:17" ) // Copyright is the copyright owner string diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index e1250b4e4..9c2117417 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -7,7 +7,7 @@ shell and Murex's numerous features.
      -- [category: user-guide](#category--id-) +- [category: User Guide](#category--title-) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/apis-md-doc.tmpl b/gen/apis-md-doc.tmpl index a1cc765d2..1e8dce95e 100644 --- a/gen/apis-md-doc.tmpl +++ b/gen/apis-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/blog-md-cat.tmpl b/gen/blog-md-cat.tmpl index 3f4ff09e9..25b295685 100644 --- a/gen/blog-md-cat.tmpl +++ b/gen/blog-md-cat.tmpl @@ -3,7 +3,7 @@ title: {{ .Title }} description: {{ quote .Summary }} index: true icon: comment -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/blog-md-doc.tmpl b/gen/blog-md-doc.tmpl index a88c369a9..f2494ffaa 100644 --- a/gen/blog-md-doc.tmpl +++ b/gen/blog-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/changelog-md-cat.tmpl b/gen/changelog-md-cat.tmpl index 6be0f7dd0..7346be925 100644 --- a/gen/changelog-md-cat.tmpl +++ b/gen/changelog-md-cat.tmpl @@ -3,7 +3,7 @@ index: true title: {{ .Title }} description: {{ quote .Summary }} icon: laptop-code -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/changelog-md-doc.tmpl b/gen/changelog-md-doc.tmpl index 4b6e788cf..5f36e02da 100644 --- a/gen/changelog-md-doc.tmpl +++ b/gen/changelog-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/commands-md-cat.tmpl b/gen/commands-md-cat.tmpl index f2f0d2d6b..3c065b052 100644 --- a/gen/commands-md-cat.tmpl +++ b/gen/commands-md-cat.tmpl @@ -3,7 +3,7 @@ index: true title: {{ .Title }} description: {{ quote .Summary }} icon: cubes -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/commands-md-doc.tmpl b/gen/commands-md-doc.tmpl index 64ab49472..1b44b6af7 100644 --- a/gen/commands-md-doc.tmpl +++ b/gen/commands-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/events-md-cat.tmpl b/gen/events-md-cat.tmpl index 279bbc485..2549ef22f 100644 --- a/gen/events-md-cat.tmpl +++ b/gen/events-md-cat.tmpl @@ -2,7 +2,7 @@ index: true title: {{ .Title }} description: {{ quote .Summary }} -category: {{ .ID }} +category: {{ .Title }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): diff --git a/gen/events-md-doc.tmpl b/gen/events-md-doc.tmpl index c272f6fc4..56cbabcf0 100644 --- a/gen/events-md-doc.tmpl +++ b/gen/events-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/integrations-md-cat.tmpl b/gen/integrations-md-cat.tmpl index 6c48ae453..4550326a5 100644 --- a/gen/integrations-md-cat.tmpl +++ b/gen/integrations-md-cat.tmpl @@ -3,7 +3,7 @@ index: true icon: puzzle-piece title: {{ quote .Title }} description: {{ quote .Summary }} -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ .Title }} diff --git a/gen/integrations-md-doc.tmpl b/gen/integrations-md-doc.tmpl index 7f51b4b7d..2369ed7c5 100644 --- a/gen/integrations-md-doc.tmpl +++ b/gen/integrations-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/mkarray-md-doc.tmpl b/gen/mkarray-md-doc.tmpl index b83e36c7f..9d290e85e 100644 --- a/gen/mkarray-md-doc.tmpl +++ b/gen/mkarray-md-doc.tmpl @@ -1,7 +1,9 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +category: {{ .CategoryTitle }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/murex-md-cat.tmpl b/gen/murex-md-cat.tmpl index 22e8a0591..f0b683a5d 100644 --- a/gen/murex-md-cat.tmpl +++ b/gen/murex-md-cat.tmpl @@ -2,7 +2,7 @@ index: true title: {{ md .Title }} description: {{ quote .Summary }} -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ md .Title }}{{ if .Description }} diff --git a/gen/parser-md-cat.tmpl b/gen/parser-md-cat.tmpl index 79a952006..01fc176d6 100644 --- a/gen/parser-md-cat.tmpl +++ b/gen/parser-md-cat.tmpl @@ -2,7 +2,7 @@ title: {{ $doc.Title }} description: {{ quote .Summary }} index: true -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}# {{ md $doc.Title }}{{ if .Description }} diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 26e9c7ff2..8f517bbfe 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,7 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index ab07a9ad6..05abe635e 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,7 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index 11555d8e1..dd3de7f6f 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -3,7 +3,7 @@ title: {{ md .Title }} description: {{ quote .Summary }} index: true icon: book -category: {{ .ID }} +category: {{ .Title }} --- {{ end }}

      {{ md .Title }}

      {{ if .Description }} @@ -14,7 +14,7 @@ category: {{ .ID }}
      -- [category: {{ .ID }}](#category--id-) +- [category: {{ .Title }}](#category--title-) - [Language Tour](#language-tour) - [User Guides](#user-guides) - [Integrations](#integrations) diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index 7bc690ea8..2a6998713 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,7 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} -category: {{ .CategoryID }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/gen/variables-md-cat.tmpl b/gen/variables-md-cat.tmpl index a185786dc..02838f4ee 100644 --- a/gen/variables-md-cat.tmpl +++ b/gen/variables-md-cat.tmpl @@ -1,7 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- index: true description: {{ quote .Summary }} -category: {{ .ID }} +category: {{ .Title }} --- {{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 65b837b0a..636247af6 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,7 +1,8 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} -category: {{ .CategoryID }} +{{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} + - {{ .Title }}{{ end }}{{ end }} --- {{ end }}# {{ md .Title }} diff --git a/utils/docgen/api/category.go b/utils/docgen/api/category.go index 6c297f7b5..90a216f6a 100644 --- a/utils/docgen/api/category.go +++ b/utils/docgen/api/category.go @@ -36,24 +36,6 @@ func (c *category) SubCategoryByID(id string) (*category, error) { return nil, fmt.Errorf("cannot find a sub-category with the id '%s'", id) } -/*func (c *category) getSubCategoryTitle(id string) string { - sub, err := c.SubCategoryByID(id) - if err != nil { - return "" - } - - return sub.Title -} - -func (c *category) getSubCategoryDescription(id string) string { - sub, err := c.SubCategoryByID(id) - if err != nil { - return "" - } - - return sub.Description -}*/ - type templates struct { // OutputPath to write the rendered documents OutputPath string `yaml:"OutputPath"` diff --git a/utils/docgen/api/document.go b/utils/docgen/api/document.go index b9157a42b..a86351246 100644 --- a/utils/docgen/api/document.go +++ b/utils/docgen/api/document.go @@ -5,6 +5,8 @@ import ( "sort" "strings" "time" + + "github.com/lmorg/murex/utils/lists" ) // Document is the catalogue of config files found in the search path @@ -129,7 +131,7 @@ func (t templates) DocumentValues(d *document, docs documents, nest bool) *docum CategoryID: d.CategoryID, CategoryTitle: t.ref.Title, CategoryDescription: t.ref.Description, - SubCategories: documentSubCategories(t.ref), + SubCategories: documentSubCategories(d), Summary: d.Summary, Description: d.Description, Usage: d.Usage, @@ -200,14 +202,19 @@ type documentValuesSubCats struct { Description string } -func documentSubCategories(cat *category) []documentValuesSubCats { +func documentSubCategories(d *document) []documentValuesSubCats { var subs []documentValuesSubCats - for _, c := range cat.SubCategories { - subs = append(subs, documentValuesSubCats{ - ID: c.ID, - Title: c.Title, - Description: c.Description, - }) + for _, cat := range Config.Categories { + for _, sub := range cat.SubCategories { + if !lists.Match(d.SubCategoryIDs, sub.ID) { + continue + } + subs = append(subs, documentValuesSubCats{ + ID: sub.ID, + Title: sub.Title, + Description: sub.Description, + }) + } } return subs } diff --git a/version.svg b/version.svg index 8f439d736..bffa74bda 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4189Version6.3.4189 +Version: 6.3.4195Version6.3.4195 From 028d581fd6f4e9178bca3dfc7ad99accfe92354b Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 18 Sep 2024 07:54:58 +0100 Subject: [PATCH 140/142] website: update templates + variable landing page --- app/app.go | 4 +- builtins/docs/summaries.go | 6 +- builtins/events/events_doc.yaml | 4 - docs/commands/event.md | 17 -- .../events/README.md | 6 + docs/user-guide/README.md | 44 +++++ docs/user-guide/reserved-vars.md | 11 +- docs/variables/README.md | 87 ++++++++ docs/variables/argv.md | 43 ---- docs/variables/columns.md | 45 +---- docs/variables/event_return.md | 43 ---- docs/variables/home.md | 43 ---- docs/variables/hostname.md | 43 ---- docs/variables/lines.md | 45 +---- docs/variables/logname.md | 43 ---- docs/variables/meta-values.md | 43 ---- docs/variables/murex_argv.md | 43 ---- docs/variables/murex_exe.md | 43 ---- docs/variables/numeric.md | 43 ---- docs/variables/oldpwd.md | 43 ---- docs/variables/params.md | 43 ---- docs/variables/pwd.md | 43 ---- docs/variables/pwdhist.md | 43 ---- docs/variables/random.md | 43 ---- docs/variables/self.md | 43 ---- docs/variables/shell.md | 43 ---- docs/variables/tmpdir.md | 43 ---- docs/variables/user.md | 43 ---- gen/docgen.yaml | 16 +- gen/events-md-cat.inc.md | 0 gen/events-md-cat.tmpl | 8 +- gen/includes/autogenerated.variables.inc.md | 40 ---- gen/parser-md-doc.tmpl | 1 + gen/types-md-doc.tmpl | 1 + gen/user-guide/reserved_vars_doc.yaml | 17 +- gen/userguide-md-cat.tmpl.md | 7 + gen/userguide-md-doc.tmpl | 1 + gen/variables-md-cat.inc.md | 42 ++++ gen/variables-md-cat.tmpl | 9 +- gen/variables-md-doc.tmpl | 7 +- gen/variables-vue-cat.tmpl | 1 + gen/variables/LINES_doc.yaml | 2 +- gen/vuepress/sidebar.ts | 9 +- gen/vuepress/variables_generated.json | 186 ++++++++++++++++++ utils/docgen/api/functions.go | 2 +- version.svg | 2 +- 46 files changed, 438 insertions(+), 956 deletions(-) rename gen/includes/autogenerated.events.inc.md => docs/events/README.md (96%) create mode 100644 docs/variables/README.md create mode 100644 gen/events-md-cat.inc.md delete mode 100644 gen/includes/autogenerated.variables.inc.md create mode 100644 gen/variables-md-cat.inc.md create mode 100644 gen/variables-vue-cat.tmpl create mode 100644 gen/vuepress/variables_generated.json diff --git a/app/app.go b/app/app.go index ae3279887..d68088be0 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4195 + Revision = 4213 Branch = "develop" - BuildDate = "2024-09-17 22:10:17" + BuildDate = "2024-09-18 08:38:26" ) // Copyright is the copyright owner string diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index b578c805c..832ba6359 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -333,10 +333,10 @@ func init() { "variables/meta-values": "State information for iteration blocks", "variables/argv": "Array of the command name and parameters within a given scope", "variables/columns": "Character width of terminal", - "variables/lines": "Character height of terminal", "variables/event_return": "Return values for events", "variables/home": "Return the home directory for the current session user", "variables/hostname": "Hostname of the current machine", + "variables/lines": "Character height of terminal", "variables/logname": "Username for the current session (historic)", "variables/murex_argv": "Array of the command name and parameters passed to the current shell", "variables/murex_exe": "Absolute path to running shell", @@ -949,14 +949,14 @@ func init() { "variables/ARGS": "variables/argv", "variables/columns": "variables/columns", "variables/COLUMNS": "variables/columns", - "variables/lines": "variables/lines", - "variables/LINES": "variables/lines", "variables/event_return": "variables/event_return", "variables/EVENT_RETURN": "variables/event_return", "variables/home": "variables/home", "variables/HOME": "variables/home", "variables/hostname": "variables/hostname", "variables/HOSTNAME": "variables/hostname", + "variables/lines": "variables/lines", + "variables/LINES": "variables/lines", "variables/logname": "variables/logname", "variables/LOGNAME": "variables/logname", "variables/murex_argv": "variables/murex_argv", diff --git a/builtins/events/events_doc.yaml b/builtins/events/events_doc.yaml index 00de94b92..9ae0fb949 100644 --- a/builtins/events/events_doc.yaml +++ b/builtins/events/events_doc.yaml @@ -54,10 +54,6 @@ ``` Flags: Detail: |- - ### Supported events - - {{ include "gen/includes/autogenerated.events.inc.md" }} - ### ANSI constants The `interrupt` field in the CLI supports ANSI constants. eg diff --git a/docs/commands/event.md b/docs/commands/event.md index fc8219866..881df62fc 100644 --- a/docs/commands/event.md +++ b/docs/commands/event.md @@ -57,23 +57,6 @@ event onSecondsElapsed autoquit=60 { ## Detail -### Supported events - -* [`onCommandCompletion`](../events/oncommandcompletion.md): - Trigger an event upon a command's completion -* [`onFileSystemChange`](../events/onfilesystemchange.md): - Add a filesystem watch -* [`onKeyPress`](../events/onkeypress.md): - Custom definable key bindings and macros -* [`onPreview`](../events/onpreview.md): - Full screen previews for files and command documentation -* [`onPrompt`](../events/onprompt.md): - Events triggered by changes in state of the interactive shell -* [`onSecondsElapsed`](../events/onsecondselapsed.md): - Events triggered by time intervals -* [`onSignalReceived`](../events/onsignalreceived.md): - Trap OS signals - ### ANSI constants The `interrupt` field in the CLI supports ANSI constants. eg diff --git a/gen/includes/autogenerated.events.inc.md b/docs/events/README.md similarity index 96% rename from gen/includes/autogenerated.events.inc.md rename to docs/events/README.md index a91a85ae9..e0319c687 100644 --- a/gen/includes/autogenerated.events.inc.md +++ b/docs/events/README.md @@ -1,3 +1,9 @@ +# events + + + +## Pages + * [`onCommandCompletion`](../events/oncommandcompletion.md): Trigger an event upon a command's completion * [`onFileSystemChange`](../events/onfilesystemchange.md): diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md index 9c2117417..ffc02d2a4 100644 --- a/docs/user-guide/README.md +++ b/docs/user-guide/README.md @@ -17,6 +17,7 @@ shell and Murex's numerous features. - [Optional Builtins](#optional-builtins) - [Data Types](#data-types) - [Events](#events) +- [Variables](#variables) - [Integrations](#integrations-1) - [API Reference](#api-reference) @@ -466,6 +467,49 @@ are only included by default on Windows. * [`onSignalReceived`](../events/onsignalreceived.md): Trap OS signals +## Variables + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LINES` (int)](../variables/lines.md): + Character height of terminal +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory +* [`USER` (str)](../variables/user.md): + Username for the current session + ## Integrations * [ChatGPT](../integrations/chatgpt.md): diff --git a/docs/user-guide/reserved-vars.md b/docs/user-guide/reserved-vars.md index b27b76a9c..8392a4814 100644 --- a/docs/user-guide/reserved-vars.md +++ b/docs/user-guide/reserved-vars.md @@ -3,19 +3,26 @@ > Special variables reserved by Murex In Murex, there are five different classes of variables: + 1. Local variables (scope limited to a function et al) + 2. Module variables (scoped to a module) + 3. Global variables (available to every function within Murex but not shared with processes outside of the Murex's runtime) + 4. Environmental variables (available to every function and process -- internal and external to Murex) + 5. Reserved variables Reserved variables are data that are available to any code running within Murex and exposed as a variable. -Because reserved variables are dynamic properties of the runtime environment, -they can only be queried and not set: +Reserved variables are called _reserved_ because they are read only. + +Reserved variables are often also dynamic, returning different values based on +contextual circumstances. ``` » set SELF="foobar" diff --git a/docs/variables/README.md b/docs/variables/README.md new file mode 100644 index 000000000..1a9478c6e --- /dev/null +++ b/docs/variables/README.md @@ -0,0 +1,87 @@ +# Special Variables + +Variables are typed. + +They can be a _primitive_ like `int` or `str`. They can also be a structured +document like `json`, `csv` or `sexpr`. + +Variables can also have a string representation, for compatibility with older +POSIX idioms, as well as a native object format. + +## Glossary Of Terms + +To help better understand how variables work under the hood, blow is a glossary +of terms: + +* _primitive_: this refers to the atomic component of a _data-type_. In other + words, the smallest possible format for a piece of data. Where a JSON file + might arrays and maps, the values for those objects cannot be divided any + smaller than numbers, strings or a small number of constants like `true`, + `false`, and `null`. + +* _scope_: this is how far outside the code block that a particular variable + can be written to, or read from. + +* _local_ (scope): this refers to variables that cannot be read nor modified + outside of the current function. Thus one function cannot read nor write to + a variable in another function. + +* _module_ (scope): these variables are accessible by any function or routine + from within the same module. You'll only need _module scoped_ variables if + you're writing modules -- and even then, only if you want that variable + available to all functions within that module. + +* _global_ (scope): these are variables which are accessible from any function, + anywhere within Murex. + +* _environmental variables_: sometimes written as _env vars_ for short, these + are system variables. They can be passed from one process to another, so + careful what secrets you store and what software you run while you have + sensitive _env vars_ defined. + +* _reserved variables_: this refers to variables that are read only. Some + reserved variables are dynamic and thus can change their value depending on + contextual circumstances. + +## Pages + +* [Numeric (str)](../variables/numeric.md): + Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above +* [`$.`, Meta Values (json)](../variables/meta-values.md): + State information for iteration blocks +* [`ARGV` (json)](../variables/argv.md): + Array of the command name and parameters within a given scope +* [`COLUMNS` (int)](../variables/columns.md): + Character width of terminal +* [`EVENT_RETURN` (json)](../variables/event_return.md): + Return values for events +* [`HOME` (path)](../variables/home.md): + Return the home directory for the current session user +* [`HOSTNAME` (str)](../variables/hostname.md): + Hostname of the current machine +* [`LINES` (int)](../variables/lines.md): + Character height of terminal +* [`LOGNAME` (str)](../variables/logname.md): + Username for the current session (historic) +* [`MUREX_ARGV` (json)](../variables/murex_argv.md): + Array of the command name and parameters passed to the current shell +* [`MUREX_EXE` (path)](../variables/murex_exe.md): + Absolute path to running shell +* [`OLDPWD` (path)](../variables/oldpwd.md): + Return the home directory for the current session user +* [`PARAMS` (json)](../variables/params.md): + Array of the parameters within a given scope +* [`PWDHIST` (json)](../variables/pwdhist.md): + History of each change to the sessions working directory +* [`PWD` (path)](../variables/pwd.md): + Current working directory +* [`RANDOM` (int)](../variables/random.md): + Return a random 32-bit integer (historical) +* [`SELF` (json)](../variables/self.md): + Meta information about the running scope. +* [`SHELL` (str)](../variables/shell.md): + Path of current shell +* [`TMPDIR` (path)](../variables/tmpdir.md): + Return the temporary directory +* [`USER` (str)](../variables/user.md): + Username for the current session \ No newline at end of file diff --git a/docs/variables/argv.md b/docs/variables/argv.md index 2b0ee0c45..d4cc5980b 100644 --- a/docs/variables/argv.md +++ b/docs/variables/argv.md @@ -36,49 +36,6 @@ the name with other languages. `ARGS` will remain available for compatibility reasons but is considered deprecated and may be removed from future releases. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Define Variable (`set`)](../commands/set.md): diff --git a/docs/variables/columns.md b/docs/variables/columns.md index b35a8ee9e..b3973b8e3 100644 --- a/docs/variables/columns.md +++ b/docs/variables/columns.md @@ -12,56 +12,13 @@ the same width as one terminal cell. This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Interactive Shell](../user-guide/interactive-shell.md): What's different about Murex's interactive shell? * [Reserved Variables](../user-guide/reserved-vars.md): Special variables reserved by Murex -* [`COLUMNS` (int)](../variables/lines.md): +* [`LINES` (int)](../variables/lines.md): Character height of terminal * [`int`](../types/int.md): Whole number (primitive) diff --git a/docs/variables/event_return.md b/docs/variables/event_return.md index 9f2c3f0c7..963443a62 100644 --- a/docs/variables/event_return.md +++ b/docs/variables/event_return.md @@ -23,49 +23,6 @@ event onPreview example=exec { `$EVENT_RETURN` will support different values for different events. Please read the respective event document for details on using this variable. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Murex Event Subsystem (`event`)](../commands/event.md): diff --git a/docs/variables/home.md b/docs/variables/home.md index ca68eb558..ca6c7e0fe 100644 --- a/docs/variables/home.md +++ b/docs/variables/home.md @@ -11,49 +11,6 @@ POSIX support. This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/docs/variables/hostname.md b/docs/variables/hostname.md index f7503c62e..835f60d63 100644 --- a/docs/variables/hostname.md +++ b/docs/variables/hostname.md @@ -9,49 +9,6 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/docs/variables/lines.md b/docs/variables/lines.md index a29f336b4..22e61029b 100644 --- a/docs/variables/lines.md +++ b/docs/variables/lines.md @@ -1,4 +1,4 @@ -# `COLUMNS` (int) +# `LINES` (int) > Character height of terminal @@ -27,49 +27,6 @@ Error in `/Users/laurencemorgan/dev/go/src/github.com/lmorg/murex/murex` (0,1): This error can be caught via `||`, `try` et al. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Execute External Command (`exec`)](../commands/exec.md): diff --git a/docs/variables/logname.md b/docs/variables/logname.md index 8c8826561..44a4bcdc1 100644 --- a/docs/variables/logname.md +++ b/docs/variables/logname.md @@ -63,49 +63,6 @@ compatibility reasons. purposes (such as logging) and then get confused why other utilities might break after they've overwritten the contents of `$LOGNAME` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/docs/variables/meta-values.md b/docs/variables/meta-values.md index 9e55e9dae..c4aa2936d 100644 --- a/docs/variables/meta-values.md +++ b/docs/variables/meta-values.md @@ -22,49 +22,6 @@ iteration structure's documentation to check what information is exposed via 5: Friday ``` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [For Each In List (`foreach`)](../commands/foreach.md): diff --git a/docs/variables/murex_argv.md b/docs/variables/murex_argv.md index 96d74a373..cdc0a80dd 100644 --- a/docs/variables/murex_argv.md +++ b/docs/variables/murex_argv.md @@ -21,49 +21,6 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be ] ``` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [`@Array` Sigil](../parser/array.md): diff --git a/docs/variables/murex_exe.md b/docs/variables/murex_exe.md index be9d7b166..1dd048272 100644 --- a/docs/variables/murex_exe.md +++ b/docs/variables/murex_exe.md @@ -10,49 +10,6 @@ variable is so that the shell path cannot be overridden. This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Define Variable (`set`)](../commands/set.md): diff --git a/docs/variables/numeric.md b/docs/variables/numeric.md index 0e179b990..16088a1d2 100644 --- a/docs/variables/numeric.md +++ b/docs/variables/numeric.md @@ -29,49 +29,6 @@ then the variable will not be set thus the upper limit variable is determined by how many parameters are set. For example if you have 19 parameters passed then variables `$1` through to `$19` (inclusive) will all be set. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Define Variable (`set`)](../commands/set.md): diff --git a/docs/variables/oldpwd.md b/docs/variables/oldpwd.md index 4d04f2268..e3d87f0e2 100644 --- a/docs/variables/oldpwd.md +++ b/docs/variables/oldpwd.md @@ -34,49 +34,6 @@ Error in `cd` (0,1): cannot assign value to $OLDPWD: already at oldest entry in > Character : 9 ``` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/docs/variables/params.md b/docs/variables/params.md index ff109cf17..7a19062d7 100644 --- a/docs/variables/params.md +++ b/docs/variables/params.md @@ -24,49 +24,6 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be ] ``` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Define Variable (`set`)](../commands/set.md): diff --git a/docs/variables/pwd.md b/docs/variables/pwd.md index 66240e077..9f671a871 100644 --- a/docs/variables/pwd.md +++ b/docs/variables/pwd.md @@ -8,49 +8,6 @@ It is updated via `cd` however you can overwrite its value manually via `export`. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Change Directory (`cd`)](../commands/cd.md): diff --git a/docs/variables/pwdhist.md b/docs/variables/pwdhist.md index c51fabac1..ef23b181b 100644 --- a/docs/variables/pwdhist.md +++ b/docs/variables/pwdhist.md @@ -21,49 +21,6 @@ It is updated via `cd` however you can overwrite its value manually via `set`. ] ``` -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Change Directory (`cd`)](../commands/cd.md): diff --git a/docs/variables/random.md b/docs/variables/random.md index d8b95ee9c..4d0770bfc 100644 --- a/docs/variables/random.md +++ b/docs/variables/random.md @@ -11,49 +11,6 @@ random tokens in Murex is via the [`rand` builtin](/docs/commands/rand.md). This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Generate Random Sequence (`rand`)](../commands/rand.md): diff --git a/docs/variables/self.md b/docs/variables/self.md index 156ca47e1..19c6a6f9e 100644 --- a/docs/variables/self.md +++ b/docs/variables/self.md @@ -80,49 +80,6 @@ scope. A boolean value as to whether stdout is a TTY (ie are we printing to the terminal (TTY) or a pipe?) -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Interactive Shell](../user-guide/interactive-shell.md): diff --git a/docs/variables/shell.md b/docs/variables/shell.md index 5748a3f33..bdda98f23 100644 --- a/docs/variables/shell.md +++ b/docs/variables/shell.md @@ -13,49 +13,6 @@ environmental variable, it can be overwritten via `export`. For Murex specific code, you are recommended to use `MUREX_EXE`, which is a reserved variable, and thus read only, if you require precision and safety. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Define Environmental Variable (`export`)](../commands/export.md): diff --git a/docs/variables/tmpdir.md b/docs/variables/tmpdir.md index 177fe97a6..3be3c758c 100644 --- a/docs/variables/tmpdir.md +++ b/docs/variables/tmpdir.md @@ -8,49 +8,6 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/docs/variables/user.md b/docs/variables/user.md index fe879a796..18aac7c44 100644 --- a/docs/variables/user.md +++ b/docs/variables/user.md @@ -8,49 +8,6 @@ This is a [reserved variable](/docs/user-guide/reserved-vars.md) so it cannot be changed. -## Other Reserved Variables - -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session - ## See Also * [Reserved Variables](../user-guide/reserved-vars.md): diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 125638223..4561f9c61 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -199,10 +199,11 @@ Categories: Title: events Summary: >- Murex's event system allows for easy and flexible code. You can extend upon the shell in a multitude of ways. - Description: + Description: |- + {{ include "gen/events-md-cat.inc.md" }} Templates: - OutputPath: docs/events - CategoryFile: ../../gen/includes/autogenerated.events.inc.md + CategoryFile: README.md OutputExt: .md CategoryTemplate: gen/events-md-cat.tmpl DocumentTemplate: gen/events-md-doc.tmpl @@ -227,15 +228,20 @@ Categories: - ID: variables Title: Special Variables Summary: >- - Variables are tokenised, so to avoid accidental bugs caused by (for example) spaces in file names. Enhancements like these are what makes Murex a much safer language than traditional shells - Description: + Variables are tokenized, so to avoid accidental bugs caused by (for example) spaces in file names. Enhancements like these are what makes Murex a much safer language than traditional shells + Description: |- + {{ include "gen/variables-md-cat.inc.md" }} Templates: - OutputPath: docs/variables - CategoryFile: ../../gen/includes/autogenerated.variables.inc.md + CategoryFile: README.md OutputExt: .md CategoryTemplate: gen/variables-md-cat.tmpl DocumentTemplate: gen/variables-md-doc.tmpl + - OutputPath: gen/vuepress + CategoryFile: variables_generated.json + CategoryTemplate: gen/variables-vue-cat.tmpl + SubCategories: - ID: vars.env Title: Environmental Variables diff --git a/gen/events-md-cat.inc.md b/gen/events-md-cat.inc.md new file mode 100644 index 000000000..e69de29bb diff --git a/gen/events-md-cat.tmpl b/gen/events-md-cat.tmpl index 2549ef22f..79dfc3914 100644 --- a/gen/events-md-cat.tmpl +++ b/gen/events-md-cat.tmpl @@ -4,6 +4,12 @@ title: {{ .Title }} description: {{ quote .Summary }} category: {{ .Title }} --- -{{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} +{{ end }}# {{ md .Title }}{{ if .Description }} + +{{ md (include .Description) }}{{ end }} + +## Pages + +{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/includes/autogenerated.variables.inc.md b/gen/includes/autogenerated.variables.inc.md deleted file mode 100644 index 365d97794..000000000 --- a/gen/includes/autogenerated.variables.inc.md +++ /dev/null @@ -1,40 +0,0 @@ -* [Numeric (str)](../variables/numeric.md): - Variables who's name is a positive integer, eg `0`, `1`, `2`, `3` and above -* [`$.`, Meta Values (json)](../variables/meta-values.md): - State information for iteration blocks -* [`ARGV` (json)](../variables/argv.md): - Array of the command name and parameters within a given scope -* [`COLUMNS` (int)](../variables/columns.md): - Character width of terminal -* [`COLUMNS` (int)](../variables/lines.md): - Character height of terminal -* [`EVENT_RETURN` (json)](../variables/event_return.md): - Return values for events -* [`HOME` (path)](../variables/home.md): - Return the home directory for the current session user -* [`HOSTNAME` (str)](../variables/hostname.md): - Hostname of the current machine -* [`LOGNAME` (str)](../variables/logname.md): - Username for the current session (historic) -* [`MUREX_ARGV` (json)](../variables/murex_argv.md): - Array of the command name and parameters passed to the current shell -* [`MUREX_EXE` (path)](../variables/murex_exe.md): - Absolute path to running shell -* [`OLDPWD` (path)](../variables/oldpwd.md): - Return the home directory for the current session user -* [`PARAMS` (json)](../variables/params.md): - Array of the parameters within a given scope -* [`PWDHIST` (json)](../variables/pwdhist.md): - History of each change to the sessions working directory -* [`PWD` (path)](../variables/pwd.md): - Current working directory -* [`RANDOM` (int)](../variables/random.md): - Return a random 32-bit integer (historical) -* [`SELF` (json)](../variables/self.md): - Meta information about the running scope. -* [`SHELL` (str)](../variables/shell.md): - Path of current shell -* [`TMPDIR` (path)](../variables/tmpdir.md): - Return the temporary directory -* [`USER` (str)](../variables/user.md): - Username for the current session \ No newline at end of file diff --git a/gen/parser-md-doc.tmpl b/gen/parser-md-doc.tmpl index 8f517bbfe..9b8456613 100644 --- a/gen/parser-md-doc.tmpl +++ b/gen/parser-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: {{ .CategoryTitle }} {{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} - {{ .Title }}{{ end }}{{ end }} --- diff --git a/gen/types-md-doc.tmpl b/gen/types-md-doc.tmpl index 05abe635e..0b4e935e7 100644 --- a/gen/types-md-doc.tmpl +++ b/gen/types-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: {{ .CategoryTitle }} {{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} - {{ .Title }}{{ end }}{{ end }} --- diff --git a/gen/user-guide/reserved_vars_doc.yaml b/gen/user-guide/reserved_vars_doc.yaml index c7747777c..7ceb0f8ec 100644 --- a/gen/user-guide/reserved_vars_doc.yaml +++ b/gen/user-guide/reserved_vars_doc.yaml @@ -6,29 +6,32 @@ Special variables reserved by Murex Description: |- In Murex, there are five different classes of variables: + 1. Local variables (scope limited to a function et al) + 2. Module variables (scoped to a module) + 3. Global variables (available to every function within Murex but not shared with processes outside of the Murex's runtime) + 4. Environmental variables (available to every function and process -- internal and external to Murex) + 5. Reserved variables Reserved variables are data that are available to any code running within Murex and exposed as a variable. - Because reserved variables are dynamic properties of the runtime environment, - they can only be queried and not set: + Reserved variables are called _reserved_ because they are read only. + + Reserved variables are often also dynamic, returning different values based on + contextual circumstances. ``` » set SELF="foobar" Error in `set` (0,1): cannot set a reserved variable: SELF ``` - Detail: |- - For more detail on specific reserved variables, please read their accompanying - documentation: - - {{ include "gen/includes/autogenerated.variables.inc.md" }} + Detail: Synonyms: - reserved-vars - reserved diff --git a/gen/userguide-md-cat.tmpl.md b/gen/userguide-md-cat.tmpl.md index dd3de7f6f..9607efb8c 100644 --- a/gen/userguide-md-cat.tmpl.md +++ b/gen/userguide-md-cat.tmpl.md @@ -24,6 +24,7 @@ category: {{ .Title }} - [Optional Builtins](#optional-builtins) - [Data Types](#data-types) - [Events](#events) +- [Variables](#variables) - [Integrations](#integrations-1) - [API Reference](#api-reference) @@ -81,6 +82,12 @@ are only included by default on Windows. {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} +## Variables + +{{ if otherdocs "variables" }}{{ range $i,$a := otherdocs "variables" }}{{ if gt $i 0 }} +{{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): + {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} + ## Integrations {{ if otherdocs "integrations" }}{{ range $i,$a := otherdocs "integrations" }}{{ if gt $i 0 }} diff --git a/gen/userguide-md-doc.tmpl b/gen/userguide-md-doc.tmpl index 2a6998713..0fbb5d5b8 100644 --- a/gen/userguide-md-doc.tmpl +++ b/gen/userguide-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-lines description: {{ quote .Summary }} +category: {{ .CategoryTitle }} {{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} - {{ .Title }}{{ end }}{{ end }} --- diff --git a/gen/variables-md-cat.inc.md b/gen/variables-md-cat.inc.md new file mode 100644 index 000000000..6a64fb256 --- /dev/null +++ b/gen/variables-md-cat.inc.md @@ -0,0 +1,42 @@ +Variables are typed. + +They can be a _primitive_ like `int` or `str`. They can also be a structured +document like `json`, `csv` or `sexpr`. + +Variables can also have a string representation, for compatibility with older +POSIX idioms, as well as a native object format. + +## Glossary Of Terms + +To help better understand how variables work under the hood, blow is a glossary +of terms: + +* _primitive_: this refers to the atomic component of a _data-type_. In other + words, the smallest possible format for a piece of data. Where a JSON file + might arrays and maps, the values for those objects cannot be divided any + smaller than numbers, strings or a small number of constants like `true`, + `false`, and `null`. + +* _scope_: this is how far outside the code block that a particular variable + can be written to, or read from. + +* _local_ (scope): this refers to variables that cannot be read nor modified + outside of the current function. Thus one function cannot read nor write to + a variable in another function. + +* _module_ (scope): these variables are accessible by any function or routine + from within the same module. You'll only need _module scoped_ variables if + you're writing modules -- and even then, only if you want that variable + available to all functions within that module. + +* _global_ (scope): these are variables which are accessible from any function, + anywhere within Murex. + +* _environmental variables_: sometimes written as _env vars_ for short, these + are system variables. They can be passed from one process to another, so + careful what secrets you store and what software you run while you have + sensitive _env vars_ defined. + +* _reserved variables_: this refers to variables that are read only. Some + reserved variables are dynamic and thus can change their value depending on + contextual circumstances. diff --git a/gen/variables-md-cat.tmpl b/gen/variables-md-cat.tmpl index 02838f4ee..14698ce60 100644 --- a/gen/variables-md-cat.tmpl +++ b/gen/variables-md-cat.tmpl @@ -3,6 +3,13 @@ index: true description: {{ quote .Summary }} category: {{ .Title }} --- -{{ end}}{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} + +{{ end }}# {{ md .Title }}{{ if .Description }} + +{{ md (include .Description) }}{{ end }} + +## Pages + +{{ if .Documents }}{{ range $i,$a := .Documents }}{{ if gt $i 0 }} {{ end }}* [{{ md .Title }}](../{{ md .Hierarchy }}.md): {{ md .Summary }}{{ end }}{{ else }}No pages currently exist for this category.{{ end }} \ No newline at end of file diff --git a/gen/variables-md-doc.tmpl b/gen/variables-md-doc.tmpl index 636247af6..d97054906 100644 --- a/gen/variables-md-doc.tmpl +++ b/gen/variables-md-doc.tmpl @@ -1,6 +1,7 @@ {{ if env "DOCGEN_TARGET=vuepress" }}--- icon: file-code description: {{ quote .Summary }} +category: {{ .CategoryTitle }} {{ if .SubCategories }}tag:{{ range $cat := .SubCategories }} - {{ .Title }}{{ end }}{{ end }} --- @@ -23,11 +24,7 @@ description: {{ quote .Summary }} ## Detail -{{ md (include .Detail) }}{{ end }} - -## Other Reserved Variables - -{{ file "gen/includes/autogenerated.variables.inc.md" }}{{ if .Related }} +{{ md (include .Detail) }}{{ end }}{{ if .Related }} ## See Also diff --git a/gen/variables-vue-cat.tmpl b/gen/variables-vue-cat.tmpl new file mode 100644 index 000000000..c5bc96b12 --- /dev/null +++ b/gen/variables-vue-cat.tmpl @@ -0,0 +1 @@ +{{ vuepressmenu "variables" }} \ No newline at end of file diff --git a/gen/variables/LINES_doc.yaml b/gen/variables/LINES_doc.yaml index 0c97c80a1..753e6f438 100644 --- a/gen/variables/LINES_doc.yaml +++ b/gen/variables/LINES_doc.yaml @@ -1,6 +1,6 @@ - DocumentID: lines Title: >- - `COLUMNS` (int) + `LINES` (int) CategoryID: variables SubCategoryIDs: [ vars.reserved, vars.posix ] Summary: >- diff --git a/gen/vuepress/sidebar.ts b/gen/vuepress/sidebar.ts index a108e0bc4..c4140b03d 100644 --- a/gen/vuepress/sidebar.ts +++ b/gen/vuepress/sidebar.ts @@ -1,6 +1,7 @@ import { sidebar } from "vuepress-theme-hope"; import commandsMenu from "./commands_generated.json" import parserMenu from "./parser_generated.json" +import variablesMenu from "./variables_generated.json" export default sidebar({ "/": [ @@ -47,18 +48,18 @@ export default sidebar({ children: commandsMenu, collapsible: true, }, - { + /*{ text: "Optional Builtins", icon: "cube", prefix: "optional/", children: "structure", collapsible: true, - }, + },*/ { text: "Special Variables", icon: "dollar", - prefix: "variables/", - children: "structure", + prefix: "/", + children: variablesMenu, collapsible: true, }, { diff --git a/gen/vuepress/variables_generated.json b/gen/vuepress/variables_generated.json new file mode 100644 index 000000000..75646f8b2 --- /dev/null +++ b/gen/vuepress/variables_generated.json @@ -0,0 +1,186 @@ +[ + { + "icon": "file-lines", + "index": true, + "link": "/variables/", + "text": "Special Variables" + }, + { + "children": [ + { + "icon": "file-lines", + "link": "variables/pwdhist.html", + "text": "PWDHIST (json)" + }, + { + "icon": "file-lines", + "link": "variables/pwd.html", + "text": "PWD (path)" + }, + { + "icon": "file-lines", + "link": "variables/shell.html", + "text": "SHELL (str)" + } + ], + "collapsible": true, + "icon": "folder-closed", + "text": "Environmental Variables" + }, + { + "children": [ + { + "icon": "file-lines", + "link": "variables/numeric.html", + "text": "Numeric (str)" + }, + { + "icon": "file-lines", + "link": "variables/meta-values.html", + "text": "$., Meta Values (json)" + }, + { + "icon": "file-lines", + "link": "variables/argv.html", + "text": "ARGV (json)" + }, + { + "icon": "file-lines", + "link": "variables/event_return.html", + "text": "EVENT_RETURN (json)" + }, + { + "icon": "file-lines", + "link": "variables/params.html", + "text": "PARAMS (json)" + }, + { + "icon": "file-lines", + "link": "variables/self.html", + "text": "SELF (json)" + } + ], + "collapsible": true, + "icon": "folder-closed", + "text": "Scoped Variables" + }, + { + "children": [ + { + "icon": "file-lines", + "link": "variables/columns.html", + "text": "COLUMNS (int)" + }, + { + "icon": "file-lines", + "link": "variables/home.html", + "text": "HOME (path)" + }, + { + "icon": "file-lines", + "link": "variables/lines.html", + "text": "LINES (int)" + }, + { + "icon": "file-lines", + "link": "variables/logname.html", + "text": "LOGNAME (str)" + }, + { + "icon": "file-lines", + "link": "variables/oldpwd.html", + "text": "OLDPWD (path)" + }, + { + "icon": "file-lines", + "link": "variables/pwd.html", + "text": "PWD (path)" + }, + { + "icon": "file-lines", + "link": "variables/random.html", + "text": "RANDOM (int)" + }, + { + "icon": "file-lines", + "link": "variables/shell.html", + "text": "SHELL (str)" + }, + { + "icon": "file-lines", + "link": "variables/tmpdir.html", + "text": "TMPDIR (path)" + }, + { + "icon": "file-lines", + "link": "variables/user.html", + "text": "USER (str)" + } + ], + "collapsible": true, + "icon": "folder-closed", + "text": "Defined by POSIX" + }, + { + "children": [ + { + "icon": "file-lines", + "link": "variables/numeric.html", + "text": "Numeric (str)" + }, + { + "icon": "file-lines", + "link": "variables/argv.html", + "text": "ARGV (json)" + }, + { + "icon": "file-lines", + "link": "variables/columns.html", + "text": "COLUMNS (int)" + }, + { + "icon": "file-lines", + "link": "variables/hostname.html", + "text": "HOSTNAME (str)" + }, + { + "icon": "file-lines", + "link": "variables/lines.html", + "text": "LINES (int)" + }, + { + "icon": "file-lines", + "link": "variables/murex_argv.html", + "text": "MUREX_ARGV (json)" + }, + { + "icon": "file-lines", + "link": "variables/murex_exe.html", + "text": "MUREX_EXE (path)" + }, + { + "icon": "file-lines", + "link": "variables/params.html", + "text": "PARAMS (json)" + }, + { + "icon": "file-lines", + "link": "variables/random.html", + "text": "RANDOM (int)" + }, + { + "icon": "file-lines", + "link": "variables/self.html", + "text": "SELF (json)" + }, + { + "icon": "file-lines", + "link": "variables/user.html", + "text": "USER (str)" + } + ], + "collapsible": true, + "icon": "folder-closed", + "text": "Reserved Variables" + } +] \ No newline at end of file diff --git a/utils/docgen/api/functions.go b/utils/docgen/api/functions.go index c577d526a..772aad77e 100644 --- a/utils/docgen/api/functions.go +++ b/utils/docgen/api/functions.go @@ -199,7 +199,7 @@ func funcInclude(s string) string { w := bytes.NewBuffer([]byte{}) t := template.Must(template.New(path).Funcs(funcMap).Parse(string(b))) if err := t.Execute(w, nil); err != nil { - panic(err.Error()) + panic(fmt.Sprintf("%s (%s)", err.Error(), path)) } s = strings.Replace(s, match[i][0], w.String(), -1) diff --git a/version.svg b/version.svg index bffa74bda..6a2105656 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4195Version6.3.4195 +Version: 6.3.4213Version6.3.4213 From 1ea3f25f8ae2a5973bf702670caee94fa1fdef16 Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 18 Sep 2024 17:08:25 +0100 Subject: [PATCH 141/142] Add changelog --- app/app.go | 4 +- docs/changelog/README.md | 5 ++ docs/changelog/v6.3.md | 144 ++++++++++++++++++++++++++++++++++++ docs/commands/README.md | 2 +- gen/changelog/v6.3.inc.md | 103 ++++++++++++++++++++++++++ gen/changelog/v6.3_doc.yaml | 25 +++++++ gen/docgen.yaml | 2 +- version.svg | 2 +- 8 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 docs/changelog/v6.3.md create mode 100644 gen/changelog/v6.3.inc.md create mode 100644 gen/changelog/v6.3_doc.yaml diff --git a/app/app.go b/app/app.go index d68088be0..9a27002b4 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4213 + Revision = 4219 Branch = "develop" - BuildDate = "2024-09-18 08:38:26" + BuildDate = "2024-09-18 17:08:29" ) // Copyright is the copyright owner string diff --git a/docs/changelog/README.md b/docs/changelog/README.md index 8fb7a82dc..2a72d476e 100644 --- a/docs/changelog/README.md +++ b/docs/changelog/README.md @@ -4,6 +4,11 @@ Track new features, any breaking changes, and the release history here. ## Articles +### 18.09.2024 - [v6.3](../changelog/v6.3.md) + +This is a massive release ahead of the v7.0. This brings notifications of new deprecations, new builtins, new flags, improved CI/CD flow, and changes to the website. Unfortunately it also carries 3 breaking changes. + + ### 19.07.2024 - [v6.2](../changelog/v6.2.md) Bug fix release diff --git a/docs/changelog/v6.3.md b/docs/changelog/v6.3.md new file mode 100644 index 000000000..222de4d28 --- /dev/null +++ b/docs/changelog/v6.3.md @@ -0,0 +1,144 @@ +# v6.3 + +This is a massive release ahead of the v7.0. This brings notifications of new deprecations, new builtins, new flags, improved CI/CD flow, and changes to the website. Unfortunately it also carries 3 breaking changes. + +## Deprecation Warnings + +Please read out [compatibility commitment](https://murex.rocks/compatibility.html) to understand how features are deprecated. + +* the `?` pipe will be deprecated to make way for a the ternary operator. You can achieve the same result with ` `, eg `command parameters... | next-command ...` + +* the `=` and `let` builtins are now officially deprecated. They've been marked as deprecated in the documentation for a couple of years but you'll now receive a deprecation warning when using them. This warning will not impact any functions that call them (they bypass the stdout and stderr pipes and write directly to your TTY) but it is still recommended that you update any existing code not to use it. The change is very simple, Murex supported expressions as first class primitives, so you can simply drop the `=` and `let` command names from your expressions + +* `tread` has been deprecated for a while due to `read` supporting all `tread`'s use cases. `tread` will officially be removed in the next release + +* `@[]` syntax for ranging has been deprecated for a while. It will be officially removed in the next release in favour of `[]` + +* backtick strings (````) has been an undocumented hack for several years. This release officially sees that hack as deprecated and will be removed in the next release + +* `die` has been deprecated because it just adds a feature for no purpose. It was original borrowed from Perl but realistically you can do the same with `exit 1` so this removal is to bring the language complexity down. + +## Breaking Changes + +* `for` syntax change, switching from parenthesis to curly braces ([discussion](https://github.com/lmorg/murex/discussions/855), [documentation](/docs/commands/for.md)) + +* tilde `~` sigil for home directories will now fail if username is not found ([issue #840](https://github.com/lmorg/murex/issues/840)) + +* support removed for string concatenation via `+=`. This isn't really needed in a shell with infixing support. Removing this feature allows for more common code with other operators and thus fewer bugs + +## Features + +* variables: tilde `~` sigil for home directories will now fail if username is not found ([issue #840](https://github.com/lmorg/murex/issues/840)) + +* new builtin + operator: `~>` to perform immutable merges ([read more](/docs/commands/alter.md)) + +* `count`: added support for `--bytes` and `--runes` ([read more](/docs/commands/count.md)) + +* variables: Lots of new variables added for POSIX compatibility ([issue #873](https://github.com/lmorg/murex/issues/873)) + +* expressions: added support for sub-expressions inside object and array builders ([issue #834](https://github.com/lmorg/murex/issues/834)) + +* core: added support for pseudo-variable pointers via parenthesis ([issue #830](https://github.com/lmorg/murex/issues/830)) + +* expressions: added support for `++` and `--` + +* new builtin: `mjoin` created to join arrays into a string ([read more](/docs/commands/mjoin.md)) + +* new builtin: `list.case` created to alter the text capitalizations on arrays and strings ([read more](/docs/commands/list.case.md)) + +* `regexp`: new flag, `M`, returns matches including first row. This is useful if first row is a headings ([read more](/docs/commands/regexp.md)) + +* `murex`: new flag: `setsid` provides better POSIX support with SID / GPID management. This breaks some of Murex's features so this flag is provided for edge cases where commands capture job control signals + +* integrations: added wrapper for Helix editor to support job control + +* `version`: now includes git's branch name, build date and license. ([read more](/docs/commands/version.md)) + +* core: `go generate` now builds and executes doc gen. As well as updates Murex's version number and build date + +* docgen: added support for sub-categories and Vue menu generation + +* `murex`: new environmental variable, `MUREX_DEBUG`, enables `--debug` flag without having to specify a parameter (eg when using Murex as a shell) + +* integrations: new integration: orbstack. + +* `regexp`: separator can now support separators which are characters larger than 1 byte, ie unicode characters ([read more](/docs/commands/regexp.md)) + +* `murex`: new flag `--execute` -- this behaves like `-c` except that it takes `@ARGV` parameters instead of a pipeline as a single string + +* cicd: added support for Go v1.23 + +* website: significant updates across all documents + +* readline: if terminal is small, the max completion rows is automatically reduced + +## Bug Fixes + +* core: better conversion of numbers from strings ([issue #874](https://github.com/lmorg/murex/issues/874)) + +* `config`: errors generated via dynamic config are now better surfaced + +* `alter`: fixed nil pointer error in `--merge` ([issue #850](https://github.com/lmorg/murex/issues/850)) + +* autocomplete: fixed unit file completions for `systemctl` + +* core: terminal no longer hangs if stdin is a term and `` defined in command + +* autocomplete: removed deprecated `?` operator from `git` + +* expressions: sub-shell scalars inside object builders now return objects instead of strings ([issue #853](https://github.com/lmorg/murex/issues/853)) + +* core: improved expression validator + +* core: statements are no longer forced to be parsed as expressions when the first parameter is `=` ([issue #854](https://github.com/lmorg/murex/issues/854)) + +* readline: ignore panics in VIM keys. In the edge cases where panics are raised, we'd want to exit that function regardless. So handling panics as exceptions is the cleanest way to handle errors ([issue #866](https://github.com/lmorg/murex/issues/866)) + +* integrations: removed deprecated builtin, `=`, from Linux profile + +* core: missing `Release()` after `os.FindProcess()` + +* readline: preview displays error if terminal too small ([issue #868](https://github.com/lmorg/murex/issues/868)) + +## Special Thanks + +Thank yous for this release goes to [tiymat](https://github.com/tiymat), [atagen](https://github.com/atagen) and [orefalo](https://github.com/orefalo) for your testing and feedback. Also thank you to everyone in the [discussions group](https://github.com/lmorg/murex/discussions) and all who raise bug reports. + +You rock! + +
      + +Published: 18.09.2024 at 20:00 + +## See Also + +* [Alter Data Structure (`alter` / `~>`)](../commands/alter.md): + Change a value within a structured data-type and pass that change along the pipeline without altering the original source input +* [Change Text Case (`list.case`)](../commands/list.case.md): + Changes the character case of a string or all elements in an array +* [Count (`count`)](../commands/count.md): + Count items in a map, list or array +* [Expressions (`expr`)](../commands/expr.md): + Expressions: mathematical, string comparisons, logical operators +* [For Loop (`for`)](../commands/for.md): + A more familiar iteration loop to existing developers +* [How To Contribute](../Murex/CONTRIBUTING.md): + Murex is community project. We gratefully accept contributions +* [Integrations](../user-guide/integrations.md): + Default integrations shipped with Murex +* [Join Array To String (`mjoin`)](../commands/mjoin.md): + Joins a list or array into a single string +* [Murex Version (`version`)](../commands/version.md): + Get Murex version +* [Operators And Tokens](../user-guide/operators-and-tokens.md): + All supported operators and tokens +* [Regex Operations (`regexp`)](../commands/regexp.md): + Regexp tools for arrays / lists of strings +* [Shell Configuration And Settings (`config`)](../commands/config.md): + Query or define Murex runtime settings +* [`~` Home Sigil](../parser/tilde.md): + Home directory path variable + +
      + +This document was generated from [gen/changelog/v6.3_doc.yaml](https://github.com/lmorg/murex/blob/master/gen/changelog/v6.3_doc.yaml). \ No newline at end of file diff --git a/docs/commands/README.md b/docs/commands/README.md index 9fba1b304..30d32b7b6 100644 --- a/docs/commands/README.md +++ b/docs/commands/README.md @@ -158,7 +158,7 @@ Commands that operate against a list or array. ### String Manipulation Commands for working with strings. -> All list based tools also work with strings. +> Several list based tools will also work with strings. Those that can, are included in this sub-section. * [Change Text Case (`list.case`)](../commands/list.case.md): Changes the character case of a string or all elements in an array diff --git a/gen/changelog/v6.3.inc.md b/gen/changelog/v6.3.inc.md new file mode 100644 index 000000000..857415fc8 --- /dev/null +++ b/gen/changelog/v6.3.inc.md @@ -0,0 +1,103 @@ +## Deprecation Warnings + +Please read out [compatibility commitment](https://murex.rocks/compatibility.html) to understand how features are deprecated. + +* the `?` pipe will be deprecated to make way for a the ternary operator. You can achieve the same result with ` `, eg `command parameters... | next-command ...` + +* the `=` and `let` builtins are now officially deprecated. They've been marked as deprecated in the documentation for a couple of years but you'll now receive a deprecation warning when using them. This warning will not impact any functions that call them (they bypass the stdout and stderr pipes and write directly to your TTY) but it is still recommended that you update any existing code not to use it. The change is very simple, Murex supported expressions as first class primitives, so you can simply drop the `=` and `let` command names from your expressions + +* `tread` has been deprecated for a while due to `read` supporting all `tread`'s use cases. `tread` will officially be removed in the next release + +* `@[]` syntax for ranging has been deprecated for a while. It will be officially removed in the next release in favour of `[]` + +* backtick strings (````) has been an undocumented hack for several years. This release officially sees that hack as deprecated and will be removed in the next release + +* `die` has been deprecated because it just adds a feature for no purpose. It was original borrowed from Perl but realistically you can do the same with `exit 1` so this removal is to bring the language complexity down. + +## Breaking Changes + +* `for` syntax change, switching from parenthesis to curly braces ([discussion](https://github.com/lmorg/murex/discussions/855), {{link "documentation" "for"}}) + +* tilde `~` sigil for home directories will now fail if username is not found ([issue #840](https://github.com/lmorg/murex/issues/840)) + +* support removed for string concatenation via `+=`. This isn't really needed in a shell with infixing support. Removing this feature allows for more common code with other operators and thus fewer bugs + +## Features + +* variables: tilde `~` sigil for home directories will now fail if username is not found ([issue #840](https://github.com/lmorg/murex/issues/840)) + +* new builtin + operator: `~>` to perform immutable merges ({{link "read more" "alter"}}) + +* `count`: added support for `--bytes` and `--runes` ({{link "read more" "count"}}) + +* variables: Lots of new variables added for POSIX compatibility ([issue #873](https://github.com/lmorg/murex/issues/873)) + +* expressions: added support for sub-expressions inside object and array builders ([issue #834](https://github.com/lmorg/murex/issues/834)) + +* core: added support for pseudo-variable pointers via parenthesis ([issue #830](https://github.com/lmorg/murex/issues/830)) + +* expressions: added support for `++` and `--` + +* new builtin: `mjoin` created to join arrays into a string ({{link "read more" "mjoin"}}) + +* new builtin: `list.case` created to alter the text capitalizations on arrays and strings ({{link "read more" "list.case"}}) + +* `regexp`: new flag, `M`, returns matches including first row. This is useful if first row is a headings ({{link "read more" "regexp"}}) + +* `murex`: new flag: `setsid` provides better POSIX support with SID / GPID management. This breaks some of Murex's features so this flag is provided for edge cases where commands capture job control signals + +* integrations: added wrapper for Helix editor to support job control + +* `version`: now includes git's branch name, build date and license. ({{link "read more" "version"}}) + +* core: `go generate` now builds and executes doc gen. As well as updates Murex's version number and build date + +* docgen: added support for sub-categories and Vue menu generation + +* `murex`: new environmental variable, `MUREX_DEBUG`, enables `--debug` flag without having to specify a parameter (eg when using Murex as a shell) + +* integrations: new integration: orbstack. + +* `regexp`: separator can now support separators which are characters larger than 1 byte, ie unicode characters ({{link "read more" "regexp"}}) + +* `murex`: new flag `--execute` -- this behaves like `-c` except that it takes `@ARGV` parameters instead of a pipeline as a single string + +* cicd: added support for Go v1.23 + +* website: significant updates across all documents + +* readline: if terminal is small, the max completion rows is automatically reduced + +## Bug Fixes + +* core: better conversion of numbers from strings ([issue #874](https://github.com/lmorg/murex/issues/874)) + +* `config`: errors generated via dynamic config are now better surfaced + +* `alter`: fixed nil pointer error in `--merge` ([issue #850](https://github.com/lmorg/murex/issues/850)) + +* autocomplete: fixed unit file completions for `systemctl` + +* core: terminal no longer hangs if stdin is a term and `` defined in command + +* autocomplete: removed deprecated `?` operator from `git` + +* expressions: sub-shell scalars inside object builders now return objects instead of strings ([issue #853](https://github.com/lmorg/murex/issues/853)) + +* core: improved expression validator + +* core: statements are no longer forced to be parsed as expressions when the first parameter is `=` ([issue #854](https://github.com/lmorg/murex/issues/854)) + +* readline: ignore panics in VIM keys. In the edge cases where panics are raised, we'd want to exit that function regardless. So handling panics as exceptions is the cleanest way to handle errors ([issue #866](https://github.com/lmorg/murex/issues/866)) + +* integrations: removed deprecated builtin, `=`, from Linux profile + +* core: missing `Release()` after `os.FindProcess()` + +* readline: preview displays error if terminal too small ([issue #868](https://github.com/lmorg/murex/issues/868)) + +## Special Thanks + +Thank yous for this release goes to [tiymat](https://github.com/tiymat), [atagen](https://github.com/atagen) and [orefalo](https://github.com/orefalo) for your testing and feedback. Also thank you to everyone in the [discussions group](https://github.com/lmorg/murex/discussions) and all who raise bug reports. + +You rock! diff --git a/gen/changelog/v6.3_doc.yaml b/gen/changelog/v6.3_doc.yaml new file mode 100644 index 000000000..eccd0ba9f --- /dev/null +++ b/gen/changelog/v6.3_doc.yaml @@ -0,0 +1,25 @@ +- DocumentID: v6.3 + Title: >- + v6.3 + CategoryID: changelog + DateTime: 2024-09-18 20:00 + Summary: >- + This is a massive release ahead of the v7.0. This brings notifications of + new deprecations, new builtins, new flags, improved CI/CD flow, and changes + to the website. Unfortunately it also carries 3 breaking changes. + Description: |- + {{ include "gen/changelog/v6.3.inc.md" }} + Related: + - CONTRIBUTING + - expr + - operators-and-tokens + - for + - tilde + - alter + - count + - mjoin + - list.case + - regexp + - version + - config + - integrations diff --git a/gen/docgen.yaml b/gen/docgen.yaml index 4561f9c61..78a44afbf 100644 --- a/gen/docgen.yaml +++ b/gen/docgen.yaml @@ -45,7 +45,7 @@ Categories: VueIcon: quote-left Description: |- Commands for working with strings. - > All list based tools also work with strings. + > Several list based tools will also work with strings. Those that can, are included in this sub-section. - ID: commands.num Title: Numeric / Math Tools VueIcon: square-root-variable diff --git a/version.svg b/version.svg index 6a2105656..d136385dc 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4213Version6.3.4213 +Version: 6.3.4219Version6.3.4219 From 5f826a3418ad48fc8476db8191d8d78390db74aa Mon Sep 17 00:00:00 2001 From: Laurence Morgan Date: Wed, 18 Sep 2024 17:10:00 +0100 Subject: [PATCH 142/142] #868 readline: display 'terminal too small error' in preview --- app/app.go | 4 ++-- builtins/docs/summaries.go | 2 ++ utils/readline/preview.go | 26 ++++++++++++++++++++++++-- utils/readline/tab.go | 3 ++- version.svg | 2 +- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/app/app.go b/app/app.go index 9a27002b4..93abc6c21 100644 --- a/app/app.go +++ b/app/app.go @@ -16,9 +16,9 @@ const Name = "murex" const ( Major = 6 Minor = 3 - Revision = 4219 + Revision = 4221 Branch = "develop" - BuildDate = "2024-09-18 17:08:29" + BuildDate = "2024-09-18 21:37:02" ) // Copyright is the copyright owner string diff --git a/builtins/docs/summaries.go b/builtins/docs/summaries.go index 832ba6359..dce3019c3 100644 --- a/builtins/docs/summaries.go +++ b/builtins/docs/summaries.go @@ -418,6 +418,7 @@ func init() { "changelog/v6.0": "Despite this being a new major version release, it is a vary minor update. Aside from a handful of bugfixes, the most significant change is notice of deprecation for `=`, `let`, and `?`.", "changelog/v6.1": "This release sees a massive jump in event-driven capabilities as well as several new features and bug fixes.", "changelog/v6.2": "Bug fix release", + "changelog/v6.3": "This is a massive release ahead of the v7.0. This brings notifications of new deprecations, new builtins, new flags, improved CI/CD flow, and changes to the website. Unfortunately it also carries 3 breaking changes.", } Synonym = map[string]string{ @@ -1070,5 +1071,6 @@ func init() { "changelog/v6.0": "changelog/v6.0", "changelog/v6.1": "changelog/v6.1", "changelog/v6.2": "changelog/v6.2", + "changelog/v6.3": "changelog/v6.3", } } diff --git a/utils/readline/preview.go b/utils/readline/preview.go index f8e583dfa..368842108 100644 --- a/utils/readline/preview.go +++ b/utils/readline/preview.go @@ -107,6 +107,8 @@ func (rl *Instance) getPreviewXY() (*PreviewSizeT, error) { width = 80 } + rl.previewAutocompleteHeight(height) + preview, forward := getPreviewWidth(width) size := &PreviewSizeT{ Height: height - rl.MaxTabCompleterRows - 10, // hintText, multi-line prompts, etc @@ -117,6 +119,24 @@ func (rl *Instance) getPreviewXY() (*PreviewSizeT, error) { return size, nil } +func (rl *Instance) previewAutocompleteHeight(height int) { + switch { + case height < 40: + rl.MaxTabCompleterRows = noLargerThan(rl.MaxTabCompleterRows, 4) + case height < 30: + rl.MaxTabCompleterRows = noLargerThan(rl.MaxTabCompleterRows, 3) + case height < 20: + rl.MaxTabCompleterRows = noLargerThan(rl.MaxTabCompleterRows, 2) + } +} + +func noLargerThan(src, max int) int { + if src > max { + return max + } + return src +} + func (rl *Instance) writePreviewStr() string { if rl.previewMode == previewModeClosed { rl.previewCache = nil @@ -144,9 +164,9 @@ func (rl *Instance) writePreviewStr() string { } size, err := rl.getPreviewXY() - if err != nil || size.Height < 8 || size.Width < 10 { + if err != nil || size.Height < 4 || size.Width < 10 { rl.previewCache = nil - return "" + return previewTerminalTooSmall } item := rl.previewItem @@ -158,6 +178,8 @@ func (rl *Instance) writePreviewStr() string { return "" } +var previewTerminalTooSmall = fmt.Sprintf("%s%sTerminal too small to display preview%s", curPosSave, curHome, curPosRestore) + const ( curHome = "\x1b[H" curPosSave = "\x1b[s" diff --git a/utils/readline/tab.go b/utils/readline/tab.go index 7d96770ec..c6878d33c 100644 --- a/utils/readline/tab.go +++ b/utils/readline/tab.go @@ -71,13 +71,14 @@ func (rl *Instance) autocompleteHeightAdjust() { height = 25 } + rl.previewAutocompleteHeight(height) + switch { case height <= 4: rl.MaxTabCompleterRows = 1 case height-4 <= rl.MaxTabCompleterRows: rl.MaxTabCompleterRows = height - 4 } - } func (rl *Instance) moveTabCompletionHighlight(x, y int) { diff --git a/version.svg b/version.svg index d136385dc..14e08b783 100644 --- a/version.svg +++ b/version.svg @@ -1 +1 @@ -Version: 6.3.4219Version6.3.4219 +Version: 6.3.4221Version6.3.4221