tabled/lib.rs
1//! An easy to use library for pretty print tables of Rust `struct`s and `enum`s.
2//!
3//! There's two approaches to construct a table.
4//!
5//! 1. When the type of data is known.
6//! 2. When it's unknown.
7//!
8//! Here you can work with both.\
9//! For first approach you shall find [`derive::Tabled`] macros being very helpfull.\
10//! For a later one you shall take a look at [`Builder`].
11//!
12//! There are a number of [`settings`] you can use\
13//! to change table appearance, layout and data itself.
14//!
15//! Beside a default [`Table`] type there are more,\
16//! more specific table which works best when there are some constraints.
17//!
18#![cfg_attr(
19 all(feature = "derive", feature = "std", feature = "assert"),
20 doc = "```"
21)]
22#![cfg_attr(
23 not(all(feature = "derive", feature = "std", feature = "assert")),
24 doc = "```ignore"
25)]
26//! use tabled::{
27//! Tabled, Table, assert::assert_table,
28//! settings::{Style, Alignment, object::Columns},
29//! };
30//!
31//! #[derive(Tabled)]
32//! struct Language {
33//! name: &'static str,
34//! designed_by: &'static str,
35//! invented_year: usize,
36//! }
37//!
38//! let languages = vec![
39//! Language{ name: "C", designed_by: "Dennis Ritchie", invented_year: 1972 },
40//! Language{ name: "Rust", designed_by: "Graydon Hoare", invented_year: 2010 },
41//! Language{ name: "Go", designed_by: "Rob Pike", invented_year: 2009 },
42//! ];
43//!
44//! let mut table = Table::new(languages);
45//! table.with(Style::modern());
46//! table.modify(Columns::first(), Alignment::right());
47//!
48//! assert_table!(
49//! table,
50//! "┌──────┬────────────────┬───────────────┐"
51//! "│ name │ designed_by │ invented_year │"
52//! "├──────┼────────────────┼───────────────┤"
53//! "│ C │ Dennis Ritchie │ 1972 │"
54//! "├──────┼────────────────┼───────────────┤"
55//! "│ Rust │ Graydon Hoare │ 2010 │"
56//! "├──────┼────────────────┼───────────────┤"
57//! "│ Go │ Rob Pike │ 2009 │"
58//! "└──────┴────────────────┴───────────────┘"
59//! );
60//! ```
61//!
62//! ## Building table step by step
63//!
64//! When you data scheme is not known at compile time.\
65//! You most likely will not able to relay on [`Table`].\
66//! One option would be is to use [`Builder`].
67//!
68#![cfg_attr(all(feature = "std", feature = "assert"), doc = "```")]
69#![cfg_attr(not(all(feature = "std", feature = "assert")), doc = "```ignore")]
70//! use std::iter::once;
71//! use tabled::{builder::Builder, settings::Style, assert::assert_table};
72//!
73//! const X: usize = 3;
74//! const Y: usize = 5;
75//!
76//! let mut builder = Builder::default();
77//!
78//! for i in 0..X {
79//! let row = (0..Y).map(|j| (i * j).to_string());
80//! builder.push_record(row);
81//! }
82//!
83//! builder.insert_record(0, (0..Y).map(|i| i.to_string()));
84//! builder.insert_column(0, once(String::new()).chain((0..X).map(|i| i.to_string())));
85//!
86//! let mut table = builder.build();
87//! table.with(Style::rounded());
88//!
89//! assert_table!(
90//! table,
91//! "╭───┬───┬───┬───┬───┬───╮"
92//! "│ │ 0 │ 1 │ 2 │ 3 │ 4 │"
93//! "├───┼───┼───┼───┼───┼───┤"
94//! "│ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │"
95//! "│ 1 │ 0 │ 1 │ 2 │ 3 │ 4 │"
96//! "│ 2 │ 0 │ 2 │ 4 │ 6 │ 8 │"
97//! "╰───┴───┴───┴───┴───┴───╯"
98//! );
99//! ```
100//!
101//! ## Settings
102//!
103//! You can find lots of settings in [`tabled::settings`].
104//!
105//! ## Hints
106//!
107//! [`Table`] can be build from vast majority of Rust's standard types.\
108//! This allows you to run the following code.
109//!
110#![cfg_attr(all(feature = "std", feature = "assert"), doc = "```")]
111#![cfg_attr(not(all(feature = "std", feature = "assert")), doc = "```ignore")]
112//! use tabled::{Table, assert::assert_table};
113//!
114//! let table = Table::new(&[1, 2, 3]);
115//!
116//! assert_table!(
117//! table,
118//! "+-----+"
119//! "| i32 |"
120//! "+-----+"
121//! "| 1 |"
122//! "+-----+"
123//! "| 2 |"
124//! "+-----+"
125//! "| 3 |"
126//! "+-----+"
127//! );
128//! ```
129//!
130//! You can compine types, and settings together using a tupples.\
131//! And achive magical results.
132//!
133#![cfg_attr(all(feature = "std", feature = "assert"), doc = "```")]
134#![cfg_attr(not(all(feature = "std", feature = "assert")), doc = "```ignore")]
135//! use tabled::{
136//! Table, assert::assert_table,
137//! settings::{style::{Style, HorizontalLine}, Alignment, Padding},
138//! };
139//!
140//! let data = &[(1, 2, "Hello"), (1, 3, "World")];
141//!
142//! let mut table = Table::new(data);
143//! table.with(
144//! Style::modern()
145//! .remove_horizontal()
146//! .horizontals([(1, HorizontalLine::inherit(Style::modern()))])
147//! );
148//! table.with((Alignment::right(), Padding::new(2, 0, 2, 1)));
149//!
150//! assert_table!(
151//! table,
152//! "┌─────┬─────┬───────┐"
153//! "│ │ │ │"
154//! "│ │ │ │"
155//! "│ i32│ i32│ &str│"
156//! "│ │ │ │"
157//! "├─────┼─────┼───────┤"
158//! "│ │ │ │"
159//! "│ │ │ │"
160//! "│ 1│ 2│ Hello│"
161//! "│ │ │ │"
162//! "│ │ │ │"
163//! "│ │ │ │"
164//! "│ 1│ 3│ World│"
165//! "│ │ │ │"
166//! "└─────┴─────┴───────┘"
167//! );
168//! ```
169//!
170//! Be ware you don't obligated to `collect` your data before building.
171//!
172#![cfg_attr(
173 all(feature = "derive", feature = "std", feature = "assert"),
174 doc = "```"
175)]
176#![cfg_attr(
177 not(all(feature = "derive", feature = "std", feature = "assert")),
178 doc = "```ignore"
179)]
180//! use tabled::{Tabled, Table, assert::assert_table};
181//!
182//! let data = (0..3).map(|i| [i, i * 2, i * 3]);
183//!
184//! let mut table = Table::new(data);
185//!
186//! assert_table!(
187//! table,
188//! "+---+---+---+"
189//! "| 0 | 1 | 2 |"
190//! "+---+---+---+"
191//! "| 0 | 0 | 0 |"
192//! "+---+---+---+"
193//! "| 1 | 2 | 3 |"
194//! "+---+---+---+"
195//! "| 2 | 4 | 6 |"
196//! "+---+---+---+"
197//! );
198//! ```
199//!
200//! Build table using [`row!`] and [`col!`] macros.
201//!
202#![cfg_attr(
203 all(feature = "macros", feature = "std", feature = "assert"),
204 doc = "```"
205)]
206#![cfg_attr(
207 not(all(feature = "macros", feature = "std", feature = "assert")),
208 doc = "```ignore"
209)]
210//! use tabled::{row, col, assert::assert_table};
211//!
212//! let table = row![
213//! col!["Hello", "World", "!"],
214//! col!["Hello"; 3],
215//! col!["World"; 3],
216//! ];
217//!
218//! assert_table!(
219//! table,
220//! "+-----------+-----------+-----------+"
221//! "| +-------+ | +-------+ | +-------+ |"
222//! "| | Hello | | | Hello | | | World | |"
223//! "| +-------+ | +-------+ | +-------+ |"
224//! "| | World | | | Hello | | | World | |"
225//! "| +-------+ | +-------+ | +-------+ |"
226//! "| | ! | | | Hello | | | World | |"
227//! "| +-------+ | +-------+ | +-------+ |"
228//! "+-----------+-----------+-----------+"
229//! );
230//! ```
231//!
232//! # `no_std`
233//!
234//! Only [`CompactTable`] can be used in `no_std` context.
235//!
236//! # Features
237//!
238//! - `std` - Used by default. If not its considered `no_std` with a limited set of functionality.
239//! - `derive` - Used by default. A support for `Tabled` derive macro.
240//! - `ansi` - A support for ANSI sequences.
241//! - `macros` - A support for `row!`, `col!` macro.
242//!
243//! ## More information
244//!
245//! You can find more examples of settings and attributes in
246//! [README.md](https://github.com/zhiburt/tabled/blob/master/README.md)
247//!
248//! [`Builder`]: crate::builder::Builder
249//! [`IterTable`]: crate::tables::IterTable
250//! [`CompactTable`]: crate::tables::CompactTable
251//! [`fmt::Write`]: core::fmt::Write
252//! [`row!`]: crate::row
253//! [`col!`]: crate::col
254//! [`tabled::settings`]: crate::settings
255
256#![cfg_attr(not(any(feature = "std", test)), no_std)]
257#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
258#![doc(
259 html_logo_url = "https://raw.githubusercontent.com/zhiburt/tabled/86ac146e532ce9f7626608d7fd05072123603a2e/assets/tabled-gear.svg"
260)]
261#![deny(unused_must_use)]
262#![warn(
263 missing_docs,
264 rust_2018_idioms,
265 rust_2018_compatibility,
266 missing_debug_implementations,
267 unreachable_pub,
268 future_incompatible,
269 single_use_lifetimes,
270 trivial_casts,
271 trivial_numeric_casts,
272 unused_extern_crates,
273 unused_import_braces,
274 unused_qualifications,
275 unused_results,
276 unused_variables,
277 variant_size_differences
278)]
279#![allow(clippy::uninlined_format_args)]
280
281#[cfg(feature = "macros")]
282mod macros;
283#[cfg(feature = "std")]
284mod tabled;
285mod util;
286
287#[cfg(feature = "assert")]
288#[cfg_attr(docsrs, doc(cfg(feature = "assert")))]
289pub mod assert;
290#[cfg(feature = "std")]
291#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
292pub mod builder;
293#[cfg(feature = "derive")]
294#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
295pub mod derive;
296pub mod grid;
297pub mod iter;
298pub mod settings;
299pub mod tables;
300
301#[cfg(feature = "std")]
302#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
303pub use crate::{tabled::Tabled, tables::Table};
304
305#[cfg(feature = "derive")]
306#[cfg_attr(docsrs, doc(cfg(feature = "derive")))]
307pub use derive::Tabled;