# Allow escaping space in strings

**URL:** <https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825>\
**Category:** language design\
**Created:** [February 24, 2018, 10:27pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825 "2018-02-24T22:27:33Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [February 24, 2018, 10:27pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/1 "2018-02-24T22:27:33Z")

</div>

We have multiline strings. It would be nice to be able to indent them nicely. More specifically:

```
let s = "hello\
        \ world!";

```

Would become “hello world!”.

This would be useful for e.g.:

```
const NO_XTE: &str = "`xte` not found. make sure it's correctly installed:\n\
                     \ pacman -S xautomation\n\
                     \ apt-get install xautomation\n\
                     \ <etc you get the idea>";

```

Currently I’m using:

```
const NO_XTE: &str = "`xte` not found. make sure it's correctly installed:\n\
                   \x20 pacman -S xautomation\n\
                   \x20 apt-get install xautomation\n\
                   \x20 <etc you get the idea>";

```

This gives a visual indication of the target indentation, where the “2” is immediately under the `"` and the “0” stands in for the resulting space. This is suboptimal.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 24, 2018, 11:03pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/2 "2018-02-24T23:03:07Z")

</div>

What I tend to do is unindent the string:

```rust
    const NO_XTE: &str = "\
`xte` not found....
    pacman -S ...
    <etc you get the idea>";

```

Not perfect but reflects the literalness of the string.

I believe the current behavior is that _any whitespace_ after a backslash means to ignore all whitespace until the next non-whitespace character. This would therefore be a more complicated change than you might think.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [February 24, 2018, 11:15pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/3 "2018-02-24T23:15:19Z")

</div>

Yes, the next non-whitespace, aka the `\` that escapes the whitespace.

backslash-space would be an escape sequence for space.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 24, 2018, 11:33pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/4 "2018-02-24T23:33:51Z")

</div>

OK, I was incorrect. I was under that the impression that `\<space>` currently meant the same thing as `\<newline>`, but `\<space>` is currently an error.

In that case, I think that this would be an unopposed change given that you’ve provided a use case.

---

<div class="post-metadata">

**Author:** ![lordan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lordan/32/2107_2.png) [@lordan](https://internals.rust-lang.org/u/lordan)\
**Post date:** [February 26, 2018, 11:45am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/6 "2018-02-26T11:45:16Z")

</div>

One issue is that if you happen to have a trailing space this would silently change the meaning:

```
let s = "hello\
        \␣world!";

```

vs.

```
let s = "hello\␣
        \␣world!";

```

BTW, is there a reason why Rust does not auto-concatenate consecutive string literals like C? I always found this quite handy.

```
const NO_XTE: &str = "`xte` not found. make sure it's correctly installed:\n"
                     " pacman -S xautomation\n"
                     " apt-get install xautomation\n"
                     " <etc you get the idea>";
```

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [February 26, 2018, 12:40pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/7 "2018-02-26T12:40:12Z")

</div>

> [@lordan](#):
>
> BTW, is there a reason why Rust does not auto-concatenate consecutive string literals like C? I always found this quite handy.

Because it is a literal footgun

```rust
const DATA: &[&str] = &[
    "aaaaaaaaaaa",
    "bbbbbbbb"
    "cccccccccc",
    "dddddddddddddddd",
    "eeeeeeeee"
];

```

---

<div class="post-metadata">

**Author:** ![RReverser](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rreverser/32/2189_2.png) [@RReverser](https://internals.rust-lang.org/u/RReverser)\
**Post date:** [February 26, 2018, 6:56pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/8 "2018-02-26T18:56:18Z")

</div>

Did you look into using [indoc](https://github.com/dtolnay/indoc) by any chance?

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [February 27, 2018, 1:10pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/9 "2018-02-27T13:10:40Z")

</div>

I’m not gonna back off from this.

For now, I’ll keep using `\x20` everywhere. Fix it or deal with it.

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [February 28, 2018, 6:43pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/10 "2018-02-28T18:43:08Z")

</div>

> [@Soni](#):
>
> Fix it or deal with it.

I also like to indent my strings the way you do, for what it's worth =)

I'm a bit confused though -- are you asking for language changes here? Or rustfmt changes?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [March 1, 2018, 12:34am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/11 "2018-03-01T00:34:50Z")

</div>

(`<space>` means a literal space (U+20) and `<newline>` means a literal newline (`\n` or `\r\n`).)

This is a summary of the points so far.

The requested language change is to let `\<space>` mean the same thing as a literal space. It is currently an error.

This would mean that you could terminate a `\<newline>`'s skip-all-whitespace behavior and then include leading whitespace by escaping the first space with `\<space>` instead of using `\x20`. The only current way to have `\n\<newline>` continuation of a string and leading whitespace in the resulting string is currently to use the character-code escapes to start said whitespace.

The case that `\<newline>` and `\<space><newline>` look the same and have drastically different behavior though is a strong point against the proposed change. In order to avoid that visual ambiguity, it would have to be that `\<space>` would escape that space from the `\<newline>` gobbling of whitespace, but still error when not terminating said gobbling. This complicates the feature and makes it less intuitive (“you can escape a space” vs special cases) to avoid a visual ambiguity.

* * *

Personal opinion.

I think that un-indenting the string and just including the literal representation that you want against the left margin is the best choice currently. This is likely due to in part my dislike for visual indenting/alignment; I prefer block indenting with tabs (but don’t care enough to argue the point with an established default style).

---

<div class="post-metadata">

**Author:** ![nikomatsakis](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nikomatsakis/32/5410_2.png) [@nikomatsakis](https://internals.rust-lang.org/u/nikomatsakis)\
**Post date:** [March 1, 2018, 12:42am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/12 "2018-03-01T00:42:19Z")

</div>

Thanks for the summary! =)

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [March 1, 2018, 7:11am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/13 "2018-03-01T07:11:23Z")

</div>

Seems like you could unambiguously have `\|` (or `\>`…) be an empty character (or only valid as a white space stripping terminator). So you could have

```rust
const NO_XTE: &str = "`xte` not found. make sure it's correctly installed:\n\
                    \| pacman -S xautomation\n\
                    \| apt-get install xautomation\n\
                    \| <etc you get the idea>";

```

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [March 1, 2018, 8:11am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/14 "2018-03-01T08:11:44Z")

</div>

Raw strings to the rescue!  
You don’t even have to write `\n`s at line ends.

```rust
const NO_XTE: &str =
r"`xte` not found. make sure it's correctly installed:
    pacman -S xautomation
    apt-get install xautomation
    <etc you get the idea>";

```

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [March 1, 2018, 8:16am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/15 "2018-03-01T08:16:18Z")

</div>

You don’t even need it to be a raw string.

```rust
    const NO_XTE: &str = "\
`xte` not found....
    pacman -S ...
    <etc you get the idea>";

```

[Play](https://play.rust-lang.org/?gist=bd2644b45a3c9e8bbc7c6926fbaab28d&version=stable)

---

<div class="post-metadata">

**Author:** ![atagunov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/atagunov/32/5877_2.png) [@atagunov](https://internals.rust-lang.org/u/atagunov)\
**Post date:** [March 4, 2018, 10:54pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/16 "2018-03-04T22:54:40Z")

</div>

> [@CAD97](#):
>
> `\<newline>` and `\<space><newline>` [would] ... have drastically different behavior

Could `\<space><newline>` then become equivalent to `\<newline>`? E.g.

> `\` followed by a sequence of non-escaped whitespace characters until the end of the line behaves in the same way as `\` followed by a newline immediately; in other words those non-escaped whitespace characters are discarded

So both of these

```rust
let s1 = "hello\␣
         \␣world!";
let s2 = "hello\
         \␣\
         world!";

```

would mean `"hello world!"`?

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [March 4, 2018, 11:05pm UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/17 "2018-03-04T23:05:39Z")

</div>

We could also drop the whole newline stuff entirely (sorry everyone who currently uses it) and go for Lua: [`\z`](http://www.lua.org/manual/5.3/manual.html#3.1).

---

<div class="post-metadata">

**Author:** ![steven099](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steven099/32/3871_2.png) [@steven099](https://internals.rust-lang.org/u/steven099)\
**Post date:** [March 5, 2018, 12:52am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/18 "2018-03-05T00:52:22Z")

</div>

> [@CAD97](#):
>
> You don’t even need it to be a raw string.

I think the point was to _avoid_ having to outdent the string.

> [@Soni](#):
>
> We could also drop the whole newline stuff entirely (sorry everyone who currently uses it) and go for Lua: \z.

How is this different from how it currently works? The whole problem is that `\` skips the subsequent span of whitespace (just like `\z`) and they want to split that into a span that is skipped followed immediately by a span of whitespace which is _not_ skipped. The two ways to do this are to have a delimiter (like `\|` in my previous comment), or to use trailing quote to indicate the indentation level, like with Swift multiline strings:

```rust
const NO_XTE: &str = """`xte` not found. make sure it's correctly installed:
                            pacman -S xautomation
                            apt-get install xautomation
                            <etc you get the idea>
                        """;

```

or

```rust
const NO_XTE: &str = """
    `xte` not found. make sure it's correctly installed:
        pacman -S xautomation
        apt-get install xautomation
        <etc you get the idea>
    """;

```

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [March 5, 2018, 12:56am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/19 "2018-03-05T00:56:13Z")

</div>

It only makes unescaped newlines an error.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:29am UTC](https://internals.rust-lang.org/t/allow-escaping-space-in-strings/6825/20 "2019-03-25T08:29:42Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
