# Formatln! = format! + platform specific newline

**URL:** <https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798>\
**Category:** libs\
**Created:** [January 10, 2021, 4:10pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798 "2021-01-10T16:10:53Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![gilescope](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gilescope/32/2798_2.png) [@gilescope](https://internals.rust-lang.org/u/gilescope)\
**Post date:** [January 10, 2021, 4:10pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/1 "2021-01-10T16:10:53Z")

</div>

At the moment it's not so easy to add a platform specific newline to a string. It's easy in c# ( [https://docs.microsoft.com/en-us/dotnet/api/system.environment.newline](https://docs.microsoft.com/en-us/dotnet/api/system.environment.newline) ) or java ( [System (Java Platform SE 8 )](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#lineSeparator--) ) but not in standard rust. At the moment `println!` is the only way to achieve it out of the box.

How's about we have a `formatln!` that's just like `format!` but with a platform specific newline on the end of the created string?

Even for a batteries not included std lib this is something I'd expect to see included (just like we have rust path separator ( [std::path::MAIN\_SEPARATOR - Rust](https://doc.rust-lang.org/std/path/constant.MAIN_SEPARATOR.html) ).

(Maybe I'm missing some super easy way to get a platform specific line ending in std rust?)

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mbrubeck/32/174_2.png) [@mbrubeck](https://internals.rust-lang.org/u/mbrubeck)\
**Post date:** [January 10, 2021, 4:27pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/2 "2021-01-10T16:27:35Z")

</div>

> [@gilescope](#):
>
> At the moment `println!` is the only way to achieve it out of the box.

`println!` does not have any platform-specific behavior. It uses `"\n"` as the line ending [on all platforms](https://doc.rust-lang.org/std/macro.println.html).

In addition, standard Rust tools like `rustc` and `cargo` use only `"\n"` line endings in both terminal output and in files they write, on all platforms.

The idea of “platform-specific newline” is somewhat obsolete, as evidenced by the fact that your existing Rust code works without it even though you assumed it didn’t. (Even Notepad.exe has supported `"\n"` line endings for years now.)

---

<div class="post-metadata">

**Author:** ![gilescope](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gilescope/32/2798_2.png) [@gilescope](https://internals.rust-lang.org/u/gilescope)\
**Post date:** [January 10, 2021, 5:03pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/3 "2021-01-10T17:03:15Z")

</div>

`\r` is dead? Well that's great to hear. That certainly makes things simpler.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)\
**Post date:** [January 10, 2021, 5:49pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/4 "2021-01-10T17:49:16Z")

</div>

C stdio APIs have the requirement that `\n` in files opened in text mode be transparently translated to the platform line ending, in output as well as in input.

Not sure if this only applies to C, or indeed, typical non- `\n` platforms do this for all text streams, but I suspect it's the latter, and it just works in Rust for that reason.

---

<div class="post-metadata">

**Author:** ![XAMPPRocky](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/xampprocky/32/6049_2.png) [@XAMPPRocky](https://internals.rust-lang.org/u/XAMPPRocky)\
**Post date:** [January 10, 2021, 8:45pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/5 "2021-01-10T20:45:41Z")

</div>

It’s a bit more long winded but you can use `writeln!`.

```rust
let mut s = String::new();
let _ = writeln!(&mut s, "{}", 5);

```

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [January 10, 2021, 9:22pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/6 "2021-01-10T21:22:51Z")

</div>

FWIW, I appreciate that Rust just uses `\n` here. I'm happy to put the `\r` myself if needed.

Having to deal with [`TextWriter.NewLine`](https://docs.microsoft.com/en-us/dotnet/api/system.io.textwriter.newline?view=net-5.0#remarks) in C# has caused issues for me just as much as it's helped.

---

<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:** [January 10, 2021, 10:43pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/7 "2021-01-10T22:43:26Z")

</div>

Having things silently normalize-out OS specific newlines (where "out" is another part of your program, not the OS) is asking for OS portability issues.

I fixed a Windows test failure for some crate I was using that was due to my checkout having CRLF. The solution the maintainer used there was to just normalize to `\n` on reading the file (as it was a snapshot test iirc, test the program gives the same output as in the file). The same way that `include_str!` and multiline string literals normalize CRLF to just LF.

Automatically normalizing-in can be surprising, but it leads to code just working in more places, being more platform (and git `auto.crlf`) agnostic to where it was compiled.

Oh, and a fun place where auto CRLF messed things up: [reading an exe from a QR code](https://youtu.be/ExwqNreocpg) (for fun). Because of normalize-out (and in one place forgetting to set binary mode), `\n` bytes in the exe were being "corrected" to `\r\n`.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [January 11, 2021, 2:30am UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/8 "2021-01-11T02:30:17Z")

</div>

Since when does `include_str!` normalize line endings? There was a PR in FCP a while back that I successfully argued against. If the behavior has changed, that is a serious issue.

---

<div class="post-metadata">

**Author:** ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)\
**Post date:** [January 11, 2021, 7:48am UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/9 "2021-01-11T07:48:57Z")

</div>

Just checked, it doesn't. `rustc 1.49.0 (e1884a8e3 2020-12-29)`

```rust
fn main() {
	let stuff = include_bytes!("crlf.txt");
	println!("{:?}", stuff);
}
// Output: [99, 114, 108, 102, 13, 10, 99, 114, 108, 102, 13, 10]
// ^^^^^^ ^^^^^^

```

**Edit:** Oh, oops, `include_bytes!()` wasn't the question. Same result with `include_str!()` and `.as_bytes()` though.

---

<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:** [January 11, 2021, 10:19pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/10 "2021-01-11T22:19:10Z")

</div>

Hm, I could've sworn `include_str!` (not `include_bytes!`) did. I guess I confused it with a literal source string, which definitely does normalize "raw" CRLF (i.e. ones physically present in the `.rs` file) to just LF (but not explicit `\r\n` ofc).

---

<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:** [April 11, 2021, 10:19pm UTC](https://internals.rust-lang.org/t/formatln-format-platform-specific-newline/13798/11 "2021-04-11T22:19:27Z")

</div>

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