diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 4a64e2e2d102d..67bf65f81c559 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -174,6 +174,7 @@ #![feature(intra_doc_pointers)] #![feature(intrinsics)] #![feature(lang_items)] +#![feature(let_else)] #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] #![feature(min_specialization)] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index cd5ed35be79ba..7dc8b51a04dce 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1833,6 +1833,48 @@ impl str { self.trim_end_matches(|c: char| c.is_whitespace()) } + /// Returns a string slice with any one trailing newline removed. + /// + /// 'Newline' is precisely a newline character (`0xA`), perhaps + /// preceded by a carriage return (`0xD`). I.e., `'\r\n'` or + /// `'\n'`. (This is the same definition as used by [`str::lines`] + /// and `std::io::BufRead::lines`.) + // + // Unfortunately it doesn't seem to be possible to make the reference to `lines` + // a link. This: + // [`std::io::BufRead::lines`]: ../std/io/trait.BufRead.html#method.lines + // works in `core`, but fails with a broken link error in `std`, where + // this text is incorporated due to `String`'s `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(trim_newline)] + /// use std::fmt::Write as _; + /// + /// assert_eq!("Text", "Text".trim_newline()); + /// assert_eq!("Text", "Text\n".trim_newline()); + /// assert_eq!("Text", "Text\r\n".trim_newline()); + /// assert_eq!("Text\r", "Text\r".trim_newline()); + /// assert_eq!("Text\n", "Text\n\n".trim_newline()); + /// assert_eq!("Text\n\r", "Text\n\r".trim_newline()); // LF CR is not a valid newline + /// + /// let mut s = String::new(); + /// writeln!(s, " Hi! ").unwrap(); + /// assert_eq!(" Hi! ", s.trim_newline()); + /// assert_eq!(" Hi! ", s.trim_newline().trim_newline()); + /// ``` + #[inline] + #[must_use = "this returns the trimmed string as a new slice, \ + without modifying the original"] + #[unstable(feature = "trim_newline", issue = "none")] + pub fn trim_newline(&self) -> &str { + let s = self; + let Some(s) = s.strip_suffix('\n') else { return s }; + let Some(s) = s.strip_suffix('\r') else { return s }; + s + } + /// Returns a string slice with leading whitespace removed. /// /// 'Whitespace' is defined according to the terms of the Unicode Derived