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.
5 Answers
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##"#
"###;
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