Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/commit-message-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ jobs:
excludeDescription: 'true' # optional: this excludes the description body of a pull request
excludeTitle: 'true' # optional: this excludes the title of a pull request
accessToken: ${{ secrets.GITHUB_TOKEN }}
pattern: '^(DataChange:|Change:|Feature:|Improve:|Perf:|Dep:|Doc:|Test:|CI:|Refactor:|Fix:|Fixdoc:|Fixup:|Merge|BumpVer:|Chore:|fix:|feat:|perf:|refactor:|test:|docs:|deps:|chore:|ci:|Build\(deps\):) .+$'
pattern: '^(DataChange:|Change:|change:|Feature:|Improve:|Perf:|Dep:|Doc:|Test:|CI:|Refactor:|Fix:|Fixdoc:|Fixup:|Merge|BumpVer:|Chore:|fix:|feat:|perf:|refactor:|test:|docs:|deps:|chore:|ci:|Build\(deps\):) .+$'
flags: 'gm'
error: |
Subject line has to contain a commit type, e.g.: "Change: blabla" or a merge commit e.g.: "Merge xxx".
Valid types are:
DataChange - Persistent data change
Change - API breaking change
change - API breaking change
Feature - API compatible new feature
feat - API compatible new feature
Improve - Become better without functional changes
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "display-more"
description = "helper to display various types"
version = "0.1.3"
version = "0.2.0"
authors = ["Databend Authors <opensource@datafuselabs.com>"]
license = "Apache-2.0"
edition = "2021"
Expand Down
83 changes: 58 additions & 25 deletions src/display_slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,48 @@ use std::fmt;

/// Implement `Display` for `&[T]` if T is `Display`.
///
/// It outputs at most `MAX` elements, excluding those from the 5th to the second-to-last one:
/// - `DisplaySlice(&[1,2,3,4,5,6])` outputs: `"[1,2,3,4,...,6]"`.
pub struct DisplaySlice<'a, T: fmt::Display, const MAX: usize = 5>(pub &'a [T]);
/// It outputs at most `limit` elements, excluding those from the 5th to the second-to-last one:
/// - `DisplaySlice{ slice: &[1,2,3,4,5,6], ...}` outputs: `"[1,2,3,4,...,6]"`.
pub struct DisplaySlice<'a, T: fmt::Display> {
slice: &'a [T],
/// The maximum number of elements to display. by default, it is 5.
limit: Option<usize>,
}

impl<'a, T: fmt::Display> DisplaySlice<'a, T> {
pub fn new(slice: &'a [T]) -> Self {
Self { slice, limit: None }
}

pub fn at_most(mut self, limit: Option<usize>) -> Self {
self.limit = limit;
self
}

impl<T: fmt::Display, const MAX: usize> fmt::Display for DisplaySlice<'_, T, MAX> {
pub fn limit(&self) -> usize {
self.limit.unwrap_or(5)
}
}

impl<T: fmt::Display> fmt::Display for DisplaySlice<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let slice = self.0;
let limit = self.limit();

if limit == 0 {
return write!(f, "[..]");
}

let slice = self.slice;
let len = slice.len();

write!(f, "[")?;

if len > MAX {
for (i, t) in slice[..(MAX - 1)].iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}

write!(f, "{}", t)?;
if len > limit {
for t in slice[..(limit - 1)].iter() {
write!(f, "{},", t)?;
}

write!(f, ",..,")?;
write!(f, "..,")?;
write!(f, "{}", slice.last().unwrap())?;
} else {
for (i, t) in slice.iter().enumerate() {
Expand Down Expand Up @@ -68,41 +89,53 @@ impl<T: fmt::Display, const MAX: usize> fmt::Display for DisplaySlice<'_, T, MAX
pub trait DisplaySliceExt<'a, T: fmt::Display> {
fn display(&'a self) -> DisplaySlice<'a, T>;

/// Display at most `MAX` elements.
fn display_n<const MAX: usize>(&'a self) -> DisplaySlice<'a, T, MAX>;
/// Display at most `n` elements.
fn display_n(&'a self, n: usize) -> DisplaySlice<'a, T> {
self.display().at_most(Some(n))
}
}

impl<T> DisplaySliceExt<'_, T> for [T]
where T: fmt::Display
{
fn display(&self) -> DisplaySlice<T> {
DisplaySlice(self)
}

fn display_n<const MAX: usize>(&'_ self) -> DisplaySlice<'_, T, MAX> {
DisplaySlice(self)
DisplaySlice::new(self)
}
}

#[cfg(test)]
mod tests {
use super::DisplaySlice;
use crate::DisplaySliceExt;

#[test]
fn test_display_slice() {
let a = vec![1, 2, 3, 4];
assert_eq!("[1,2,3,4]", DisplaySlice::<_>(&a).to_string());
assert_eq!("[1,2,3,4]", DisplaySlice::new(&a).to_string());

let a = vec![1, 2, 3, 4, 5];
assert_eq!("[1,2,3,4,5]", DisplaySlice::<_>(&a).to_string());
assert_eq!("[1,2,3,4,5]", DisplaySlice::new(&a).to_string());

let a = vec![1, 2, 3, 4, 5, 6];
assert_eq!("[1,2,3,4,..,6]", DisplaySlice::<_>(&a).to_string());
assert_eq!("[1,2,3,4,..,6]", DisplaySlice::new(&a).to_string());

let a = vec![1, 2, 3, 4, 5, 6, 7];
assert_eq!("[1,2,3,4,..,7]", DisplaySlice::<_>(&a).to_string());
assert_eq!("[1,2,3,4,..,7]", DisplaySlice::new(&a).to_string());

// with limit

let a = vec![1, 2, 3, 4, 5, 6, 7];
assert_eq!("[1,..,7]", DisplaySlice::<_, 2>(&a).to_string());
assert_eq!(
"[1,..,7]",
DisplaySlice::new(&a).at_most(Some(2)).to_string()
);

assert_eq!("[1,..,7]", a.display().at_most(Some(2)).to_string());

assert_eq!("[1,..,7]", a.display_n(2).to_string());

assert_eq!("[..,7]", a.display_n(1).to_string());

assert_eq!("[..]", a.display_n(0).to_string());
}
}