From 1558f26c51e7cac196f962471b6a7ab361a33bd1 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Tue, 15 Feb 2022 18:44:25 -0500 Subject: [PATCH 1/2] Add strings.remove{pre,suf}fix methods --- doc/spec.md | 28 ++++++++++++++++++++++++++++ starlark/library.go | 18 ++++++++++++++++++ starlark/testdata/string.star | 21 +++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/doc/spec.md b/doc/spec.md index 07285894..37896146 100644 --- a/doc/spec.md +++ b/doc/spec.md @@ -175,6 +175,8 @@ reproducibility is paramount, such as build tools. * [string·lower](#string·lower) * [string·lstrip](#string·lstrip) * [string·partition](#string·partition) + * [string·removeprefix](#string·removeprefix) + * [string·removesuffix](#string·removesuffix) * [string·replace](#string·replace) * [string·rfind](#string·rfind) * [string·rindex](#string·rindex) @@ -680,6 +682,8 @@ Strings have several built-in methods: * [`lstrip`](#string·lstrip) * [`partition`](#string·partition) * [`replace`](#string·replace) +* [`removeprefix`](#string·removeprefix) +* [`removesuffix`](#string·removesuffix) * [`rfind`](#string·rfind) * [`rindex`](#string·rindex) * [`rpartition`](#string·rpartition) @@ -4026,6 +4030,30 @@ If S does not contain `x`, `partition` returns `(S, "", "")`. "one/two/three".partition("/") # ("one", "/", "two/three") ``` + +### string·removeprefix + +`S.removeprefix(prefix)` returns a copy of string S with the prefix `prefix` +removed if S starts with `prefix`, otherwise it returns S. + +```python +"banana".removeprefix("ban") # "ana" +"banana".removeprefix("foo") # "banana" +"foofoobar".removeprefix("foo") # "foobar" +``` + + +### string·removesuffix + +`S.removesuffix(suffix)` returns a copy of string S with the suffix `suffix` +removed if S ends with `suffix`, otherwise it returns S. + +```python +"banana".removesuffix("nana") # "ba" +"banana".removesuffix("foo") # "banana" +"banana".removesuffix("na") # "bana" +``` + ### string·replace diff --git a/starlark/library.go b/starlark/library.go index cb2c8207..d7d05365 100644 --- a/starlark/library.go +++ b/starlark/library.go @@ -123,6 +123,8 @@ var ( "lower": NewBuiltin("lower", string_lower), "lstrip": NewBuiltin("lstrip", string_strip), // sic "partition": NewBuiltin("partition", string_partition), + "removeprefix": NewBuiltin("removeprefix", string_removefix), + "removesuffix": NewBuiltin("removesuffix", string_removefix), "replace": NewBuiltin("replace", string_replace), "rfind": NewBuiltin("rfind", string_rfind), "rindex": NewBuiltin("rindex", string_rindex), @@ -1889,6 +1891,22 @@ func string_partition(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, return tuple, nil } +// https://github.com/google/starlark-go/blob/master/doc/spec.md#string·removeprefix +// https://github.com/google/starlark-go/blob/master/doc/spec.md#string·removesuffix +func string_removefix(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { + recv := string(b.Receiver().(String)) + var fix string + if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &fix); err != nil { + return nil, err + } + if b.name[6] == 'p' { + recv = strings.TrimPrefix(recv, fix) + } else { + recv = strings.TrimSuffix(recv, fix) + } + return String(recv), nil +} + // https://github.com/google/starlark-go/blob/master/doc/spec.md#string·replace func string_replace(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, error) { recv := string(b.Receiver().(String)) diff --git a/starlark/testdata/string.star b/starlark/testdata/string.star index b317d1af..1a38d622 100644 --- a/starlark/testdata/string.star +++ b/starlark/testdata/string.star @@ -470,3 +470,24 @@ assert.true(not "DŽenan LJubović".istitle()) assert.fails(lambda: "".starts_with, "no .starts_with field.*did you mean .startswith") assert.fails(lambda: "".StartsWith, "no .StartsWith field.*did you mean .startswith") assert.fails(lambda: "".fin, "no .fin field.*.did you mean .find") + + +# removesuffix +assert.eq("Apricot".removesuffix("cot"), "Apri") +assert.eq("Apricot".removesuffix("Cot"), "Apricot") +assert.eq("Apricot".removesuffix("t"), "Aprico") +assert.eq("a".removesuffix(""), "a") +assert.eq("".removesuffix(""), "") +assert.eq("".removesuffix("a"), "") +assert.eq("Apricot".removesuffix("co"), "Apricot") +assert.eq("Apricotcot".removesuffix("cot"), "Apricot") + +# removeprefix +assert.eq("Apricot".removeprefix("Apr"), "icot") +assert.eq("Apricot".removeprefix("apr"), "Apricot") +assert.eq("Apricot".removeprefix("A"), "pricot") +assert.eq("a".removeprefix(""), "a") +assert.eq("".removeprefix(""), "") +assert.eq("".removeprefix("a"), "") +assert.eq("Apricot".removeprefix("pr"), "Apricot") +assert.eq("AprApricot".removeprefix("Apr"), "Apricot") \ No newline at end of file From 6753612a56d870613b06329f4eaa2263f27f4dd0 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Thu, 17 Feb 2022 09:59:53 -0500 Subject: [PATCH 2/2] Avoid constant 6 --- starlark/library.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starlark/library.go b/starlark/library.go index d7d05365..1c801be6 100644 --- a/starlark/library.go +++ b/starlark/library.go @@ -1899,7 +1899,7 @@ func string_removefix(_ *Thread, b *Builtin, args Tuple, kwargs []Tuple) (Value, if err := UnpackPositionalArgs(b.Name(), args, kwargs, 1, &fix); err != nil { return nil, err } - if b.name[6] == 'p' { + if b.name[len("remove")] == 'p' { recv = strings.TrimPrefix(recv, fix) } else { recv = strings.TrimSuffix(recv, fix)