mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
builtin: add string.trim_indent()
` method (#17099)
This commit is contained in:
parent
5aad0db0f7
commit
17d65db828
vlib/builtin
@ -1951,6 +1951,8 @@ pub fn (s string) fields() []string {
|
||||
// Note: the delimiter has to be a byte at this time. That means surrounding
|
||||
// the value in ``.
|
||||
//
|
||||
// See also: string.trim_indent()
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// st := 'Hello there,
|
||||
@ -2011,6 +2013,99 @@ pub fn (s string) strip_margin_custom(del u8) string {
|
||||
}
|
||||
}
|
||||
|
||||
// trim_indent detects a common minimal indent of all the input lines,
|
||||
// removes it from every line and also removes the first and the last
|
||||
// lines if they are blank (notice difference blank vs empty).
|
||||
//
|
||||
// Note that blank lines do not affect the detected indent level.
|
||||
//
|
||||
// In case if there are non-blank lines with no leading whitespace characters
|
||||
// (no indent at all) then the common indent is 0, and therefore this function
|
||||
// doesn't change the indentation.
|
||||
//
|
||||
// Example:
|
||||
// ```v
|
||||
// st := '
|
||||
// Hello there,
|
||||
// this is a string,
|
||||
// all the leading indents are removed
|
||||
// and also the first and the last lines if they are blank
|
||||
// '.trim_indent()
|
||||
//
|
||||
// assert st == 'Hello there,
|
||||
// this is a string,
|
||||
// all the leading indents are removed
|
||||
// and also the first and the last lines if they are blank'
|
||||
// ```
|
||||
pub fn (s string) trim_indent() string {
|
||||
mut lines := s.split_into_lines()
|
||||
|
||||
lines_indents := lines
|
||||
.filter(!it.is_blank())
|
||||
.map(it.indent_width())
|
||||
|
||||
mut min_common_indent := int(2147483647) // max int
|
||||
for line_indent in lines_indents {
|
||||
if line_indent < min_common_indent {
|
||||
min_common_indent = line_indent
|
||||
}
|
||||
}
|
||||
|
||||
// trim first line if it's blank
|
||||
if lines.len > 0 && lines.first().is_blank() {
|
||||
lines = lines[1..]
|
||||
}
|
||||
|
||||
// trim last line if it's blank
|
||||
if lines.len > 0 && lines.last().is_blank() {
|
||||
lines = lines[..lines.len - 1]
|
||||
}
|
||||
|
||||
mut trimmed_lines := []string{cap: lines.len}
|
||||
|
||||
for line in lines {
|
||||
if line.is_blank() {
|
||||
trimmed_lines << line
|
||||
continue
|
||||
}
|
||||
|
||||
trimmed_lines << line[min_common_indent..]
|
||||
}
|
||||
|
||||
return trimmed_lines.join('\n')
|
||||
}
|
||||
|
||||
// indent_width returns the number of spaces or tabs at the beginning of the string.
|
||||
// Example: assert ' v'.indent_width() == 2
|
||||
// Example: assert '\t\tv'.indent_width() == 2
|
||||
pub fn (s string) indent_width() int {
|
||||
for i, c in s {
|
||||
if !c.is_space() {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// is_blank returns true if the string is empty or contains only white-space.
|
||||
// Example: assert ' '.is_blank()
|
||||
// Example: assert '\t'.is_blank()
|
||||
// Example: assert 'v'.is_blank() == false
|
||||
pub fn (s string) is_blank() bool {
|
||||
if s.len == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for c in s {
|
||||
if !c.is_space() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// match_glob matches the string, with a Unix shell-style wildcard pattern.
|
||||
// Note: wildcard patterns are NOT the same as regular expressions.
|
||||
// They are much simpler, and do not allow backtracking, captures, etc.
|
||||
|
@ -1056,3 +1056,26 @@ fn test_string_is_ascii() {
|
||||
fn test_string_with_zero_byte_escape() {
|
||||
assert '\x00'.bytes() == [u8(0)]
|
||||
}
|
||||
|
||||
fn test_is_blank() {
|
||||
assert ''.is_blank()
|
||||
assert ' '.is_blank()
|
||||
assert ' \t'.is_blank()
|
||||
assert ' \t
|
||||
|
||||
'.is_blank()
|
||||
assert ' \t\r'.is_blank()
|
||||
assert ' \t\r
|
||||
|
||||
'.is_blank()
|
||||
}
|
||||
|
||||
fn test_indent_width() {
|
||||
assert 'abc'.indent_width() == 0
|
||||
assert ' abc'.indent_width() == 1
|
||||
assert ' abc'.indent_width() == 2
|
||||
assert '\tabc'.indent_width() == 1
|
||||
assert '\t abc'.indent_width() == 2
|
||||
assert '\t\tabc'.indent_width() == 2
|
||||
assert '\t\t abc'.indent_width() == 3
|
||||
}
|
||||
|
126
vlib/builtin/string_trim_indent_test.v
Normal file
126
vlib/builtin/string_trim_indent_test.v
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
||||
// Use of this source code is governed by an MIT license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
fn test_empty_string() {
|
||||
assert ''.trim_indent() == ''
|
||||
}
|
||||
|
||||
fn test_blank_string() {
|
||||
assert ' \t'.trim_indent() == ''
|
||||
}
|
||||
|
||||
fn test_multiline_blank_string() {
|
||||
assert '
|
||||
\t
|
||||
'.trim_indent() == ''
|
||||
}
|
||||
|
||||
fn test_zero_indentation() {
|
||||
assert 'abc
|
||||
def'.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_zero_indentation_and_blank_first_and_last_lines() {
|
||||
assert '
|
||||
abc
|
||||
def
|
||||
'.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_common_case_tabbed() {
|
||||
assert '
|
||||
abc
|
||||
def
|
||||
'.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_common_case_spaced() {
|
||||
assert '
|
||||
abc
|
||||
def
|
||||
'.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_common_case_tabbed_with_middle_blank_like() {
|
||||
assert '
|
||||
abc
|
||||
|
||||
def
|
||||
'.trim_indent() == 'abc\n\ndef'
|
||||
}
|
||||
|
||||
fn test_common_case_tabbed_with_blank_first_line() {
|
||||
assert ' \t
|
||||
abc
|
||||
def
|
||||
'.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_common_case_tabbed_with_blank_first_and_last_line() {
|
||||
assert ' \t
|
||||
abc
|
||||
def
|
||||
\t '.trim_indent() == 'abc\ndef'
|
||||
}
|
||||
|
||||
fn test_html() {
|
||||
assert '
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hello, World!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
'.trim_indent() == '<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hello, World!
|
||||
</p>
|
||||
</body>
|
||||
</html>'
|
||||
}
|
||||
|
||||
fn test_broken_html() {
|
||||
assert '
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hello, World!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
'.trim_indent() == ' <!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Hello, World!
|
||||
</p>
|
||||
</body>
|
||||
</html>'
|
||||
}
|
||||
|
||||
fn test_doc_example() {
|
||||
st := '
|
||||
Hello there,
|
||||
this is a string,
|
||||
all the leading indents are removed
|
||||
and also the first and the last lines if they are blank
|
||||
'.trim_indent()
|
||||
assert st == 'Hello there,
|
||||
this is a string,
|
||||
all the leading indents are removed
|
||||
and also the first and the last lines if they are blank'
|
||||
}
|
Loading…
Reference in New Issue
Block a user