|
6 | 6 | "fmt" |
7 | 7 | "io" |
8 | 8 | "reflect" |
| 9 | + "regexp" |
9 | 10 | "strings" |
10 | 11 | "time" |
11 | 12 | ) |
@@ -297,3 +298,77 @@ func vibeValueToJSONValue(val Value, state *jsonStringifyState) (any, error) { |
297 | 298 | return nil, fmt.Errorf("JSON.stringify unsupported value type %s", val.Kind()) |
298 | 299 | } |
299 | 300 | } |
| 301 | + |
| 302 | +func builtinRegexMatch(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) { |
| 303 | + if len(args) != 2 { |
| 304 | + return NewNil(), fmt.Errorf("Regex.match expects pattern and text") |
| 305 | + } |
| 306 | + if len(kwargs) > 0 { |
| 307 | + return NewNil(), fmt.Errorf("Regex.match does not accept keyword arguments") |
| 308 | + } |
| 309 | + if !block.IsNil() { |
| 310 | + return NewNil(), fmt.Errorf("Regex.match does not accept blocks") |
| 311 | + } |
| 312 | + if args[0].Kind() != KindString || args[1].Kind() != KindString { |
| 313 | + return NewNil(), fmt.Errorf("Regex.match expects string pattern and text") |
| 314 | + } |
| 315 | + |
| 316 | + re, err := regexp.Compile(args[0].String()) |
| 317 | + if err != nil { |
| 318 | + return NewNil(), fmt.Errorf("Regex.match invalid regex: %v", err) |
| 319 | + } |
| 320 | + match := re.FindString(args[1].String()) |
| 321 | + if match == "" { |
| 322 | + return NewNil(), nil |
| 323 | + } |
| 324 | + return NewString(match), nil |
| 325 | +} |
| 326 | + |
| 327 | +func builtinRegexReplace(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) { |
| 328 | + return builtinRegexReplaceInternal(args, kwargs, block, false) |
| 329 | +} |
| 330 | + |
| 331 | +func builtinRegexReplaceAll(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) { |
| 332 | + return builtinRegexReplaceInternal(args, kwargs, block, true) |
| 333 | +} |
| 334 | + |
| 335 | +func builtinRegexReplaceInternal(args []Value, kwargs map[string]Value, block Value, replaceAll bool) (Value, error) { |
| 336 | + method := "Regex.replace" |
| 337 | + if replaceAll { |
| 338 | + method = "Regex.replace_all" |
| 339 | + } |
| 340 | + |
| 341 | + if len(args) != 3 { |
| 342 | + return NewNil(), fmt.Errorf("%s expects text, pattern, replacement", method) |
| 343 | + } |
| 344 | + if len(kwargs) > 0 { |
| 345 | + return NewNil(), fmt.Errorf("%s does not accept keyword arguments", method) |
| 346 | + } |
| 347 | + if !block.IsNil() { |
| 348 | + return NewNil(), fmt.Errorf("%s does not accept blocks", method) |
| 349 | + } |
| 350 | + if args[0].Kind() != KindString || args[1].Kind() != KindString || args[2].Kind() != KindString { |
| 351 | + return NewNil(), fmt.Errorf("%s expects string text, pattern, replacement", method) |
| 352 | + } |
| 353 | + |
| 354 | + text := args[0].String() |
| 355 | + pattern := args[1].String() |
| 356 | + replacement := args[2].String() |
| 357 | + |
| 358 | + re, err := regexp.Compile(pattern) |
| 359 | + if err != nil { |
| 360 | + return NewNil(), fmt.Errorf("%s invalid regex: %v", method, err) |
| 361 | + } |
| 362 | + |
| 363 | + if replaceAll { |
| 364 | + return NewString(re.ReplaceAllString(text, replacement)), nil |
| 365 | + } |
| 366 | + |
| 367 | + loc := re.FindStringIndex(text) |
| 368 | + if loc == nil { |
| 369 | + return NewString(text), nil |
| 370 | + } |
| 371 | + segment := text[loc[0]:loc[1]] |
| 372 | + replaced := re.ReplaceAllString(segment, replacement) |
| 373 | + return NewString(text[:loc[0]] + replaced + text[loc[1]:]), nil |
| 374 | +} |
0 commit comments