github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/ranges/ranges.go (about) 1 package ranges 2 3 import ( 4 "errors" 5 "fmt" 6 "regexp" 7 "strings" 8 9 "github.com/lmorg/murex/debug" 10 "github.com/lmorg/murex/lang" 11 "github.com/lmorg/murex/lang/types" 12 ) 13 14 func init() { 15 lang.DefineMethod("@[", CmdRange, types.ReadArray, types.WriteArray) 16 } 17 18 const usage = "\nUsage: [start..end] / [start..end]se\n(start or end can be omitted)" 19 20 // if additional ranges are added here, they will also need to be added to 21 // /home/lau/dev/go/src/github.com/lmorg/murex/lang/parameters.go 22 var RxSplitRange = regexp.MustCompile(`^\s*(.*?)\s*\.\.\s*(.*?)\s*\]([bt8ernsiu]*)\s*$`) 23 24 func CmdRange(p *lang.Process) (err error) { 25 dt := p.Stdin.GetDataType() 26 p.Stdout.SetDataType(dt) 27 28 if err := p.ErrIfNotAMethod(); err != nil { 29 return err 30 } 31 32 s := p.Parameters.StringAll() 33 34 split := RxSplitRange.FindStringSubmatch(s) 35 if len(split) != 4 { 36 err = indexAndExpand(p, dt) 37 if err != nil { 38 return fmt.Errorf("not a valid range: %v.%s\nnor a valid index: %v", split, usage, err) 39 } 40 return nil 41 } 42 43 r := &rangeParameters{ 44 Start: split[1], 45 End: split[2], 46 } 47 48 if strings.Contains(split[3], "e") { 49 r.Exclude = true 50 split[3] = strings.Replace(split[3], "e", "", -1) 51 } 52 53 if strings.Contains(split[3], "8") { 54 r.RmBS = true 55 split[3] = strings.Replace(split[3], "8", "", -1) 56 } 57 58 if strings.Contains(split[3], "b") { 59 r.StripBlank = true 60 split[3] = strings.Replace(split[3], "b", "", -1) 61 } 62 63 if strings.Contains(split[3], "t") { 64 r.TrimSpace = true 65 split[3] = strings.Replace(split[3], "t", "", -1) 66 } 67 68 if len(split[3]) > 1 { 69 return fmt.Errorf("invalid syntax: you cannot combine the following flags: %s.%s", split[3], usage) 70 } 71 72 switch split[3] { 73 case "r": 74 err = newRegexp(r) 75 76 case "s": 77 err = newString(r) 78 79 case "n": 80 err = newNumber(r) 81 82 case "i": 83 err = newIndex(r) 84 85 default: 86 if p.Name.String() == "@[" { 87 err = newNumber(r) 88 } else { 89 err = newIndex(r) 90 } 91 } 92 93 if err != nil { 94 return err 95 } 96 97 return readArray(p, r, dt) 98 } 99 100 func indexAndExpand(p *lang.Process, dt string) (err error) { 101 if !debug.Enabled { 102 defer func() { 103 if r := recover(); r != nil { 104 err = fmt.Errorf("panic caught, please report this to https://github.com/lmorg/murex/issues : %s", r) 105 } 106 }() 107 } 108 109 // We will set data type from the index function but fallback to this just 110 // in case it's forgotten about in the index function. This is safe because 111 // SetDataType() cannot overwrite the data type once set. 112 defer p.Stdout.SetDataType(dt) 113 114 params := p.Parameters.StringArray() 115 l := len(params) - 1 116 if l < 0 { 117 return errors.New("missing parameters. Please select 1 or more indexes") 118 } 119 120 switch { 121 case params[l] == "]": 122 params = params[:l] 123 case strings.HasSuffix(params[l], "]"): 124 params[l] = params[l][:len(params[l])-1] 125 default: 126 return errors.New("missing closing bracket, ` ]`") 127 } 128 129 f := lang.ReadIndexes[dt] 130 if f == nil { 131 return errors.New("i don't know how to get an index from this data type: `" + dt + "`") 132 } 133 134 silent, err := p.Config.Get("index", "silent", types.Boolean) 135 if err != nil { 136 silent = false 137 } 138 139 err = f(p, params) 140 if silent.(bool) { 141 return nil 142 } 143 144 return err 145 }