Kotlin - How to trim all leading spaces from a multiline string? - string

String.trim() does not work for strings built using buildString. For example,
val s = buildString {
append("{")
append('\n')
append(" ".repeat(5))
append("hello")
append(" ".repeat(7))
append("world")
append("}")
}
println(s.trim())
This prints
{
hello world}
but I need it to print
{
hello
world
}
How can I trim indent without writing my own trim method?

trim() only removes whitespaces from the beginning and end of a whole string, not per-line. You can remove spaces from each line with:
s.lineSequence()
.map { it.trim() }
.joinToString("\n")
Please note that as a side effect, above code converts all line endings to LF ("\n"). You can replace "\n" with "\r\n" or "\r" to get different results. To preserve line endings exactly as they were in the original string, we would need a more complicated solution.

One liner:
s.lines().joinToString(transform = String::trim, separator = "\n")

You could use a regular expression to trim leading whitespace:
val s = buildString {
append("{")
append('\n')
append(" ".repeat(5))
append("hello\n")
append(" ".repeat(7))
append("world\n")
append("}")
}
println(s.replace(Regex("""^\s+""", RegexOption.MULTILINE), ""))
Output:
{
hello
world
}

Related

Flutter remove extra white space between string

how to remove extra white space between following string ?
String word= "Hai where are you from" ;
word.split(" ") does not work for this condition.
this will remove the white space in the string
try
String word= "Hai where are you from";
print(word.replaceAll(' ', ''));
You can you two functions for String:
ReplaceAll Function
String str;
str.replaceAll(" ", " ");
Trim function
str.trim();
If you want to remove extra white spaces you can use this code. Just call the cleanupWhitespace method and it will return the cleaned up string.
final whitespaceRE = RegExp(r"(?! )\s+| \s+");
String cleanupWhitespace(String input) => input.split(whitespaceRE).join(" ");
It works like this for ex if you have a string like this:
Hello world
It will replace all the white space with a single white space.
Hello world

How to put double quotes into Swift String

I am writing some codes that deals with string with double quote in Swift. Here is what I've done so far:
func someMethod {
let string = "String with \"Double Quotes\""
dealWithString(string)
}
func dealWithString(input: String) {
// I placed a breakpoint here.
}
When I run the codes the breakpoint stopped there as usual but when I input the following into the debugger:
print input
This is what I get:
(String) $R0 = "String with \"Double Quotes\""
I got this string with the backslashes. But if I tried to remove the backslashes from the source, it will give me compile error. Is there a workaround for this?
You are doing everything right. Backslash is used as an escape character to insert double quotes into Swift string precisely in the way that you use it.
The issue is the debugger. Rather than printing the actual value of the string, it prints the value as a string literal, i.e. enclosed in double quotes, with all special characters properly escaped escaped.
If you use print(input) in your code, you would see the string that you expect, i.e. with escape characters expanded and no double quotes around them.
Newer versions of Swift support an alternate delimiter syntax that lets you embed special characters without escaping. Add one or more # symbols before and after the opening and closing quotes, like so:
#"String with "Double Quotes""#
Be careful, though, because other common escapes require those extra # symbols, too.
#"This is not a newline: \n"#
#"This is a newline: \#n"#
You can read more about this at Extended String Delimiters at swift.org.
extension CustomStringConvertible {
var inspect: String {
if self is String {
return "\"\(self)\""
} else {
return self.description
}
}
}
let word = "Swift"
let s = "This is \(word.inspect)"

How do I make a new line in swift

Is there a way to have a way to make a new line in swift like "\n" for java?
var example: String = "Hello World \n This is a new line"
You should be able to use \n inside a Swift string, and it should work as expected, creating a newline character. You will want to remove the space after the \n for proper formatting like so:
var example: String = "Hello World \nThis is a new line"
Which, if printed to the console, should become:
Hello World
This is a new line
However, there are some other considerations to make depending on how you will be using this string, such as:
If you are setting it to a UILabel's text property, make sure that the UILabel's numberOfLines = 0, which allows for infinite lines.
In some networking use cases, use \r\n instead, which is the Windows newline.
Edit: You said you're using a UITextField, but it does not support multiple lines. You must use a UITextView.
Also useful:
let multiLineString = """
Line One
Line Two
Line Three
"""
Makes the code read more understandable
Allows copy pasting
You can use the following code;
var example: String = "Hello World \r\n This is a new line"
You can do this
textView.text = "Name: \(string1) \n" + "Phone Number: \(string2)"
The output will be
Name: output of string1
Phone Number: output of string2
"\n" is not working everywhere!
For example in email, it adds the exact "\n" into the text instead of a new line if you use it in the custom keyboard like: textDocumentProxy.insertText("\n")
There are another newLine characters available but I can't just simply paste them here (Because they make a new lines).
using this extension:
extension CharacterSet {
var allCharacters: [Character] {
var result: [Character] = []
for plane: UInt8 in 0...16 where self.hasMember(inPlane: plane) {
for unicode in UInt32(plane) << 16 ..< UInt32(plane + 1) << 16 {
if let uniChar = UnicodeScalar(unicode), self.contains(uniChar) {
result.append(Character(uniChar))
}
}
}
return result
}
}
you can access all characters in any CharacterSet. There is a character set called newlines. Use one of them to fulfill your requirements:
let newlines = CharacterSet.newlines.allCharacters
for newLine in newlines {
print("Hello World \(newLine) This is a new line")
}
Then store the one you tested and worked everywhere and use it anywhere.
Note that you can't relay on the index of the character set. It may change.
But most of the times "\n" just works as expected.

Swift 2.0 Escaping string for new line (String Encoding)

I am trying to escape string for new line i.e \n.
For example lets say string is:-
First Line Of String
second Line of String
Third Line of String
Now if i use String extension and say
func escapeString() -> String{
newString = self.stringByRemovingPercentEncoding
return newString
}
This extension does not give me newString as
First Line Of String\nSecond Line Of String\nThird Line Of String
I need above string as a jsonString to pass to server.i.e. i have to String encode it
Swift 5
You can use JSONEncoder to escape \n, \, \t, \r, ', " and etc. characters instead of manually replacing them in your string e.g.:
extension String {
var escaped: String {
if let data = try? JSONEncoder().encode(self) {
let escaped = String(data: data, encoding: .utf8)!
// Remove leading and trailing quotes
let set = CharacterSet(charactersIn: "\"")
return escaped.trimmingCharacters(in: set)
}
return self
}
}
let str = "new line - \n, quote - \", url - https://google.com"
print("Original: \(str)")
print("Escaped: \(str.escaped)")
Outputs:
Original: new line -
, quote - ", url - https://google.com
Escaped: new line - \n, quote - \", url - https:\/\/google.com
stringByRemovingPercentEncoding is for percent encoding as used in URLs, as you might expect from the name. (If not from that, maybe from reading the docs, the pertinent part of which even shows up in Xcode code completion.) That is, it takes a string like "some%20text%20with%20spaces" and turns it into "some text with spaces".
If you want to do a different kind of character substitution, you'll need to do it yourself. But that can still be a one-liner:
extension String {
var withEscapedNewlines: String {
return self.stringByReplacingOccurrencesOfString("\n", withString: "\\n")
}
}
Note the first argument to self.stringByReplacingOccurrencesOfString is an escape code passed to the Swift compiler, so the actual value of the argument is the newline character (ASCII/UTF8 0x0A). The second argument escapes the backslash (in the text passed to the Swift compiler), so the actual value of the argument is the text \n.

What is the syntax for a multiline string literal?

I'm having a hard time figuring out how string syntax works in Rust. Specifically, I'm trying to figure out how to make a multiple line string.
All string literals can be broken across several lines; for example:
let string = "line one
line two";
is a two line string, the same as "line one\nline two" (of course one can use the \n newline escape directly too). If you wish to just break a string across multiple lines for formatting reasons you can escape the newline and leading whitespace with a \; for example:
let string = "one line \
written over \
several";
is the same as "one line written over several".
If you want linebreaks in the string you can add them before the \:
let string = "multiple\n\
lines\n\
with\n\
indentation";
It's the same as "multiple\nlines\nwith\nindentation";
In case you want to do something a bit longer, which may or may not include quotes, backslashes, etc., use the raw string literal notation:
let shader = r#"
#version 330
in vec4 v_color;
out vec4 color;
void main() {
color = v_color;
};
"#;
If you have sequences of double quotes and hash symbols within your string, you can denote an arbitrary number of hashes as a delimiter:
let crazy_raw_string = r###"
My fingers #"
can#"#t stop "#"" hitting
hash##"#
"###;
Outputs:
#version 330
in vec4 v_color;
out vec4 color;
void main() {
color = v_color;
};
Playground link
Huon's answer is correct but if the indentation bothers you, consider using Indoc which is a procedural macro for indented multi-line strings. It stands for "indented document." It provides a macro called indoc!() that takes a multiline string literal and un-indents it so the leftmost non-space character is in the first column.
let s = indoc! {"
line one
line two
"};
The result is "line one\nline two\n".
Whitespace is preserved relative to the leftmost non-space character in the document, so the following has line two indented 3 spaces relative to line one:
let s = indoc! {"
line one
line two
"};
The result is "line one\n line two\n".
If you want to have fine granular control over spaces in multiline strings with linebreaks without using an external crate you can do the follwing. Example taken from my own project.
impl Display for OCPRecData {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "OCPRecData {{\n\
\x20 msg: {:?}\n\
\x20 device_name: {:?}\n\
\x20 parent_device_name: {:?}\n\
}}", self.msg, self.device_name, self.parent_device_name)
}
}
Results in
OCPRecData {
msg: Some("Hello World")
device_name: None
parent_device_name: None
}
\n\ at each code line end creates a line break at the proper position and discards further spaces in this line of code
\x20 (hex; 32 in decimal) is an ASCII space and an indicator for the first space to be preserved in this line of the string
\x20\x20\x20\x20 and \x20 have the same effect
In case you want to indent multiline text in your code:
let s = "first line\n\
second line\n\
third line";
println!("Multiline text goes next:\n{}", s);
The result will be the following:
Multiline text goes next:
first line
second line
third line

Resources