--- a/rust/hg-core/src/utils.rs Thu Feb 25 23:14:35 2021 +0100
+++ b/rust/hg-core/src/utils.rs Thu Feb 25 21:25:04 2021 +0100
@@ -11,6 +11,8 @@
use crate::utils::hg_path::HgPath;
use im_rc::ordmap::DiffItem;
use im_rc::ordmap::OrdMap;
+use std::cell::Cell;
+use std::fmt;
use std::{io::Write, ops::Deref};
pub mod files;
@@ -378,3 +380,43 @@
right
}
}
+
+/// Join items of the iterable with the given separator, similar to Python’s
+/// `separator.join(iter)`.
+///
+/// Formatting the return value consumes the iterator.
+/// Formatting it again will produce an empty string.
+pub fn join_display(
+ iter: impl IntoIterator<Item = impl fmt::Display>,
+ separator: impl fmt::Display,
+) -> impl fmt::Display {
+ JoinDisplay {
+ iter: Cell::new(Some(iter.into_iter())),
+ separator,
+ }
+}
+
+struct JoinDisplay<I, S> {
+ iter: Cell<Option<I>>,
+ separator: S,
+}
+
+impl<I, T, S> fmt::Display for JoinDisplay<I, S>
+where
+ I: Iterator<Item = T>,
+ T: fmt::Display,
+ S: fmt::Display,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(mut iter) = self.iter.take() {
+ if let Some(first) = iter.next() {
+ first.fmt(f)?;
+ }
+ for value in iter {
+ self.separator.fmt(f)?;
+ value.fmt(f)?;
+ }
+ }
+ Ok(())
+ }
+}