diff --git a/docs/markdown/snippets/add_str_splitlines_method.md b/docs/markdown/snippets/add_str_splitlines_method.md new file mode 100644 index 000000000..6787f179b --- /dev/null +++ b/docs/markdown/snippets/add_str_splitlines_method.md @@ -0,0 +1,3 @@ +## Added str.splitlines method + +[[str.splitlines]] can now be used to split a string into an array of lines. diff --git a/docs/yaml/elementary/str.yml b/docs/yaml/elementary/str.yml index 00587cbd6..dca6382a2 100644 --- a/docs/yaml/elementary/str.yml +++ b/docs/yaml/elementary/str.yml @@ -204,6 +204,28 @@ methods: type: str description: Specifies the character / substring where to split the string. +- name: splitlines + returns: list[str] + since: 1.2.0 + description: | + Splits the string into an array of lines. + Unlike .split('\n'), the empty string produced an empty array, + and if the string ends in a newline, splitlines() doesn't split + on that last newline. + '\n', '\r' and '\r\n' are all considered newlines. + + example: | + ```meson + output = 'hello\nworld\n'.splitlines() + # Output value is ['hello', 'world'] + output = ''.splitlines() + # Output value is [] + fs = import('fs') + paths = fs.read('my_paths.list').splitlines() + # paths is now the paths listed in 'my_paths.list', or an empty list + # if 'my_paths.list' is empty + ``` + # str.join() - name: join returns: str diff --git a/mesonbuild/interpreter/primitives/string.py b/mesonbuild/interpreter/primitives/string.py index d9f6a0664..d4daab9f0 100644 --- a/mesonbuild/interpreter/primitives/string.py +++ b/mesonbuild/interpreter/primitives/string.py @@ -38,6 +38,7 @@ class StringHolder(ObjectHolder[str]): 'join': self.join_method, 'replace': self.replace_method, 'split': self.split_method, + 'splitlines': self.splitlines_method, 'strip': self.strip_method, 'substring': self.substring_method, 'to_int': self.to_int_method, @@ -104,6 +105,12 @@ class StringHolder(ObjectHolder[str]): return re.sub(r'@(\d+)@', arg_replace, self.held_object) + @noKwargs + @noPosargs + @FeatureNew('str.splitlines', '1.2.0') + def splitlines_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> T.List[str]: + return self.held_object.splitlines() + @noKwargs @typed_pos_args('str.join', varargs=str) def join_method(self, args: T.Tuple[T.List[str]], kwargs: TYPE_kwargs) -> str: diff --git a/test cases/common/35 string operations/meson.build b/test cases/common/35 string operations/meson.build index 116fe0b2b..27cc0d8c8 100644 --- a/test cases/common/35 string operations/meson.build +++ b/test cases/common/35 string operations/meson.build @@ -125,3 +125,15 @@ assert(mysubstring.substring(10, -25) == '', 'substring is broken') assert(mysubstring.substring(-4, 2) == '', 'substring is broken') assert(mysubstring.substring(10, 9) == '', 'substring is broken') assert(mysubstring.substring(8, 10) == 'z', 'substring is broken') + +# str.splitlines() +assert('foo\nbar\nbaz'.splitlines() == ['foo', 'bar', 'baz'], 'splitlines is broken') +assert(''.splitlines() == [], 'splitlines with empty string is broken') +assert('foo\rbar\nbaz\n'.splitlines() == ['foo', 'bar', 'baz'], 'splitlines trailing newline is broken') +assert('hello\r\nworld'.splitlines() == ['hello', 'world']) +assert( + ' leading ws\nand trailing\t'.splitlines() == [' leading ws', 'and trailing\t'], + 'splitlines leading/trailing whitespace is broken', +) +assert('\n\r\n\r'.splitlines() == ['', '', ''], 'splitlines is broken') +assert('foo'.splitlines() == ['foo'], 'splitlines is broken')