205
votes

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

5 Answers

265
votes

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";

145
votes

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##"#
"###;
74
votes

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".

11
votes

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
10
votes

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