tabled/features/width/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
//! This module contains object which can be used to limit a cell to a given width:
//!
//! - [`Truncate`] cuts a cell content to limit width.
//! - [`Wrap`] split the content via new lines in order to fit max width.
//! - [`Justify`] sets columns width to the same value.
//!
//! To set a a table width, a combination of [`Width::truncate`] or [`Width::wrap`] and [`Width::increase`] can be used.
//!
//! ## Example
//!
//! ```
//! use tabled::{Width, Table};
//!
//! let table = Table::new(&["Hello World!"])
//! .with(Width::wrap(7))
//! .with(Width::increase(7))
//! .to_string();
//!
//! assert_eq!(
//! table,
//! concat!(
//! "+-----+\n",
//! "| &st |\n",
//! "| r |\n",
//! "+-----+\n",
//! "| Hel |\n",
//! "| lo |\n",
//! "| Wor |\n",
//! "| ld! |\n",
//! "+-----+",
//! )
//! );
//! ```
mod justify;
mod min_width;
mod truncate;
mod width_list;
mod wrap;
use crate::measurment::Measurment;
pub use self::{
justify::Justify,
min_width::MinWidth,
truncate::{SuffixLimit, Truncate},
width_list::WidthList,
wrap::Wrap,
};
use papergrid::{records::Records, width::WidthEstimator, Estimate, GridConfig};
pub(crate) use wrap::wrap_text;
/// Width allows you to set a min and max width of an object on a [`Table`]
/// using different strategies.
///
/// It also allows you to set a min and max width for a whole table.
///
/// You can apply a min and max strategy at the same time with the same value,
/// the value will be a total table width.
///
/// It is an abstract factory.
///
/// Beware that borders are not removed when you set a size value to very small.
/// For example if you set size to 0 the table still be rendered but with all content removed.
///
/// Also be aware that it doesn't changes [`Padding`] settings nor it considers them.
///
/// The function is color aware if a `color` feature is on.
///
/// ## Examples
///
/// ### Cell change
///
/// ```
/// use tabled::{object::Segment, Width, Modify, Style, Table};
///
/// let data = ["Hello", "World", "!"];
///
/// let table = Table::new(&data)
/// .with(Style::markdown())
/// .with(Modify::new(Segment::all()).with(Width::truncate(3).suffix("...")));
/// ```
///
/// ### Table change
///
/// ```
/// use tabled::{Width, Table};
///
/// let table = Table::new(&["Hello World!"]).with(Width::wrap(5));
/// ```
///
/// ### Total width
///
/// ```
/// use tabled::{Width, Table};
///
/// let table = Table::new(&["Hello World!"])
/// .with(Width::wrap(5))
/// .with(Width::increase(5));
/// ```
///
/// [`Padding`]: crate::Padding
/// [`Table`]: crate::Table
#[derive(Debug)]
pub struct Width;
impl Width {
/// Returns a [`Wrap`] structure.
pub fn wrap<W>(width: W) -> Wrap<W>
where
W: Measurment<Width>,
{
Wrap::new(width)
}
/// Returns a [`Truncate`] structure.
pub fn truncate<W>(width: W) -> Truncate<'static, W>
where
W: Measurment<Width>,
{
Truncate::new(width)
}
/// Returns a [`MinWidth`] structure.
pub fn increase<W>(width: W) -> MinWidth<W>
where
W: Measurment<Width>,
{
MinWidth::new(width)
}
/// Returns a [`Justify`] structure.
pub fn justify<W>(width: W) -> Justify<W>
where
W: Measurment<Width>,
{
Justify::new(width)
}
/// Create [`WidthList`] to set a table width to a constant list of column widths.
///
/// Notice if you provide a list with `.len()` smaller than `Table::count_columns` then it will have no affect.
///
/// Also notice that you must provide values bigger than or equal to a real content width, otherwise it may panic.
///
/// # Example
///
/// ```
/// use tabled::{Table, Width};
///
/// let data = vec![
/// ("Some\ndata", "here", "and here"),
/// ("Some\ndata on a next", "line", "right here"),
/// ];
///
/// let table = Table::new(data)
/// .with(Width::list([20, 10, 12]))
/// .to_string();
///
/// assert_eq!(
/// table,
/// "+--------------------+----------+------------+\n\
/// | &str | &str | &str |\n\
/// +--------------------+----------+------------+\n\
/// | Some | here | and here |\n\
/// | data | | |\n\
/// +--------------------+----------+------------+\n\
/// | Some | line | right here |\n\
/// | data on a next | | |\n\
/// +--------------------+----------+------------+"
/// )
/// ```
pub fn list<I>(rows: I) -> WidthList
where
I: IntoIterator<Item = usize>,
{
WidthList::new(rows.into_iter().collect())
}
}
pub(crate) fn get_table_widths<R>(records: R, cfg: &GridConfig) -> Vec<usize>
where
R: Records,
{
let mut evaluator = WidthEstimator::default();
evaluator.estimate(records, cfg);
evaluator.into()
}
pub(crate) fn count_borders(
cfg: &GridConfig,
start: usize,
end: usize,
count_columns: usize,
) -> usize {
(start..end)
.skip(1)
.filter(|&i| cfg.has_vertical(i, count_columns))
.count()
}
pub(crate) fn get_table_total_width<W, R>(records: R, cfg: &GridConfig, ctrl: &W) -> usize
where
W: Estimate<R>,
R: Records,
{
ctrl.total()
+ cfg.count_vertical(records.count_columns())
+ cfg.get_margin().left.size
+ cfg.get_margin().right.size
}
pub(crate) fn get_table_widths_with_total<R>(records: R, cfg: &GridConfig) -> (Vec<usize>, usize)
where
R: Records,
{
let mut evaluator = WidthEstimator::default();
evaluator.estimate(&records, cfg);
let total_width = get_table_total_width(&records, cfg, &evaluator);
let widths = evaluator.into();
(widths, total_width)
}