about summary refs log tree commit diff
path: root/src/librustdoc/display.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/display.rs')
-rw-r--r--src/librustdoc/display.rs92
1 files changed, 88 insertions, 4 deletions
diff --git a/src/librustdoc/display.rs b/src/librustdoc/display.rs
index aa0fad26520..d62ea4c3688 100644
--- a/src/librustdoc/display.rs
+++ b/src/librustdoc/display.rs
@@ -1,6 +1,6 @@
 //! Various utilities for working with [`fmt::Display`] implementations.
 
-use std::fmt::{self, Display, Formatter};
+use std::fmt::{self, Display, Formatter, FormattingOptions};
 
 pub(crate) trait Joined: IntoIterator {
     /// Takes an iterator over elements that implement [`Display`], and format them into `f`, separated by `sep`.
@@ -10,7 +10,7 @@ pub(crate) trait Joined: IntoIterator {
     ///
     /// The performance of `joined` is slightly better than `format`, since it doesn't need to use a `Cell` to keep track of whether [`fmt`](Display::fmt)
     /// was already called (`joined`'s API doesn't allow it be called more than once).
-    fn joined(self, sep: &str, f: &mut Formatter<'_>) -> fmt::Result;
+    fn joined(self, sep: impl Display, f: &mut Formatter<'_>) -> fmt::Result;
 }
 
 impl<I, T> Joined for I
@@ -18,12 +18,12 @@ where
     I: IntoIterator<Item = T>,
     T: Display,
 {
-    fn joined(self, sep: &str, f: &mut Formatter<'_>) -> fmt::Result {
+    fn joined(self, sep: impl Display, f: &mut Formatter<'_>) -> fmt::Result {
         let mut iter = self.into_iter();
         let Some(first) = iter.next() else { return Ok(()) };
         first.fmt(f)?;
         for item in iter {
-            f.write_str(sep)?;
+            sep.fmt(f)?;
             item.fmt(f)?;
         }
         Ok(())
@@ -45,3 +45,87 @@ impl<T: Display> MaybeDisplay for Option<T> {
         })
     }
 }
+
+#[derive(Clone, Copy)]
+pub(crate) struct Wrapped<T> {
+    prefix: T,
+    suffix: T,
+}
+
+pub(crate) enum AngleBracket {
+    Open,
+    Close,
+}
+
+impl Display for AngleBracket {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        f.write_str(match (self, f.alternate()) {
+            (Self::Open, true) => "<",
+            (Self::Open, false) => "&lt;",
+            (Self::Close, true) => ">",
+            (Self::Close, false) => "&gt;",
+        })
+    }
+}
+
+impl Wrapped<AngleBracket> {
+    pub(crate) fn with_angle_brackets() -> Self {
+        Self { prefix: AngleBracket::Open, suffix: AngleBracket::Close }
+    }
+}
+
+impl Wrapped<char> {
+    pub(crate) fn with_parens() -> Self {
+        Self { prefix: '(', suffix: ')' }
+    }
+
+    pub(crate) fn with_square_brackets() -> Self {
+        Self { prefix: '[', suffix: ']' }
+    }
+}
+
+impl<T: Display> Wrapped<T> {
+    pub(crate) fn with(prefix: T, suffix: T) -> Self {
+        Self { prefix, suffix }
+    }
+
+    pub(crate) fn when(self, if_: bool) -> Wrapped<impl Display> {
+        Wrapped {
+            prefix: if_.then_some(self.prefix).maybe_display(),
+            suffix: if_.then_some(self.suffix).maybe_display(),
+        }
+    }
+
+    pub(crate) fn wrap_fn(
+        self,
+        content: impl Fn(&mut Formatter<'_>) -> fmt::Result,
+    ) -> impl Display {
+        fmt::from_fn(move |f| {
+            self.prefix.fmt(f)?;
+            content(f)?;
+            self.suffix.fmt(f)
+        })
+    }
+
+    pub(crate) fn wrap<C: Display>(self, content: C) -> impl Display {
+        self.wrap_fn(move |f| content.fmt(f))
+    }
+}
+
+#[derive(Clone, Copy)]
+pub(crate) struct WithOpts {
+    opts: FormattingOptions,
+}
+
+impl WithOpts {
+    pub(crate) fn from(f: &Formatter<'_>) -> Self {
+        Self { opts: f.options() }
+    }
+
+    pub(crate) fn display(self, t: impl Display) -> impl Display {
+        fmt::from_fn(move |f| {
+            let mut f = f.with_options(self.opts);
+            t.fmt(&mut f)
+        })
+    }
+}