string: add `strip_margin`

pull/4028/head
Major Taylor 2020-03-15 00:46:12 -04:00 committed by GitHub
parent 3e05939b65
commit 2d5c7c8e93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 137 additions and 0 deletions

View File

@ -1267,3 +1267,64 @@ pub fn (s string) repeat(count int) string {
ret[s.len * count] = 0
return string(ret)
}
// Allows multi-line strings to be formatted in a way that removes white-space
// before a delimeter. by default `|` is used.
// Note: the delimiter has to be a byte at this time. That means surrounding
// the value in ``.
//
// Example:
// st := 'Hello there,
// |this is a string,
// | Everything before the first | is removed'.strip_margin()
// Returns:
// Hello there,
// this is a string,
// Everything before the first | is removed
pub fn (s string) strip_margin(del ...byte) string {
mut sep := `|`
if del.len >= 1 {
// This is a workaround. We can't directly index a var_args array.
// Only care about the first one, ignore the rest if more
for d in del {
// The delimiter is not allowed to be white-space. Will use default
if !d.is_space() {
sep = d
} else {
eprintln("Warning: `strip_margin` cannot use white-space as a delimiter")
eprintln(" Defaulting to `|`")
}
break
}
if del.len == 1 {
eprintln("Warning: `strip_margin` only uses the first argument given")
}
}
// don't know how much space the resulting string will be, but the max it
// can be is this big
mut ret := malloc(s.len + 1)
mut count := 0
for i := 0; i < s.len; i++ {
if (s[i] in [`\n`, `\r`]) {
$if windows {
ret[count] = `\r`
ret[count+1] = `\n`
count += 2
} $else {
ret[count] = s[i]
count++
}
for s[i] != sep {
i++
if i >= s.len {
break
}
}
} else {
ret[count] = s[i]
count++
}
}
ret[count] = 0
return string(ret)
}

View File

@ -695,3 +695,79 @@ fn test_split_into_lines() {
assert line == line_content
}
}
fn test_strip_margins() {
no_tabs := 'Hello there
This is a string
With multiple lines'
no_tabs_stripped := 'Hello there
|This is a string
|With multiple lines'.strip_margin()
assert no_tabs == no_tabs_stripped
text_before := 'There is text
before the delimiter
that should be removed as well'
text_before_stripped := 'There is text
f lasj asldfj j lksjdf |before the delimiter
Which is removed hello |that should be removed as well'.strip_margin()
assert text_before_stripped == text_before
tabs := ' Tab
spaces
another tab'
tabs_stripped := ' Tab
| spaces
| another tab'.strip_margin()
assert tabs == tabs_stripped
alternate_delimiter := 'This has a different delim,
but that is ok
because everything works'
alternate_delimiter_stripped := 'This has a different delim,
#but that is ok
# because everything works'.strip_margin(`#`)
assert alternate_delimiter_stripped == alternate_delimiter
delim_after_first_instance := 'The delimiter used
only matters the |||| First time it is seen
not any | other | times'
delim_after_first_instance_stripped := 'The delimiter used
|only matters the |||| First time it is seen
|not any | other | times'.strip_margin()
assert delim_after_first_instance_stripped == delim_after_first_instance
uneven_delims := 'It doesn\'t matter if the delims are uneven,
The text will still be delimited correctly.
Maybe not everything needs 3 lines?
Let us go for 4 then'
uneven_delims_stripped := 'It doesn\'t matter if the delims are uneven,
|The text will still be delimited correctly.
|Maybe not everything needs 3 lines?
|Let us go for 4 then'.strip_margin()
assert uneven_delims_stripped == uneven_delims
multi_blank_lines := 'Multiple blank lines will be removed.
I actually consider this a feature.'
multi_blank_lines_stripped := 'Multiple blank lines will be removed.
| I actually consider this a feature.'.strip_margin()
assert multi_blank_lines == multi_blank_lines_stripped
end_with_newline := 'This line will end with a newline
Something cool or something.
'
end_with_newline_stripped := 'This line will end with a newline
|Something cool or something.
'.strip_margin()
assert end_with_newline_stripped == end_with_newline
space_delimiter := 'Using a white-space char will
revert back to default behavior.'
space_delimiter_stripped := 'Using a white-space char will
|revert back to default behavior.'.strip_margin(`\n`)
assert space_delimiter == space_delimiter_stripped
}