Repository: zhiburt/tabled
Pull request #64 (2022-02-06 22:37:40)

Improve Style customization


Patch:
diff --git a/README.md b/README.md
index e332584..3cd872e 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ An easy to use library for pretty printing tables of Rust `struct`s and `enum`s.
 ## Agenda
 
 * [Usage](#Usage)
-* [Modificators](#Modificators)
+* [Settings](#Settings)
     * [Style](#Style)
         * [ASCII](#ASCII)
         * [Psql](#Psql)
@@ -100,17 +100,21 @@ let some_numbers = [1, 2, 3];
 let table = some_numbers.table();
 ```
 
-## Modificators
+## Settings
+
+In this section is listened a set of settings you can apply for your table.
 
 ### Style
 
 There are a list of ready to use styles.
-But a custom style can be created as well.
+Each style can be castomized.
+
+A custom style also can be created from scratch.
 
 A style can be used by passing it to `.with` method of `Table`.
 
 ```rust
-let table = Table::new(&data).with(Style::PSQL);
+let table = Table::new(&data).with(Style::psql());
 ```
 
 Bellow rendered a list of pre configured styles.
@@ -142,7 +146,7 @@ Please open an issue.
   Go  |    Rob Pike    |     2009      
 ```
 
-#### GithubMarkdown
+#### Github Markdown
 
 ```
 | name |  designed_by   | invented_year |
@@ -152,7 +156,7 @@ Please open an issue.
 |  Go  |    Rob Pike    |     2009      |
 ```
 
-#### Pseudo
+#### Modern
 
 ```
 ┌──────┬────────────────┬───────────────┐
@@ -166,19 +170,7 @@ Please open an issue.
 └──────┴────────────────┴───────────────┘
 ```
 
-#### PseudoClean
-
-```
-┌──────┬────────────────┬───────────────┐
-│ name │  designed_by   │ invented_year │
-├──────┼────────────────┼───────────────┤
-│  C   │ Dennis Ritchie │     1972      │
-│ Rust │ Graydon Hoare  │     2010      │
-│  Go  │    Rob Pike    │     2009      │
-└──────┴────────────────┴───────────────┘
-```
-
-#### NoBorder
+#### Blank
 
 ```
  name    designed_by     invented_year 
@@ -189,17 +181,25 @@ Please open an issue.
 
 #### Custom
 
-You can modify existing styles to fits your needs.
+You can modify existing styles to fit your needs.
 
 ```rust
-let style = tabled::Style::NO_BORDER
-                .frame_bottom(Some(Line::short('*', ' ')))
-                .split(Some(Line::short(' ', ' ')))
-                .inner(' ');
+let style = Style::modern().header_off().horizontal_off();
+```
+
+The style will look like the following.
 
-let table = Table::new(&data).with(style);
+```rust
+┌──────┬────────────────┬───────────────┐
+│ name │  designed_by   │ invented_year │
+│  C   │ Dennis Ritchie │     1972      │
+│ Rust │ Graydon Hoare  │     2010      │
+│  Go  │    Rob Pike    │     2009      │
+└──────┴────────────────┴───────────────┘
 ```
 
+You can find more methods which are available in the [documentation]()
+
 ### Alignment
 
 You can set a horizontal and vertical alignment for a `Header`, `Column`, `Row` or `Full` set of cells.
@@ -218,7 +218,7 @@ The `Format` function provides an interface for a modification of cells.
 
 ```rust
 Table::new(&data)
-    .with(Style::PSQL),
+    .with(Style::psql()),
     .with(Modify::new(Column(..)).with(Format(|s| format!("<< {} >>", s))))
     .with(Modify::new(Row(..1)).with(Format(|s| format!("Head {}", s))));
 ```
@@ -227,7 +227,7 @@ It's also possible to use functions with signature `Fn(&str) -> String` as a for
 
 ```rust
 Table::new(&data)
-    .with(Style::PSQL),
+    .with(Style::psql()),
     .with(Modify::new(Column(..)).with(|s: &str| format!("<< {} >>", s)))
     .with(Modify::new(Row(..1)).with(str::to_lowercase));
 ```
@@ -462,7 +462,7 @@ The library doesn't bind you in usage of any color library but to be able to wor
 
 ```rust
 Table::new(&data)
-    .with(Style::PSQL)
+    .with(Style::psql())
     .with(Modify::new(Column(..1)).with(Format(|s| s.red().to_string())))
     .with(Modify::new(Column(1..2)).with(Format(|s| s.blue().to_string())))
     .with(Modify::new(Column(2..)).with(Format(|s| s.green().to_string())));
@@ -495,7 +495,7 @@ let data = vec![
     (Developer("Maxim Zhiburt"), Domain::Unknown),
 ];
 
-let table = Table::new(data).with(Style::PSQL).to_string();
+let table = Table::new(data).with(Style::psql()).to_string();
 
 assert_eq!(
     table,
@@ -608,7 +608,7 @@ fn main() {
         .add_row(["1", "English"])
         .add_row(["2", "Deutsch"])
         .build()
-        .with(Style::PSQL);
+        .with(Style::psql());
 
     println!("{}", table);
 }
diff --git a/benches/table_build.rs b/benches/table_build.rs
index 49f4eb1..4db8261 100644
--- a/benches/table_build.rs
+++ b/benches/table_build.rs
@@ -46,7 +46,7 @@ table_bench!(small_table, {
 table_bench!(
     small_table_stylish,
     [0; 3],
-    Style::PSEUDO,
+    Style::modern(),
     Modify::new(Full)
         .with(Alignment::left())
         .with(Alignment::top())
diff --git a/examples/basic.rs b/examples/basic.rs
index 7884595..e53e304 100644
--- a/examples/basic.rs
+++ b/examples/basic.rs
@@ -44,7 +44,7 @@ fn main() {
     ];
 
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Modify::new(Head).with(Alignment::Horizontal(AlignmentHorizontal::Center)))
         .with(Modify::new(Row(1..)).with(Alignment::Horizontal(AlignmentHorizontal::Left)));
 
diff --git a/examples/builder.rs b/examples/builder.rs
index 5d8358f..76b66bf 100644
--- a/examples/builder.rs
+++ b/examples/builder.rs
@@ -20,7 +20,7 @@ fn main() {
         .with(Header(link))
         .with(Panel("=".repeat(link.len()), 2))
         .with(Modify::new(Row(1..2)).with(MaxWidth::wrapping(link.len())))
-        .with(Style::GITHUB_MARKDOWN);
+        .with(Style::github_markdown());
 
     println!("{}", table);
 }
diff --git a/examples/color.rs b/examples/color.rs
index 62625d0..f8f6290 100644
--- a/examples/color.rs
+++ b/examples/color.rs
@@ -48,7 +48,7 @@ fn main() {
     ];
 
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Head).with(Alignment::center_horizontal()))
         .with(Modify::new(Row(1..)).with(Alignment::left()))
         .with(Modify::new(Column(1..2)).with(Format(|s| s.blue().to_string())))
diff --git a/examples/concat.rs b/examples/concat.rs
index f21bb6a..062bec6 100644
--- a/examples/concat.rs
+++ b/examples/concat.rs
@@ -51,7 +51,7 @@ fn main() {
 
     let data_table = weather_table
         .with(Concat::horizontal(location_table))
-        .with(Style::PSEUDO_CLEAN);
+        .with(Style::modern().horizontal_off());
 
     println!("data");
     println!("{}", data_table);
diff --git a/examples/custom_style.rs b/examples/custom_style.rs
new file mode 100644
index 0000000..8ed3f68
--- /dev/null
+++ b/examples/custom_style.rs
@@ -0,0 +1,44 @@
+//! The example can be run by this command
+//! `cargo run --example custom_style`
+
+use tabled::{Alignment, Full, Modify, Style, Table, Tabled};
+
+#[derive(Tabled)]
+struct CodeEditor {
+    name: &'static str,
+    first_release: &'static str,
+    developer: &'static str,
+}
+
+impl CodeEditor {
+    fn new(name: &'static str, first_release: &'static str, developer: &'static str) -> Self {
+        Self {
+            name,
+            first_release,
+            developer,
+        }
+    }
+}
+
+fn main() {
+    let data = [
+        CodeEditor::new("Sublime Text 3", "2008", "Sublime HQ"),
+        CodeEditor::new("Visual Studio Code", "2015", "Microsoft"),
+        CodeEditor::new("Notepad++", "2003", "Don Ho"),
+        CodeEditor::new("GNU Emacs", "1984", "Richard Stallman"),
+        CodeEditor::new("Neovim", "2015", "Vim community"),
+    ];
+
+    let table = Table::new(&data)
+        .with(
+            Style::modern()
+                .horizontal_off()
+                .vertical_off()
+                .header(' ')
+                .left_header_intersection('│')
+                .right_header_intersection('│'),
+        )
+        .with(Modify::new(Full).with(Alignment::left()));
+
+    println!("{}", table);
+}
diff --git a/examples/default_array.rs b/examples/default_array.rs
index 4c77c83..84e99b0 100644
--- a/examples/default_array.rs
+++ b/examples/default_array.rs
@@ -5,7 +5,7 @@ use tabled::{Style, Table};
 
 fn main() {
     let data = matrix::<10>();
-    let table = Table::new(&data).with(Style::PSEUDO);
+    let table = Table::new(&data).with(Style::modern());
 
     println!("{}", table);
 }
diff --git a/examples/format.rs b/examples/format.rs
index c296c02..7b9a9ba 100644
--- a/examples/format.rs
+++ b/examples/format.rs
@@ -34,7 +34,7 @@ fn main() {
     ];
 
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Row(..1)).with(FormatWithIndex(|_, _, column| column.to_string())))
         .with(Modify::new(Row(1..2).not(Column(..1))).with(FormatFrom(vec!["qwe", "asd"])))
         .with(Modify::new(Column(..1).not(Row(..1))).with(Format(|s| format!("{}...", s))));
diff --git a/examples/highlight.rs b/examples/highlight.rs
index 1405d15..1588288 100644
--- a/examples/highlight.rs
+++ b/examples/highlight.rs
@@ -6,7 +6,7 @@ use tabled::{Border, Highlight, Style, TableIteratorExt};
 fn main() {
     let data = vec![["A", "B", "C"], ["D", "E", "F"], ["G", "H", "I"]];
 
-    let table = data.table().with(Style::PSEUDO).with(Highlight::cell(
+    let table = data.table().with(Style::modern()).with(Highlight::cell(
         2,
         1,
         Border::full('*', '*', '*', '*', '*', '*', '*', '*'),
diff --git a/examples/inline.rs b/examples/inline.rs
index 96a6d3b..d66096c 100644
--- a/examples/inline.rs
+++ b/examples/inline.rs
@@ -40,7 +40,7 @@ fn main() {
     ];
 
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Modify::new(Full).with(Indent::new(1, 1, 0, 0)))
         .with(Modify::new(Head).with(Alignment::Horizontal(AlignmentHorizontal::Left)))
         .with(Modify::new(Row(1..)).with(Alignment::Horizontal(AlignmentHorizontal::Center)));
diff --git a/examples/panel.rs b/examples/panel.rs
index 38db0f2..7ca810d 100644
--- a/examples/panel.rs
+++ b/examples/panel.rs
@@ -36,7 +36,7 @@ fn main() {
     let table = Table::new(&data)
         .with(Header("Tabled Releases"))
         .with(Footer(format!("N - {}", data.len())))
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Modify::new(Full).with(Alignment::Horizontal(AlignmentHorizontal::Center)));
 
     println!("{}", table);
diff --git a/examples/rotate.rs b/examples/rotate.rs
index 10fd919..ea4147b 100644
--- a/examples/rotate.rs
+++ b/examples/rotate.rs
@@ -28,7 +28,7 @@ fn main() {
 
     let table = Table::new(&data)
         .with(Rotate::Left)
-        .with(Style::BLANK)
+        .with(Style::blank())
         .with(Modify::new(Full).with(Indent::new(1, 1, 0, 0)));
 
     println!("{}", table);
diff --git a/examples/top_border_text.rs b/examples/top_border_text.rs
index 65fb9a2..5d0ce0e 100644
--- a/examples/top_border_text.rs
+++ b/examples/top_border_text.rs
@@ -7,7 +7,7 @@ fn main() {
     let data = [[5, 6, 7, 8, 9], [10, 11, 12, 13, 14]];
 
     let table = Table::new(&data)
-        .with(Style::PSEUDO_CLEAN.split(None))
+        .with(Style::modern().horizontal_off())
         .with(TopBorderText::new("┌ Columns "))
         .with(Modify::new(Full).with(Alignment::left()));
 
diff --git a/examples/width.rs b/examples/width.rs
index b11d52e..c39a347 100644
--- a/examples/width.rs
+++ b/examples/width.rs
@@ -10,7 +10,7 @@ fn main() {
         ["Hello World", "[[[[[[[[[[[[[[[[["],
     ];
 
-    let table = Table::new(&data).with(Style::GITHUB_MARKDOWN).with(
+    let table = Table::new(&data).with(Style::github_markdown()).with(
         Modify::new(Full)
             .with(MaxWidth::truncating(10, "..."))
             .with(Alignment::left()),
diff --git a/src/builder.rs b/src/builder.rs
index 5f11f80..46c8856 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -237,7 +237,7 @@ fn create_table_from_grid(mut grid: Grid) -> Table {
     );
 
     let table = Table { grid };
-    table.with(Style::ASCII)
+    table.with(Style::ascii())
 }
 
 fn append_vec(v: &mut Vec<String>, n: usize, value: String) {
diff --git a/src/lib.rs b/src/lib.rs
index b2aa744..35d80e4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -130,7 +130,7 @@
 //!     (Developer("Maxim Zhiburt"), Domain::Unknown),
 //! ];
 //!     
-//! let table = Table::new(data).with(Style::PSQL).to_string();
+//! let table = Table::new(data).with(Style::psql()).to_string();
 //!
 //! assert_eq!(
 //!     table,
diff --git a/src/style.rs b/src/style.rs
index e62e56e..d90fc10 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -1,35 +1,99 @@
-use std::borrow::Cow;
+//! This module contains a list of Styles which can be applied to change [Table] styles.
+
+use std::{borrow::Cow, marker::PhantomData};
 
 #[allow(unused)]
 use crate::Table;
 use crate::TableOption;
 use papergrid::{Border, Entity, Grid, Settings};
 
-/// Style is responsible for a look of a [Table].
+/// Style is represents a theme of a [Table].
+///
+/// It can be Mofified extensively, look at [CustomStyle] methods.
 ///
 /// # Example
 ///
 /// ```rust,no_run
-/// use tabled::{Table, Style, style::Line};
+/// use tabled::{Table, Style};
+///
+/// let style = Style::ascii()
+///                 .bottom('*')
+///                 .inner_intersection(' ');
+///
 /// let data = vec!["Hello", "2021"];
-/// let table = Table::new(&data).with(
-///                 Style::NO_BORDER
-///                     .frame_bottom(Some(Line::short('*', ' ')))
-///                     .split(Some(Line::short('*', ' ')))
-///                     .inner(' ')
-///             )
-///             .to_string();
+/// let table = Table::new(&data).with(style).to_string();
 ///
 /// println!("{}", table);
 /// ```
-pub struct Style {
-    frame: Frame,
-    header_split_line: Option<Line>,
-    split: Option<Line>,
-    inner_split_char: char,
-}
+pub struct Style;
 
 impl Style {
+    #[deprecated(note = "Use ascii() function")]
+    pub const ASCII: StyleSettings = Self::_ASCII;
+
+    #[deprecated(note = "Use blank() function")]
+    pub const BLANK: StyleSettings = Self::_BLANK;
+
+    #[deprecated(note = "Use psql() function")]
+    pub const PSQL: StyleSettings = Self::_PSQL;
+
+    #[deprecated(note = "Use github_markdown() function")]
+    pub const GITHUB_MARKDOWN: StyleSettings = Self::_GITHUB_MARKDOWN;
+
+    #[deprecated(note = "Use modern() function")]
+    pub const PSEUDO: StyleSettings = Self::_MODERN;
+
+    #[deprecated(note = "Use modern().horizontal_off() function")]
+    pub const PSEUDO_CLEAN: StyleSettings = Self::modern().horizontal_off().inner;
+
+    #[deprecated(note = "Use modern_extended() function")]
+    pub const EXTENDED: StyleSettings = Self::_EXTENDED;
+
+    #[deprecated(note = "Use dots() function")]
+    pub const ASCII_DOTS: StyleSettings = Self::_DOTS;
+
+    #[deprecated(note = "Use re_structured_text() function")]
+    pub const RE_STRUCTURED_TEXT: StyleSettings = Self::_RE_STRUCTURED_TEXT;
+
+    /// Empty style is a style with no styling options on,
+    ///
+    /// ```text
+    ///      id  destribution            link
+    ///      0      Fedora      https://getfedora.org/
+    ///      2     OpenSUSE    https://www.opensuse.org/
+    ///      3   Endeavouros   https://endeavouros.com/
+    /// ```
+    ///
+    /// Note: The cells in the example have 1-left and 1-right indent.
+    ///
+    /// It's usefull as a scratch style to build a custom one.
+    ///
+    /// ```rust,no_run
+    /// # use tabled::Style;
+    /// let style = Style::empty()
+    ///     .top('*')
+    ///     .bottom('*')
+    ///     .header('x')
+    ///     .vertical('#')
+    ///     .bottom_intersection('^')
+    ///     .top_intersection('*');
+    /// ```
+    pub const fn empty() -> CustomStyle<(), (), (), (), (), (), ()> {
+        CustomStyle::new(StyleSettings::new(Frame::empty(), None, None, None))
+    }
+
+    /// Blank style looks like the following table
+    ///
+    /// ```text
+    ///      id   destribution             link
+    ///      0       Fedora       https://getfedora.org/
+    ///      2      OpenSUSE     https://www.opensuse.org/
+    ///      3    Endeavouros    https://endeavouros.com/
+    /// ```
+    pub const fn blank() -> CustomStyle<(), (), (), (), (), On, ()> {
+        CustomStyle::new(Self::_BLANK)
+    }
+
     /// Default style looks like the following table
     ///
     /// ```text
@@ -43,38 +107,26 @@ impl Style {
     ///     | 3  | Endeavouros  | https://endeavouros.com/  |
     ///     +----+--------------+---------------------------+
     /// ```
-    pub const ASCII: Self = Self::new(
-        Frame {
-            bottom: Some(Line::bordered('-', '+', '+', '+')),
-            top: Some(Line::bordered('-', '+', '+', '+')),
-            left: Some('|'),
-            right: Some('|'),
-        },
-        Some(Line::bordered('-', '+', '+', '+')),
-        Some(Line::bordered('-', '+', '+', '+')),
-        '|',
-    );
-
-    /// Noborder style looks like the following table
-    ///
-    /// ```text
-    ///      id   destribution             link
-    ///      0       Fedora       https://getfedora.org/
-    ///      2      OpenSUSE     https://www.opensuse.org/
-    ///      3    Endeavouros    https://endeavouros.com/
-    /// ```
-    #[deprecated(note = "Renamed to BLANK")]
-    pub const NO_BORDER: Self = Self::new(Frame::empty(), None, None, ' ');
+    pub const fn ascii() -> CustomStyle<On, On, On, On, On, On, On> {
+        CustomStyle::new(Self::_ASCII)
+    }
 
-    /// Noborder style looks like the following table
+    /// Dots style looks like the following table
     ///
     /// ```text
-    ///      id   destribution             link
-    ///      0       Fedora       https://getfedora.org/
-    ///      2      OpenSUSE     https://www.opensuse.org/
-    ///      3    Endeavouros    https://endeavouros.com/
+    ///     .................................................
+    ///     : id : destribution :           link            :
+    ///     :....:..............:...........................:
+    ///     : 0  :    Fedora    :  https://getfedora.org/   :
+    ///     :....:..............:...........................:
+    ///     : 2  :   OpenSUSE   : https://www.opensuse.org/ :
+    ///     :....:..............:...........................:
+    ///     : 3  : Endeavouros  : https://endeavouros.com/  :
+    ///     :....:..............:...........................:
     /// ```
-    pub const BLANK: Self = Self::new(Frame::empty(), None, None, ' ');
+    pub const fn dots() -> CustomStyle<On, On, On, On, On, On, On> {
+        CustomStyle::new(Self::_DOTS)
+    }
 
     /// Psql style looks like the following table
     ///
@@ -85,7 +137,9 @@ impl Style {
     ///      2  |   OpenSUSE   | https://www.opensuse.org/
     ///      3  | Endeavouros  | https://endeavouros.com/
     /// ```
-    pub const PSQL: Self = Self::new(Frame::empty(), Some(Line::short('-', '+')), None, '|');
+    pub const fn psql() -> CustomStyle<(), (), (), (), (), On, On> {
+        CustomStyle::new(Self::_PSQL)
+    }
 
     /// Github_markdown style looks like the following table
     ///
@@ -96,19 +150,13 @@ impl Style {
     ///     | 2  |   OpenSUSE   | https://www.opensuse.org/ |
     ///     | 3  | Endeavouros  | https://endeavouros.com/  |
     /// ```
-    pub const GITHUB_MARKDOWN: Self = Self::new(
-        Frame {
-            left: Some('|'),
-            right: Some('|'),
-            bottom: None,
-            top: None,
-        },
-        Some(Line::bordered('-', '+', '|', '|')),
-        None,
-        '|',
-    );
+    pub const fn github_markdown() -> CustomStyle<(), (), On, On, (), On, On> {
+        CustomStyle::new(Self::_GITHUB_MARKDOWN)
+    }
 
-    /// Pseudo style looks like the following table
+    /// Modern style looks like the following table.
+    ///
+    /// Beware: It uses UTF8 characters.
     ///
     /// ```text
     ///     ┌────┬──────────────┬───────────────────────────┐
@@ -121,43 +169,14 @@ impl Style {
     ///     │ 3  │ Endeavouros  │ https://endeavouros.com/  │
     ///     └────┴──────────────┴───────────────────────────┘
     /// ```
-    pub const PSEUDO: Self = Self::new(
-        Frame {
-            left: Some('│'),
-            right: Some('│'),
-            bottom: Some(Line::bordered('─', '┴', '└', '┘')),
-            top: Some(Line::bordered('─', '┬', '┌', '┐')),
-        },
-        Some(Line::bordered('─', '┼', '├', '┤')),
-        Some(Line::bordered('─', '┼', '├', '┤')),
-        '│',
-    );
-
-    /// Pseudo_clean style looks like the following table
-    ///
-    /// ```text
-    ///     ┌────┬──────────────┬───────────────────────────┐
-    ///     │ id │ destribution │           link            │
-    ///     ├────┼──────────────┼───────────────────────────┤
-    ///     │ 0  │    Fedora    │  https://getfedora.org/   │
-    ///     │ 2  │   OpenSUSE   │ https://www.opensuse.org/ │
-    ///     │ 3  │ Endeavouros  │ https://endeavouros.com/  │
-    ///     └────┴──────────────┴───────────────────────────┘
-    /// ```
-    pub const PSEUDO_CLEAN: Self = Self::new(
-        Frame {
-            left: Some('│'),
-            right: Some('│'),
-            bottom: Some(Line::bordered('─', '┴', '└', '┘')),
-            top: Some(Line::bordered('─', '┬', '┌', '┐')),
-        },
-        Some(Line::bordered('─', '┼', '├', '┤')),
-        None,
-        '│',
-    );
+    pub const fn modern() -> CustomStyle<On, On, On, On, On, On, On> {
+        CustomStyle::new(Self::_MODERN)
+    }
 
     /// Extended style looks like the following table
     ///
+    /// Beware: It uses UTF8 characters.
+    ///
     /// ```text
     ///     ╔════╦══════════════╦═══════════════════════════╗
     ///     ║ id ║ destribution ║           link            ║
@@ -169,7 +188,67 @@ impl Style {
     ///     ║ 3  ║ Endeavouros  ║ https://endeavouros.com/  ║
     ///     ╚════╩══════════════╩═══════════════════════════╝
     /// ```
-    pub const EXTENDED: Self = Self::new(
+    pub const fn extended() -> CustomStyle<On, On, On, On, On, On, On> {
+        CustomStyle::new(Self::_EXTENDED)
+    }
+
+    /// ReStructuredText style looks like the following table
+    ///
+    /// ```text
+    ///     ==== ============== ===========================
+    ///      id   destribution             link            
+    ///     ==== ============== ===========================
+    ///      0       Fedora       https://getfedora.org/   
+    ///      2      OpenSUSE     https://www.opensuse.org/
+    ///      3    Endeavouros    https://endeavouros.com/  
+    ///     ==== ============== ===========================
+    /// ```
+    pub const fn re_structured_text() -> CustomStyle<On, On, (), (), (), On, On> {
+        CustomStyle::new(Self::_RE_STRUCTURED_TEXT)
+    }
+
+    const _ASCII: StyleSettings = StyleSettings::new(
+        Frame {
+            bottom: Some(Line::bordered('-', '+', '+', '+')),
+            top: Some(Line::bordered('-', '+', '+', '+')),
+            left: Some('|'),
+            right: Some('|'),
+        },
+        Some(Line::bordered('-', '+', '+', '+')),
+        Some(Line::bordered('-', '+', '+', '+')),
+        Some('|'),
+    );
+
+    const _BLANK: StyleSettings = StyleSettings::new(Frame::empty(), None, None, Some(' '));
+
+    const _PSQL: StyleSettings =
+        StyleSettings::new(Frame::empty(), Some(Line::short('-', '+')), None, Some('|'));
+
+    const _GITHUB_MARKDOWN: StyleSettings = StyleSettings::new(
+        Frame {
+            left: Some('|'),
+            right: Some('|'),
+            bottom: None,
+            top: None,
+        },
+        Some(Line::bordered('-', '+', '|', '|')),
+        None,
+        Some('|'),
+    );
+
+    const _MODERN: StyleSettings = StyleSettings::new(
+        Frame {
+            left: Some('│'),
+            right: Some('│'),
+            bottom: Some(Line::bordered('─', '┴', '└', '┘')),
+            top: Some(Line::bordered('─', '┬', '┌', '┐')),
+        },
+        Some(Line::bordered('─', '┼', '├', '┤')),
+        Some(Line::bordered('─', '┼', '├', '┤')),
+        Some('│'),
+    );
+
+    const _EXTENDED: StyleSettings = StyleSettings::new(
         Frame {
             left: Some('║'),
             right: Some('║'),
@@ -178,23 +257,10 @@ impl Style {
         },
         Some(Line::bordered('═', '╬', '╠', '╣')),
         Some(Line::bordered('═', '╬', '╠', '╣')),
-        '║',
+        Some('║'),
     );
 
-    /// ASCII Dots style looks like the following table
-    ///
-    /// ```text
-    ///     .................................................
-    ///     : id : destribution :           link            :
-    ///     :....:..............:...........................:
-    ///     : 0  :    Fedora    :  https://getfedora.org/   :
-    ///     :....:..............:...........................:
-    ///     : 2  :   OpenSUSE   : https://www.opensuse.org/ :
-    ///     :....:..............:...........................:
-    ///     : 3  : Endeavouros  : https://endeavouros.com/  :
-    ///     :....:..............:...........................:
-    /// ```
-    pub const ASCII_DOTS: Self = Self::new(
+    const _DOTS: StyleSettings = StyleSettings::new(
         Frame {
             bottom: Some(Line::bordered('.', ':', ':', ':')),
             top: Some(Line::bordered('.', '.', '.', '.')),
@@ -203,21 +269,10 @@ impl Style {
         },
         Some(Line::bordered('.', ':', ':', ':')),
         None,
-        ':',
+        Some(':'),
     );
 
-    /// ReStructuredText style looks like the following table
-    ///
-    /// ```text
-    ///     ==== ============== ===========================
-    ///      id   destribution             link            
-    ///     ==== ============== ===========================
-    ///      0       Fedora       https://getfedora.org/   
-    ///      2      OpenSUSE     https://www.opensuse.org/
-    ///      3    Endeavouros    https://endeavouros.com/  
-    ///     ==== ============== ===========================
-    /// ```
-    pub const RE_STRUCTURED_TEXT: Self = Self::new(
+    const _RE_STRUCTURED_TEXT: StyleSettings = StyleSettings::new(
         Frame {
             bottom: Some(Line::short('=', ' ')),
             top: Some(Line::short('=', ' ')),
@@ -226,99 +281,25 @@ impl Style {
         },
         Some(Line::short('=', ' ')),
         None,
-        ' ',
+        Some(' '),
     );
+}
 
-    #[deprecated(note = "The name is not explicit. Use ASCII constant instead.")]
-    pub fn default() -> Self {
-        Self::ASCII
-    }
-
-    #[deprecated(note = "The name is not explicit. Use ASCII constant instead.")]
-    pub fn ascii() -> Self {
-        Self::ASCII
-    }
-
-    #[deprecated(note = "The name is not explicit. Use NO_BORDER constant instead.")]
-    pub fn noborder() -> Self {
-        Self::BLANK
-    }
-
-    #[deprecated(note = "The name is not explicit. Use PSQL constant instead.")]
-    pub fn psql() -> Self {
-        Self::PSQL
-    }
-
-    #[deprecated(note = "The name is not explicit. Use GITHUB_MARKDOWN constant instead.")]
-    pub fn github_markdown() -> Self {
-        Self::GITHUB_MARKDOWN
-    }
-
-    #[deprecated(note = "The name is not explicit. Use PSEUDO constant instead.")]
-    pub fn pseudo() -> Self {
-        Self::PSEUDO
-    }
-
-    #[deprecated(note = "The name is not explicit. Use PSEUDO_CLEAN constant instead.")]
-    pub fn pseudo_clean() -> Self {
-        Self::PSEUDO_CLEAN
-    }
-
-    #[deprecated(note = "Use EXTENDED constant instead.")]
-    pub fn extended() -> Self {
-        Self::EXTENDED
-    }
-
-    /// Left frame character.
-    pub fn frame_left(mut self, frame: Option<char>) -> Self {
-        self.frame.left = frame;
-        self
-    }
-
-    /// Right frame character.
-    pub fn frame_right(mut self, frame: Option<char>) -> Self {
-        self.frame.right = frame;
-        self
-    }
-
-    /// The header's top line.
-    ///
-    /// It's suppose that [Self::frame_bottom] and [Self::split]  has the same type of [Line] short or bordered.  
-    pub fn frame_top(mut self, frame: Option<Line>) -> Self {
-        self.frame.top = frame;
-        self
-    }
-
-    /// The footer's bottom line.
-    ///
-    /// It's suppose that [Self::frame_top] and [Self::split] has the same type of [Line] short or bordered.
-    pub fn frame_bottom(mut self, frame: Option<Line>) -> Self {
-        self.frame.bottom = frame;
-        self
-    }
-
-    /// The header's bottom line.
-    pub fn header(mut self, line: Option<Line>) -> Self {
-        self.header_split_line = line;
-        self
-    }
-
-    /// Row split line.
-    ///
-    /// [Self::frame_top] and [Self::frame_bottom]
-    pub fn split(mut self, line: Option<Line>) -> Self {
-        self.header_split_line = line.clone();
-        self.split = line;
-        self
-    }
-
-    /// Inner split character.
-    pub fn inner(mut self, c: char) -> Self {
-        self.inner_split_char = c;
-        self
-    }
+#[derive(Debug, Clone)]
+pub struct StyleSettings {
+    frame: Frame,
+    header_split_line: Option<Line>,
+    split: Option<Line>,
+    inner_split_char: Option<char>,
+}
 
-    const fn new(frame: Frame, header: Option<Line>, split: Option<Line>, inner: char) -> Self {
+impl StyleSettings {
+    const fn new(
+        frame: Frame,
+        header: Option<Line>,
+        split: Option<Line>,
+        inner: Option<char>,
+    ) -> Self {
         Self {
             frame,
             split,
@@ -330,29 +311,29 @@ impl Style {
 
 /// Line represents a horizontal line on a [Table].
 #[derive(Debug, Clone, Default)]
-pub struct Line {
+struct Line {
     main: char,
-    intersection: char,
+    intersection: Option<char>,
     left_corner: Option<char>,
     right_corner: Option<char>,
 }
 
 impl Line {
     /// A line for frame styles.
-    pub const fn bordered(main: char, intersection: char, left: char, right: char) -> Self {
+    const fn bordered(main: char, intersection: char, left: char, right: char) -> Self {
         Self {
-            intersection,
             main,
+            intersection: Some(intersection),
             left_corner: Some(left),
             right_corner: Some(right),
         }
     }
 
     /// A line for no-frame styles.
-    pub const fn short(main: char, intersection: char) -> Self {
+    const fn short(main: char, intersection: char) -> Self {
         Self {
             main,
-            intersection,
+            intersection: Some(intersection),
             left_corner: None,
             right_corner: None,
         }
@@ -378,7 +359,7 @@ impl Frame {
     }
 }
 
-impl TableOption for Style {
+impl TableOption for StyleSettings {
     fn change(&mut self, grid: &mut Grid) {
         grid.clear_split_grid();
         grid.clear_overide_split_lines();
@@ -387,13 +368,7 @@ impl TableOption for Style {
         let count_columns = grid.count_columns();
         for row in 0..count_rows {
             for column in 0..count_columns {
-                let border = make_style(
-                    self,
-                    row == 0,
-                    row + 1 == count_rows,
-                    column == 0,
-                    column + 1 == count_columns,
-                );
+                let border = make_style(self, row, column, count_rows, count_columns);
 
                 grid.set(
                     &Entity::Cell(row, column),
@@ -405,13 +380,18 @@ impl TableOption for Style {
 }
 
 fn make_style(
-    style: &Style,
-    is_first_row: bool,
-    is_last_row: bool,
-    is_first_column: bool,
-    is_last_column: bool,
+    style: &StyleSettings,
+    row: usize,
+    column: usize,
+    count_rows: usize,
+    count_columns: usize,
 ) -> Border {
-    match (is_first_row, is_last_row, is_first_column, is_last_column) {
+    let is_first_row = row == 0;
+    let is_last_row = row + 1 == count_rows;
+    let is_first_column = column == 0;
+    let is_last_column = column + 1 == count_columns;
+
+    let mut border = match (is_first_row, is_last_row, is_first_column, is_last_column) {
         // A table with a single cell
         (true, true, true, true) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
@@ -430,43 +410,40 @@ fn make_style(
             left: style.frame.left,
             left_top_corner: style.frame.top.as_ref().and_then(|l| l.left_corner),
             left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.left_corner),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
         },
         (true, true, false, true) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
             bottom: style.frame.bottom.as_ref().map(|l| l.main),
             left: style.frame.left,
-            left_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
-            right: Some(style.inner_split_char),
+            left_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
+            right: style.inner_split_char,
             right_top_corner: style.frame.top.as_ref().and_then(|l| l.right_corner),
             right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.right_corner),
         },
         (true, true, false, false) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
             bottom: style.frame.bottom.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
+            left: style.inner_split_char,
             left_top_corner: style.frame.top.as_ref().and_then(|l| l.left_corner),
-            left_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
+            left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
         },
         // Single column
         (true, false, true, true) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
-            bottom: style.header_split_line.as_ref().map(|l| l.main),
+            bottom: style.split.as_ref().map(|l| l.main),
             left: style.frame.left,
             left_top_corner: style.frame.top.as_ref().and_then(|l| l.left_corner),
-            left_bottom_corner: style.header_split_line.as_ref().and_then(|l| l.left_corner),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.left_corner),
             right: style.frame.right,
             right_top_corner: style.frame.top.as_ref().and_then(|l| l.right_corner),
-            right_bottom_corner: style
-                .header_split_line
-                .as_ref()
-                .and_then(|l| l.right_corner),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.right_corner),
         },
         (false, true, true, true) => Border {
             top: style.frame.bottom.as_ref().map(|l| l.main),
@@ -491,36 +468,33 @@ fn make_style(
         // General
         (true, false, true, false) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
-            bottom: style.header_split_line.as_ref().map(|l| l.main),
+            bottom: style.split.as_ref().map(|l| l.main),
             left: style.frame.left,
             left_top_corner: style.frame.top.as_ref().and_then(|l| l.left_corner),
-            left_bottom_corner: style.header_split_line.as_ref().and_then(|l| l.left_corner),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.header_split_line.as_ref().map(|l| l.intersection),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.left_corner),
+            right: style.inner_split_char,
+            right_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
         },
         (true, false, false, true) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
-            bottom: style.header_split_line.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.header_split_line.as_ref().map(|l| l.intersection),
+            bottom: style.split.as_ref().map(|l| l.main),
+            left: style.inner_split_char,
+            left_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
             right: style.frame.right,
             right_top_corner: style.frame.top.as_ref().and_then(|l| l.right_corner),
-            right_bottom_corner: style
-                .header_split_line
-                .as_ref()
-                .and_then(|l| l.right_corner),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.right_corner),
         },
         (true, false, false, false) => Border {
             top: style.frame.top.as_ref().map(|l| l.main),
-            bottom: style.header_split_line.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.header_split_line.as_ref().map(|l| l.intersection),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.frame.top.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.header_split_line.as_ref().map(|l| l.intersection),
+            bottom: style.split.as_ref().map(|l| l.main),
+            left: style.inner_split_char,
+            left_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.frame.top.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
         },
         (false, true, true, false) => Border {
             top: style.split.as_ref().map(|l| l.main),
@@ -528,16 +502,16 @@ fn make_style(
             left: style.frame.left,
             left_top_corner: style.split.as_ref().and_then(|l| l.left_corner),
             left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.left_corner),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.split.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
         },
         (false, true, false, true) => Border {
             top: style.split.as_ref().map(|l| l.main),
             bottom: style.frame.bottom.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.split.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
+            left: style.inner_split_char,
+            left_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
             right: style.frame.right,
             right_top_corner: style.split.as_ref().and_then(|l| l.right_corner),
             right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.right_corner),
@@ -545,12 +519,12 @@ fn make_style(
         (false, true, false, false) => Border {
             top: style.split.as_ref().map(|l| l.main),
             bottom: style.frame.bottom.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.split.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.split.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.frame.bottom.as_ref().map(|l| l.intersection),
+            left: style.inner_split_char,
+            left_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.frame.bottom.as_ref().and_then(|l| l.intersection),
         },
         (false, false, true, false) => Border {
             top: style.split.as_ref().map(|l| l.main),
@@ -558,16 +532,16 @@ fn make_style(
             left: style.frame.left,
             left_top_corner: style.split.as_ref().and_then(|l| l.left_corner),
             left_bottom_corner: style.split.as_ref().and_then(|l| l.left_corner),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.split.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.split.as_ref().map(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
         },
         (false, false, false, true) => Border {
             top: style.split.as_ref().map(|l| l.main),
             bottom: style.split.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.split.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.split.as_ref().map(|l| l.intersection),
+            left: style.inner_split_char,
+            left_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
             right: style.frame.right,
             right_top_corner: style.split.as_ref().and_then(|l| l.right_corner),
             right_bottom_corner: style.split.as_ref().and_then(|l| l.right_corner),
@@ -575,14 +549,83 @@ fn make_style(
         (false, false, false, false) => Border {
             top: style.split.as_ref().map(|l| l.main),
             bottom: style.split.as_ref().map(|l| l.main),
-            left: Some(style.inner_split_char),
-            left_top_corner: style.split.as_ref().map(|l| l.intersection),
-            left_bottom_corner: style.split.as_ref().map(|l| l.intersection),
-            right: Some(style.inner_split_char),
-            right_top_corner: style.split.as_ref().map(|l| l.intersection),
-            right_bottom_corner: style.split.as_ref().map(|l| l.intersection),
+            left: style.inner_split_char,
+            left_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            left_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right: style.inner_split_char,
+            right_top_corner: style.split.as_ref().and_then(|l| l.intersection),
+            right_bottom_corner: style.split.as_ref().and_then(|l| l.intersection),
         },
+    };
+
+    // override header style
+    if style.header_split_line.is_some() {
+        if row == 1 {
+            border.top = style.header_split_line.as_ref().map(|l| l.main);
+
+            if is_last_column {
+                border.right_top_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.right_corner);
+            } else {
+                border.right_top_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.intersection);
+            }
+
+            if is_first_column {
+                border.left_top_corner =
+                    style.header_split_line.as_ref().and_then(|l| l.left_corner);
+            } else {
+                border.left_top_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.intersection);
+            }
+        }
+
+        if row == 0 {
+            border.bottom = style.header_split_line.as_ref().map(|l| l.main);
+
+            if is_last_column {
+                border.right_bottom_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.right_corner);
+            } else {
+                border.right_bottom_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.intersection);
+            }
+
+            if is_first_column {
+                border.left_bottom_corner =
+                    style.header_split_line.as_ref().and_then(|l| l.left_corner);
+            } else {
+                border.left_bottom_corner = style
+                    .header_split_line
+                    .as_ref()
+                    .and_then(|l| l.intersection);
+            }
+        }
+    } else if count_columns > 1 {
+        if row == 1 {
+            border.top = None;
+            border.right_top_corner = None;
+            border.left_top_corner = None;
+        }
+
+        if row == 0 {
+            border.bottom = None;
+            border.right_bottom_corner = None;
+            border.left_bottom_corner = None;
+        }
     }
+
+    border
 }
 
 /// Style is responsible for a look of a [Table].
@@ -620,3 +663,609 @@ impl<'a> TableOption for TopBorderText<'a> {
         grid.override_split_line(0, self.text.as_ref())
     }
 }
+
+/// CustomStyle represents a style controlling a valid state of it.
+///
+/// For example.
+/// It doesn't allow to call method [CustomStyle::top_left_corner] unless [CustomStyle::left] and [CustomStyle::top] is set.
+#[derive(Debug, Clone)]
+pub struct CustomStyle<Top, Bottom, Left, Right, Horizontal, Vertical, Header> {
+    inner: StyleSettings,
+    _l_border: PhantomData<Left>,
+    _r_border: PhantomData<Right>,
+    _t_border: PhantomData<Top>,
+    _b_border: PhantomData<Bottom>,
+    _i_h_border: PhantomData<Horizontal>,
+    _i_v_border: PhantomData<Vertical>,
+    _h_border: PhantomData<Header>,
+}
+
+#[derive(Debug, Clone)]
+pub struct On;
+
+impl<Top, Bottom, Left, Rright, Horizontal, Vertical, Header>
+    CustomStyle<Top, Bottom, Left, Rright, Horizontal, Vertical, Header>
+{
+    const fn new(style: StyleSettings) -> Self {
+        Self {
+            inner: style,
+            _b_border: PhantomData,
+            _l_border: PhantomData,
+            _r_border: PhantomData,
+            _t_border: PhantomData,
+            _i_h_border: PhantomData,
+            _i_v_border: PhantomData,
+            _h_border: PhantomData,
+        }
+    }
+}
+
+impl<T, B, L, R, IH, IV, H> CustomStyle<T, B, L, R, IH, IV, H> {
+    /// Sets a top border.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn top(self, c: char) -> CustomStyle<On, B, L, R, IH, IV, H> {
+        let mut style = self.inner;
+
+        let mut top_line = Line {
+            main: c,
+            intersection: None,
+            left_corner: None,
+            right_corner: None,
+        };
+
+        if let Some(top) = style.frame.top {
+            top_line.intersection = top.intersection;
+            top_line.left_corner = top.left_corner;
+            top_line.left_corner = top.left_corner;
+        }
+
+        if style.frame.left.is_some() {
+            top_line.left_corner = Some(c);
+        }
+
+        if style.frame.right.is_some() {
+            top_line.right_corner = Some(c);
+        }
+
+        if style.inner_split_char.is_some() {
+            top_line.intersection = Some(c);
+        }
+
+        style.frame.top = Some(top_line);
+
+        CustomStyle::new(style)
+    }
+
+    /// Sets a bottom border.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn bottom(self, c: char) -> CustomStyle<T, On, L, R, IH, IV, H> {
+        let mut style = self.inner;
+        let mut bottom = match style.frame.bottom {
+            Some(mut line) => {
+                line.main = c;
+                line
+            }
+            None => Line {
+                main: c,
+                intersection: None,
+                left_corner: None,
+                right_corner: None,
+            },
+        };
+
+        if style.frame.left.is_some() {
+            bottom.left_corner = Some(c);
+        }
+
+        if style.frame.right.is_some() {
+            bottom.right_corner = Some(c);
+        }
+
+        if style.inner_split_char.is_some() {
+            bottom.intersection = Some(c);
+        }
+
+        style.frame.bottom = Some(bottom);
+
+        CustomStyle::new(style)
+    }
+
+    /// Sets a left border.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn left(self, c: char) -> CustomStyle<T, B, On, R, IH, IV, H> {
+        let mut style = self.inner;
+        style.frame.left = Some(c);
+
+        if let Some(mut top) = style.frame.top {
+            top.left_corner = Some(c);
+            style.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = style.frame.bottom {
+            bottom.left_corner = Some(c);
+            style.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = style.split {
+            split.left_corner = Some(c);
+            style.split = Some(split);
+        }
+
+        if let Some(mut split) = style.header_split_line {
+            split.left_corner = Some(c);
+            style.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(style)
+    }
+
+    /// Sets a right border.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn right(mut self, c: char) -> CustomStyle<T, B, L, On, IH, IV, H> {
+        self.inner.frame.right = Some(c);
+
+        if let Some(mut top) = self.inner.frame.top {
+            top.right_corner = Some(c);
+            self.inner.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = self.inner.frame.bottom {
+            bottom.right_corner = Some(c);
+            self.inner.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = self.inner.split {
+            split.right_corner = Some(c);
+            self.inner.split = Some(split);
+        }
+
+        if let Some(mut split) = self.inner.header_split_line {
+            split.right_corner = Some(c);
+            self.inner.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(self.inner)
+    }
+
+    /// Sets a horizontal split line.
+    ///
+    /// It doesn't include a header split line.
+    /// It must be set via its own method [Self::header].
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn horizontal(self, c: char) -> CustomStyle<T, B, L, R, On, IV, H> {
+        let mut style = self.inner;
+        let mut split = match style.split {
+            Some(line) => line,
+            None => Line {
+                main: '\0',
+                intersection: None,
+                left_corner: None,
+                right_corner: None,
+            },
+        };
+
+        split.main = c;
+
+        if style.frame.left.is_some() {
+            split.left_corner = Some(c);
+        }
+
+        if style.frame.right.is_some() {
+            split.right_corner = Some(c);
+        }
+
+        if style.inner_split_char.is_some() {
+            split.intersection = Some(c);
+        }
+
+        style.split = Some(split);
+
+        CustomStyle::new(style)
+    }
+
+    /// Sets a vertical split line.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn vertical(self, c: char) -> CustomStyle<T, B, L, R, IH, On, H> {
+        let mut style = self.inner;
+        style.inner_split_char = Some(c);
+
+        if let Some(mut split) = style.split {
+            split.intersection = Some(c);
+            style.split = Some(split);
+        }
+
+        if let Some(mut top) = style.frame.top {
+            top.intersection = Some(c);
+            style.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = style.frame.bottom {
+            bottom.intersection = Some(c);
+            style.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = style.header_split_line {
+            split.intersection = Some(c);
+            style.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(style)
+    }
+
+    /// Sets a 1st horizontal split line.
+    ///
+    /// Any corners and intersections which were set will be overriden.
+    pub const fn header(self, c: char) -> CustomStyle<T, B, L, R, IH, IV, On> {
+        let mut style = self.inner;
+        let mut split = match style.header_split_line {
+            Some(line) => line,
+            None => Line {
+                main: '\0',
+                intersection: None,
+                left_corner: None,
+                right_corner: None,
+            },
+        };
+
+        split.main = c;
+
+        if style.frame.left.is_some() {
+            split.left_corner = Some(c);
+        }
+
+        if style.frame.right.is_some() {
+            split.right_corner = Some(c);
+        }
+
+        if style.inner_split_char.is_some() {
+            split.intersection = Some(c);
+        }
+
+        style.header_split_line = Some(split);
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<B, R, IH, IV, H> CustomStyle<On, B, On, R, IH, IV, H> {
+    /// Sets a top left corner.
+    pub const fn top_left_corner(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.top {
+            Some(mut top) => {
+                top.left_corner = Some(c);
+                style.frame.top = Some(top);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<B, L, IH, IV, H> CustomStyle<On, B, L, On, IH, IV, H> {
+    /// Sets a top right corner.
+    pub const fn top_right_corner(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.top {
+            Some(mut top) => {
+                top.right_corner = Some(c);
+                style.frame.top = Some(top);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, L, IH, IV, H> CustomStyle<T, On, L, On, IH, IV, H> {
+    /// Sets a bottom right corner.
+    pub const fn bottom_right_corner(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.bottom {
+            Some(mut bottom) => {
+                bottom.right_corner = Some(c);
+                style.frame.bottom = Some(bottom);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, R, IH, IV, H> CustomStyle<T, On, On, R, IH, IV, H> {
+    /// Sets a bottom left corner.
+    pub const fn bottom_left_corner(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.bottom {
+            Some(mut bottom) => {
+                bottom.left_corner = Some(c);
+                style.frame.bottom = Some(bottom);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, R, IV, H> CustomStyle<T, B, On, R, On, IV, H> {
+    /// Sets a left intersection char.
+    pub const fn left_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.split {
+            Some(mut split) => {
+                split.left_corner = Some(c);
+                style.split = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        match style.header_split_line {
+            Some(mut split) => {
+                split.left_corner = Some(c);
+                style.header_split_line = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, L, IV, H> CustomStyle<T, B, L, On, On, IV, H> {
+    /// Sets a right intersection char.
+    pub const fn right_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.split {
+            Some(mut split) => {
+                split.right_corner = Some(c);
+                style.split = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        match style.header_split_line {
+            Some(mut split) => {
+                split.right_corner = Some(c);
+                style.header_split_line = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<B, L, R, IH, H> CustomStyle<On, B, L, R, IH, On, H> {
+    /// Sets a top intersection char.
+    pub const fn top_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.top {
+            Some(mut top) => {
+                top.intersection = Some(c);
+                style.frame.top = Some(top);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, L, R, IH, H> CustomStyle<T, On, L, R, IH, On, H> {
+    /// Sets a bottom intersection char.
+    pub const fn bottom_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.frame.bottom {
+            Some(mut bottom) => {
+                bottom.intersection = Some(c);
+                style.frame.bottom = Some(bottom);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, L, R, H> CustomStyle<T, B, L, R, On, On, H> {
+    /// Sets an inner intersection char.
+    /// A char between horizontal and vertical split lines.
+    pub const fn inner_intersection(mut self, c: char) -> Self {
+        match self.inner.split {
+            Some(mut split) => {
+                split.intersection = Some(c);
+                self.inner.split = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, L, R, IH> CustomStyle<T, B, L, R, IH, On, On> {
+    /// Sets an intersection char of a 1st horizontal split line.
+    pub const fn header_intersection(mut self, c: char) -> Self {
+        match self.inner.header_split_line {
+            Some(mut split) => {
+                split.intersection = Some(c);
+                self.inner.header_split_line = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, R, IH, IV> CustomStyle<T, B, On, R, IH, IV, On> {
+    /// Sets an left intersection char of a 1st horizontal split line.
+    pub const fn left_header_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.header_split_line {
+            Some(mut split) => {
+                split.left_corner = Some(c);
+                style.header_split_line = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, L, IH, IV> CustomStyle<T, B, L, On, IH, IV, On> {
+    /// Sets an right intersection char of a 1st horizontal split line.
+    pub const fn right_header_intersection(self, c: char) -> Self {
+        let mut style = self.inner;
+        match style.header_split_line {
+            Some(mut split) => {
+                split.right_corner = Some(c);
+                style.header_split_line = Some(split);
+            }
+            None => unreachable!(),
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<B, L, R, IH, IV, H> CustomStyle<On, B, L, R, IH, IV, H> {
+    /// Removes top border.
+    pub const fn top_off(self) -> CustomStyle<(), B, L, R, IH, IV, H> {
+        let mut style = self.inner;
+        style.frame.top = None;
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, L, R, IH, IV, H> CustomStyle<T, On, L, R, IH, IV, H> {
+    /// Removes bottom border.
+    pub const fn bottom_off(self) -> CustomStyle<T, (), L, R, IH, IV, H> {
+        let mut style = self.inner;
+        style.frame.bottom = None;
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, R, IH, IV, H> CustomStyle<T, B, On, R, IH, IV, H> {
+    /// Removes left border.
+    pub const fn left_off(self) -> CustomStyle<T, B, (), R, IH, IV, H> {
+        let mut style = self.inner;
+        style.frame.left = None;
+
+        if let Some(mut top) = style.frame.top {
+            top.left_corner = None;
+            style.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = style.frame.bottom {
+            bottom.left_corner = None;
+            style.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = style.split {
+            split.left_corner = None;
+            style.split = Some(split);
+        }
+
+        if let Some(mut split) = style.header_split_line {
+            split.left_corner = None;
+            style.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(style)
+    }
+}
+
+impl<T, B, L, IH, IV, H> CustomStyle<T, B, L, On, IH, IV, H> {
+    /// Removes right border.
+    pub const fn right_off(mut self) -> CustomStyle<T, B, L, (), IH, IV, H> {
+        self.inner.frame.right = None;
+
+        if let Some(mut top) = self.inner.frame.top {
+            top.right_corner = None;
+            self.inner.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = self.inner.frame.bottom {
+            bottom.right_corner = None;
+            self.inner.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = self.inner.split {
+            split.right_corner = None;
+            self.inner.split = Some(split);
+        }
+
+        if let Some(mut split) = self.inner.header_split_line {
+            split.right_corner = None;
+            self.inner.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, L, R, IV, H> CustomStyle<T, B, L, R, On, IV, H> {
+    /// Removes horizontal split lines.
+    ///
+    /// Not including 1st split line.
+    pub const fn horizontal_off(mut self) -> CustomStyle<T, B, L, R, (), IV, H> {
+        self.inner.split = None;
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, L, R, IH, H> CustomStyle<T, B, L, R, IH, On, H> {
+    /// Removes vertical split lines.
+    pub const fn vertical_off(mut self) -> CustomStyle<T, B, L, R, IH, (), H> {
+        self.inner.inner_split_char = None;
+
+        if let Some(mut split) = self.inner.split {
+            split.intersection = None;
+            self.inner.split = Some(split);
+        }
+
+        if let Some(mut top) = self.inner.frame.top {
+            top.intersection = None;
+            self.inner.frame.top = Some(top);
+        }
+
+        if let Some(mut bottom) = self.inner.frame.bottom {
+            bottom.intersection = None;
+            self.inner.frame.bottom = Some(bottom);
+        }
+
+        if let Some(mut split) = self.inner.header_split_line {
+            split.intersection = None;
+            self.inner.header_split_line = Some(split);
+        }
+
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, L, R, IH, IV> CustomStyle<T, B, L, R, IH, IV, On> {
+    /// Removes 1st horizontal split line.
+    pub const fn header_off(mut self) -> CustomStyle<T, B, L, R, IH, IV, ()> {
+        self.inner.header_split_line = None;
+        CustomStyle::new(self.inner)
+    }
+}
+
+impl<T, B, L, R, IH, IV, H> TableOption for CustomStyle<T, B, L, R, IH, IV, H> {
+    fn change(&mut self, grid: &mut Grid) {
+        self.inner.change(grid);
+    }
+}
diff --git a/src/table.rs b/src/table.rs
index 9eaa203..9f7671d 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -46,7 +46,7 @@ pub trait CellOption {
 /// use tabled::{Table, Style, Alignment, Full, Modify};
 /// let data = vec!["Hello", "2021"];
 /// let table = Table::new(&data)
-///                 .with(Style::PSQL)
+///                 .with(Style::psql())
 ///                 .with(Modify::new(Full).with(Alignment::left()));
 /// println!("{}", table);
 /// ```
@@ -149,7 +149,7 @@ where
 /// ```rust
 /// use tabled::{TableIteratorExt, Style};
 /// let strings: &[&str] = &["Hello", "World"];
-/// let table = strings.table().with(Style::PSQL);
+/// let table = strings.table().with(Style::psql());
 /// println!("{}", table);
 /// ```
 pub trait TableIteratorExt {
diff --git a/src/width.rs b/src/width.rs
index 62cb862..28ad8a2 100644
--- a/src/width.rs
+++ b/src/width.rs
@@ -15,7 +15,7 @@ use papergrid::{Entity, Grid, Settings};
 /// ];
 ///
 /// let table = Table::new(&data)
-///     .with(Style::GITHUB_MARKDOWN)
+///     .with(Style::github_markdown())
 ///     .with(Modify::new(Full).with(MaxWidth::truncating(5, "...")));
 /// ```
 ///


Test patch:
diff --git a/tests/alignment_test.rs b/tests/alignment_test.rs
index 45c55dd..2e94b63 100644
--- a/tests/alignment_test.rs
+++ b/tests/alignment_test.rs
@@ -7,7 +7,7 @@ mod util;
 fn full_alignment() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .to_string();
 
@@ -26,7 +26,7 @@ fn full_alignment() {
 fn head_and_data_alignment() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(Modify::new(Head).with(Alignment::left()))
         .with(Modify::new(Row(1..)).with(Alignment::right()))
         .to_string();
@@ -65,7 +65,7 @@ fn full_alignment_multiline() {
     );
 
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .to_string();
 
@@ -80,7 +80,7 @@ fn vertical_alignment_test() {
     data[2][3] = String::from("https://\nwww\n.\nredhat\n.com\n/en");
 
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Column(1..)).with(Alignment::bottom()))
         .to_string();
 
@@ -116,7 +116,7 @@ fn alignment_doesnt_change_indent() {
     );
 
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Indent::new(3, 0, 0, 0)))
         .with(Modify::new(Full).with(Alignment::left()))
         .to_string();
diff --git a/tests/concat_test.rs b/tests/concat_test.rs
index b800ed7..2e8969d 100644
--- a/tests/concat_test.rs
+++ b/tests/concat_test.rs
@@ -9,8 +9,8 @@ fn table_join_vertical() {
     let data2 = create_vector::<2, 3>();
 
     {
-        let table1 = Table::new(&data1).with(Style::PSQL);
-        let table2 = Table::new(&data2).with(Style::ASCII);
+        let table1 = Table::new(&data1).with(Style::psql());
+        let table2 = Table::new(&data2).with(Style::ascii());
         let table3 = table1.with(Concat::vertical(table2));
 
         let expected = concat!(
@@ -31,8 +31,8 @@ fn table_join_vertical() {
     }
 
     {
-        let table1 = Table::new(&data1).with(Style::PSQL);
-        let table2 = Table::new(&data2).with(Style::ASCII);
+        let table1 = Table::new(&data1).with(Style::psql());
+        let table2 = Table::new(&data2).with(Style::ascii());
         let table3 = table2.with(Concat::vertical(table1));
 
         let expected = concat!(
@@ -59,8 +59,8 @@ fn table_join_horizontal() {
     let data2 = create_vector::<2, 3>();
 
     {
-        let table1 = Table::new(&data1).with(Style::PSQL);
-        let table2 = Table::new(&data2).with(Style::ASCII);
+        let table1 = Table::new(&data1).with(Style::psql());
+        let table2 = Table::new(&data2).with(Style::ascii());
         let table3 = table2.with(Concat::horizontal(table1));
 
         let expected = concat!(
@@ -77,8 +77,8 @@ fn table_join_horizontal() {
     }
 
     {
-        let table1 = Table::new(&data1).with(Style::PSQL);
-        let table2 = Table::new(&data2).with(Style::ASCII);
+        let table1 = Table::new(&data1).with(Style::psql());
+        let table2 = Table::new(&data2).with(Style::ascii());
         let table3 = table1.with(Concat::horizontal(table2));
 
         let expected = concat!(
@@ -100,8 +100,8 @@ fn table_join_vertical_different_size() {
     let data1 = create_vector::<2, 2>();
     let data2 = create_vector::<2, 3>();
 
-    let table1 = Table::new(&data1).with(Style::PSQL);
-    let table2 = Table::new(&data2).with(Style::PSQL);
+    let table1 = Table::new(&data1).with(Style::psql());
+    let table2 = Table::new(&data2).with(Style::psql());
     let table3 = table1.with(Concat::vertical(table2));
 
     let expected = concat!(
@@ -123,8 +123,8 @@ fn table_join_horizontal_different_size() {
     let data1 = create_vector::<2, 3>();
     let data2 = create_vector::<3, 3>();
 
-    let table1 = Table::new(&data1).with(Style::PSQL);
-    let table2 = Table::new(&data2).with(Style::PSQL);
+    let table1 = Table::new(&data1).with(Style::psql());
+    let table2 = Table::new(&data2).with(Style::psql());
     let table3 = table1.with(Concat::horizontal(table2));
 
     let expected = concat!(
@@ -143,8 +143,8 @@ fn table_join_horizontal_with_not_default_empty_string() {
     let data1 = create_vector::<2, 3>();
     let data2 = create_vector::<3, 3>();
 
-    let table1 = Table::new(&data1).with(Style::PSQL);
-    let table2 = Table::new(&data2).with(Style::PSQL);
+    let table1 = Table::new(&data1).with(Style::psql());
+    let table2 = Table::new(&data2).with(Style::psql());
     let table3 = table1.with(Concat::horizontal(table2).default_cell("NaN"));
 
     let expected = concat!(
@@ -163,8 +163,8 @@ fn table_join_vertical_with_not_default_empty_string() {
     let data1 = create_vector::<2, 2>();
     let data2 = create_vector::<2, 3>();
 
-    let table1 = Table::new(&data1).with(Style::PSQL);
-    let table2 = Table::new(&data2).with(Style::PSQL);
+    let table1 = Table::new(&data1).with(Style::psql());
+    let table2 = Table::new(&data2).with(Style::psql());
     let table3 = table1.with(Concat::vertical(table2).default_cell("NaN"));
 
     let expected = concat!(
diff --git a/tests/disable_test.rs b/tests/disable_test.rs
index a0b60d3..824b697 100644
--- a/tests/disable_test.rs
+++ b/tests/disable_test.rs
@@ -7,7 +7,7 @@ mod util;
 fn disable_rows() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Disable::Row(1..=2))
         .to_string();
@@ -27,7 +27,7 @@ fn disable_rows() {
 fn disable_header() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Disable::Row(..1))
         .to_string();
@@ -46,7 +46,7 @@ fn disable_header() {
 fn disable_all_table_via_rows() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Disable::Row(..))
         .to_string();
@@ -60,7 +60,7 @@ fn disable_header_with_new_styling() {
     let table = Table::new(&data)
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Disable::Row(..1))
-        .with(Style::PSEUDO_CLEAN)
+        .with(Style::modern().horizontal_off())
         .to_string();
 
     let expected = concat!(
@@ -79,7 +79,7 @@ fn disable_header_with_new_styling() {
 fn disable_columns() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Disable::Column(..1))
         .to_string();
 
@@ -98,7 +98,7 @@ fn disable_columns() {
 fn disable_all_table_via_columns() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Disable::Column(..))
         .to_string();
diff --git a/tests/format_test.rs b/tests/format_test.rs
index ac8743f..cc176a7 100644
--- a/tests/format_test.rs
+++ b/tests/format_test.rs
@@ -32,7 +32,7 @@ fn formatting_full_test() {
 fn formatting_head_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Head).with(Format(|s| format!(":{}", s))))
         .to_string();
 
@@ -51,7 +51,7 @@ fn formatting_head_test() {
 fn formatting_row_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Row(1..)).with(Format(|s| format!("<{}>", s))))
         .to_string();
 
@@ -70,7 +70,7 @@ fn formatting_row_test() {
 fn formatting_column_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Column(..1)).with(Format(|s| format!("(x) {}", s))))
         .to_string();
     let expected = concat!(
@@ -91,7 +91,7 @@ fn formatting_multiline_test() {
     data[2][3] = String::from("https://\nwww\n.\nredhat\n.com\n/en");
 
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Format(multiline(|s| format!("(x) {}", s)))))
         .to_string();
 
@@ -118,7 +118,7 @@ fn formatting_multiline_test() {
 fn formatting_cell_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Cell(0, 0)).with(Format(|s| format!("(x) {}", s))))
         .with(Modify::new(Cell(0, 1)).with(Format(|s| format!("(x) {}", s))))
         .with(Modify::new(Cell(0, 2)).with(Format(|s| format!("(x) {}", s))))
@@ -139,7 +139,7 @@ fn formatting_cell_test() {
 fn formatting_and_combination_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Column(..1).and(Row(..1))).with(Format(|s| format!("(x) {}", s))))
         .to_string();
 
@@ -158,7 +158,7 @@ fn formatting_and_combination_test() {
 fn formatting_not_combination_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(
             Modify::new(Column(..1).and(Row(..1)).not(Cell(0, 0)))
                 .with(Format(|s| format!("(x) {}", s))),
@@ -180,7 +180,7 @@ fn formatting_not_combination_test() {
 fn formatting_using_lambda_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Head).with(|s: &str| format!(":{}", s)))
         .to_string();
 
@@ -199,7 +199,7 @@ fn formatting_using_lambda_test() {
 fn formatting_using_function_test() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Head).with(str::to_uppercase))
         .to_string();
 
@@ -218,7 +218,7 @@ fn formatting_using_function_test() {
 fn format_from() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Head).with(FormatFrom(vec![
             "Header Name 1",
             "Header Name 2",
@@ -241,7 +241,7 @@ fn format_from() {
 fn format_with_index() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(
             Modify::new(Head).with(FormatWithIndex(|a, b, c| match (b, c) {
                 (0, 0) => "(0, 0)".to_string(),
@@ -273,7 +273,7 @@ mod color {
     fn color_column_test() {
         let data = create_vector::<3, 3>();
         let table = Table::new(&data)
-            .with(Style::PSQL)
+            .with(Style::psql())
             .with(Modify::new(Column(..1).and(Column(2..))).with(Format(|s| s.red().to_string())))
             .with(Modify::new(Column(1..2)).with(Format(|s| s.blue().to_string())))
             .to_string();
@@ -297,7 +297,7 @@ mod color {
         data[2][3] = String::from("https://\nwww\n.\nredhat\n.com\n/en");
 
         let table = Table::new(&data)
-            .with(Style::PSQL)
+            .with(Style::psql())
             .with(Modify::new(Column(..1)).with(Format(multiline(|s| s.red().to_string()))))
             .with(Modify::new(Column(1..2)).with(Format(multiline(|s| s.blue().to_string()))))
             .with(Modify::new(Column(2..)).with(Format(multiline(|s| s.green().to_string()))))
diff --git a/tests/highlingt_test.rs b/tests/highlingt_test.rs
index 47da4ff..c749427 100644
--- a/tests/highlingt_test.rs
+++ b/tests/highlingt_test.rs
@@ -7,7 +7,7 @@ mod util;
 fn highlingt_cell() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::cell(
             0,
             0,
@@ -39,7 +39,7 @@ fn highlingt_cell() {
 fn highlingt_row() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::row(
             0,
             Border::full('+', '+', '+', '+', '+', '+', '+', '+'),
@@ -69,7 +69,7 @@ fn highlingt_row() {
 fn highlingt_column() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::column(
             0,
             Border::full('+', '+', '+', '+', '+', '+', '+', '+'),
@@ -99,7 +99,7 @@ fn highlingt_column() {
 fn highlingt_row_range() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::row_range(
             1,
             3,
@@ -126,7 +126,7 @@ fn highlingt_row_range() {
 fn highlingt_column_range() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::column_range(
             0,
             2,
@@ -153,7 +153,7 @@ fn highlingt_column_range() {
 fn highlingt_frame() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO)
+        .with(Style::modern())
         .with(Highlight::frame(Border::full(
             '+', '+', '+', '+', '+', '+', '+', '+',
         )))
diff --git a/tests/indent_test.rs b/tests/indent_test.rs
index cc00c60..e3b76a4 100644
--- a/tests/indent_test.rs
+++ b/tests/indent_test.rs
@@ -7,7 +7,7 @@ mod util;
 fn indent() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Full).with(Alignment::left()))
         .with(Modify::new(Row(1..)).with(Indent::new(1, 1, 0, 2)))
         .to_string();
@@ -33,7 +33,7 @@ fn indent() {
 fn indent_multiline() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Row(1..)).with(Indent::new(1, 1, 1, 1)))
         .to_string();
 
@@ -58,7 +58,7 @@ fn indent_multiline() {
 fn indent_multiline_with_vertical_alignment() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(
             Modify::new(Full)
                 .with(Alignment::center_horizontal())
diff --git a/tests/panel_test.rs b/tests/panel_test.rs
index af5ba94..deda024 100644
--- a/tests/panel_test.rs
+++ b/tests/panel_test.rs
@@ -8,7 +8,7 @@ mod util;
 #[test]
 fn panel_has_no_style_by_default() {
     let table = Table::new(create_vector::<3, 3>())
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Panel("Linux Distributions", 0))
         .to_string();
 
@@ -30,7 +30,7 @@ fn panel_has_no_style_by_default() {
 fn highligt_panel() {
     let table = Table::new(create_vector::<3, 3>())
         .with(Panel("Linux Distributions", 0))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Highlight::cell(
             0,
             0,
@@ -58,7 +58,7 @@ fn top_panel() {
     let table = Table::new(create_vector::<3, 3>())
         .with(Panel("Linux Distributions", 0))
         .with(Modify::new(Full).with(Alignment::center_horizontal()))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .to_string();
 
     let expected = concat!(
@@ -79,7 +79,7 @@ fn bottom_panel() {
     let table = Table::new(&data)
         .with(Panel("Linux Distributions", data.len() + 1))
         .with(Modify::new(Row(data.len() + 1..)).with(Alignment::center_horizontal()))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .to_string();
 
     let expected = concat!(
@@ -99,7 +99,7 @@ fn inner_panel() {
     let table = Table::new(create_vector::<3, 3>())
         .with(Panel("Linux Distributions", 2))
         .with(Modify::new(Row(2..)).with(Alignment::center_horizontal()))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .to_string();
 
     let expected = concat!(
@@ -118,7 +118,7 @@ fn inner_panel() {
 fn header() {
     let table = Table::new(create_vector::<3, 3>())
         .with(Header("Linux Distributions"))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Row(0..1)).with(Alignment::center_horizontal()))
         .to_string();
 
@@ -140,7 +140,7 @@ fn footer() {
     let table = Table::new(&data)
         .with(Header("Linux Distributions"))
         .with(Footer("The end"))
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(Modify::new(Row(0..1).and(Row(data.len()..))).with(Alignment::center_horizontal()))
         .to_string();
 
diff --git a/tests/rotate_test.rs b/tests/rotate_test.rs
index 134bb24..699d92b 100644
--- a/tests/rotate_test.rs
+++ b/tests/rotate_test.rs
@@ -155,7 +155,7 @@ fn rotate_preserve_border_styles_test() {
     let data = [(123, 456, 789), (234, 567, 891), (111, 222, 333)];
 
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(Highlight::row(0, Border::default().top('*')))
         .with(Rotate::Left)
         .to_string();
@@ -174,7 +174,7 @@ fn rotate_preserve_border_styles_test() {
     );
 
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(Highlight::cell(0, 2, Border::default().bottom('*')))
         .with(Rotate::Left)
         .to_string();
diff --git a/tests/style_test.rs b/tests/style_test.rs
index 3bb44eb..d864dc4 100644
--- a/tests/style_test.rs
+++ b/tests/style_test.rs
@@ -1,13 +1,13 @@
 use crate::util::create_vector;
-use tabled::style::{Line, TopBorderText};
-use tabled::{Style, Table};
+use tabled::style::TopBorderText;
+use tabled::{Full, Indent, Modify, Style, Table, TableIteratorExt};
 
 mod util;
 
 #[test]
 fn default_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::ASCII).to_string();
+    let table = Table::new(&data).with(Style::ascii()).to_string();
 
     let expected = concat!(
         "+---+----------+----------+----------+\n",
@@ -27,7 +27,7 @@ fn default_style() {
 #[test]
 fn psql_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::PSQL).to_string();
+    let table = Table::new(&data).with(Style::psql()).to_string();
 
     let expected = concat!(
         " N | column 0 | column 1 | column 2 \n",
@@ -43,7 +43,7 @@ fn psql_style() {
 #[test]
 fn github_markdown_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::GITHUB_MARKDOWN).to_string();
+    let table = Table::new(&data).with(Style::github_markdown()).to_string();
 
     let expected = concat!(
         "| N | column 0 | column 1 | column 2 |\n",
@@ -59,7 +59,7 @@ fn github_markdown_style() {
 #[test]
 fn pseudo_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::PSEUDO).to_string();
+    let table = Table::new(&data).with(Style::modern()).to_string();
 
     let expected = concat!(
         "┌───┬──────────┬──────────┬──────────┐\n",
@@ -79,7 +79,9 @@ fn pseudo_style() {
 #[test]
 fn pseudo_clean_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::PSEUDO_CLEAN).to_string();
+    let table = Table::new(&data)
+        .with(Style::modern().horizontal_off())
+        .to_string();
 
     let expected = concat!(
         "┌───┬──────────┬──────────┬──────────┐\n",
@@ -97,7 +99,7 @@ fn pseudo_clean_style() {
 #[test]
 fn blank_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::BLANK).to_string();
+    let table = Table::new(&data).with(Style::blank()).to_string();
 
     let expected = concat!(
         " N   column 0   column 1   column 2 \n",
@@ -112,7 +114,7 @@ fn blank_style() {
 #[test]
 fn extended_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::EXTENDED).to_string();
+    let table = Table::new(&data).with(Style::extended()).to_string();
 
     let expected = concat!(
         "╔═══╦══════════╦══════════╦══════════╗\n",
@@ -132,7 +134,7 @@ fn extended_style() {
 #[test]
 fn ascii_dots_style() {
     let data = create_vector::<3, 3>();
-    let table = Table::new(&data).with(Style::ASCII_DOTS).to_string();
+    let table = Table::new(&data).with(Style::dots()).to_string();
 
     let expected = concat!(
         "......................................\n",
@@ -151,7 +153,7 @@ fn ascii_dots_style() {
 fn re_structured_text_style() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::RE_STRUCTURED_TEXT)
+        .with(Style::re_structured_text())
         .to_string();
 
     let expected = concat!(
@@ -171,7 +173,7 @@ fn re_structured_text_style() {
 fn style_head_changes() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO_CLEAN.header(None))
+        .with(Style::modern().horizontal_off().header_off())
         .to_string();
 
     let expected = concat!(
@@ -190,7 +192,7 @@ fn style_head_changes() {
 fn style_frame_changes() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::PSEUDO_CLEAN.frame_bottom(None).frame_top(None))
+        .with(Style::modern().top_off().bottom_off().horizontal_off())
         .to_string();
 
     let expected = concat!(
@@ -209,16 +211,19 @@ fn custom_style() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
         .with(
-            Style::BLANK
-                .frame_bottom(Some(Line::short('*', '\'')))
-                .split(Some(Line::short('`', '\'')))
-                .inner('\''),
+            Style::blank()
+                .bottom('*')
+                .bottom_intersection('\'')
+                .vertical('\'')
+                .horizontal('`')
+                .header('`')
+                .inner_intersection('\''),
         )
         .to_string();
 
     let expected = concat!(
         " N ' column 0 ' column 1 ' column 2 \n",
-        "```'``````````'``````````'``````````\n",
+        "````````````````````````````````````\n",
         " 0 '   0-0    '   0-1    '   0-2    \n",
         "```'``````````'``````````'``````````\n",
         " 1 '   1-0    '   1-1    '   1-2    \n",
@@ -233,13 +238,13 @@ fn custom_style() {
 #[test]
 fn style_single_cell() {
     let data = create_vector::<0, 0>();
-    let table = Table::new(&data).with(Style::ASCII).to_string();
+    let table = Table::new(&data).with(Style::ascii()).to_string();
 
     let expected = concat!("+---+\n", "| N |\n", "+---+\n",);
 
     assert_eq!(table, expected);
 
-    let table = Table::new(&data).with(Style::BLANK).to_string();
+    let table = Table::new(&data).with(Style::blank()).to_string();
 
     let expected = " N \n";
 
@@ -250,7 +255,7 @@ fn style_single_cell() {
 fn top_border_override_test() {
     let data = create_vector::<2, 2>();
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(TopBorderText::new("-Table"))
         .to_string();
 
@@ -271,7 +276,7 @@ fn top_border_override_test() {
 fn top_override_doesnt_work_with_style_with_no_top_border_test() {
     let data = create_vector::<2, 2>();
     let table = Table::new(&data)
-        .with(Style::PSQL)
+        .with(Style::psql())
         .with(TopBorderText::new("-Table"))
         .to_string();
 
@@ -289,9 +294,9 @@ fn top_override_doesnt_work_with_style_with_no_top_border_test() {
 fn top_border_override_cleared_after_restyling_test() {
     let data = create_vector::<2, 2>();
     let table = Table::new(&data)
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .with(TopBorderText::new("-Table"))
-        .with(Style::ASCII)
+        .with(Style::ascii())
         .to_string();
 
     let expected = concat!(
@@ -306,3 +311,820 @@ fn top_border_override_cleared_after_restyling_test() {
 
     assert_eq!(table, expected);
 }
+
+#[test]
+fn empty_style() {
+    let data = create_vector::<3, 3>();
+    let table = Table::new(&data)
+        .with(Style::empty())
+        .with(Modify::new(Full).with(Indent::new(0, 0, 0, 0)))
+        .to_string();
+
+    let expected = concat!(
+        "Ncolumn 0column 1column 2\n",
+        "0  0-0     0-1     0-2   \n",
+        "1  1-0     1-1     1-2   \n",
+        "2  2-0     2-1     2-2   \n",
+    );
+
+    assert_eq!(table, expected);
+}
+
+#[test]
+fn custom_style_test() {
+    macro_rules! test_style {
+        ($style:expr, $expected:expr $(,)*) => {
+            let data = create_vector::<3, 3>();
+            let table = data.table().with($style).to_string();
+            assert_eq!(table, $expected);
+        };
+    }
+
+    // Single
+
+    test_style!(
+        Style::empty().top('-'),
+        concat!(
+            "---------------------------------\n",
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+        ),
+    );
+    test_style!(
+        Style::empty().bottom('-'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+            "---------------------------------\n",
+        ),
+    );
+    test_style!(
+        Style::empty().left('-'),
+        concat!(
+            "- N  column 0  column 1  column 2 \n",
+            "- 0    0-0       0-1       0-2    \n",
+            "- 1    1-0       1-1       1-2    \n",
+            "- 2    2-0       2-1       2-2    \n",
+        ),
+    );
+    test_style!(
+        Style::empty().right('-'),
+        concat!(
+            " N  column 0  column 1  column 2 -\n",
+            " 0    0-0       0-1       0-2    -\n",
+            " 1    1-0       1-1       1-2    -\n",
+            " 2    2-0       2-1       2-2    -\n",
+        ),
+    );
+    test_style!(
+        Style::empty().horizontal('-'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            "---------------------------------\n",
+            " 1    1-0       1-1       1-2    \n",
+            "---------------------------------\n",
+            " 2    2-0       2-1       2-2    \n",
+        ),
+    );
+    test_style!(
+        Style::empty().header('-'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            "---------------------------------\n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+        ),
+    );
+    test_style!(
+        Style::empty().vertical('-'),
+        concat!(
+            " N - column 0 - column 1 - column 2 \n",
+            " 0 -   0-0    -   0-1    -   0-2    \n",
+            " 1 -   1-0    -   1-1    -   1-2    \n",
+            " 2 -   2-0    -   2-1    -   2-2    \n",
+        ),
+    );
+
+    // Combinations
+
+    test_style!(
+        Style::empty().top('-').bottom('+'),
+        concat!(
+            "---------------------------------\n",
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().top('-').left('+'),
+        concat!(
+            "+---------------------------------\n",
+            "+ N  column 0  column 1  column 2 \n",
+            "+ 0    0-0       0-1       0-2    \n",
+            "+ 1    1-0       1-1       1-2    \n",
+            "+ 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().top('-').right('+'),
+        concat!(
+            "---------------------------------+\n",
+            " N  column 0  column 1  column 2 +\n",
+            " 0    0-0       0-1       0-2    +\n",
+            " 1    1-0       1-1       1-2    +\n",
+            " 2    2-0       2-1       2-2    +\n",
+        )
+    );
+    test_style!(
+        Style::empty().top('-').horizontal('+'),
+        concat!(
+            "---------------------------------\n",
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 1    1-0       1-1       1-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().top('-').vertical('+'),
+        concat!(
+            "---+----------+----------+----------\n",
+            " N + column 0 + column 1 + column 2 \n",
+            " 0 +   0-0    +   0-1    +   0-2    \n",
+            " 1 +   1-0    +   1-1    +   1-2    \n",
+            " 2 +   2-0    +   2-1    +   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().top('-').header('+'),
+        concat!(
+            "---------------------------------\n",
+            " N  column 0  column 1  column 2 \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+
+    test_style!(
+        Style::empty().bottom('-').top('+'),
+        concat!(
+            "+++++++++++++++++++++++++++++++++\n",
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+            "---------------------------------\n",
+        )
+    );
+    test_style!(
+        Style::empty().bottom('-').left('+'),
+        concat!(
+            "+ N  column 0  column 1  column 2 \n",
+            "+ 0    0-0       0-1       0-2    \n",
+            "+ 1    1-0       1-1       1-2    \n",
+            "+ 2    2-0       2-1       2-2    \n",
+            "+---------------------------------\n",
+        )
+    );
+    test_style!(
+        Style::empty().bottom('-').right('+'),
+        concat!(
+            " N  column 0  column 1  column 2 +\n",
+            " 0    0-0       0-1       0-2    +\n",
+            " 1    1-0       1-1       1-2    +\n",
+            " 2    2-0       2-1       2-2    +\n",
+            "---------------------------------+\n",
+        )
+    );
+    test_style!(
+        Style::empty().bottom('-').vertical('+'),
+        concat!(
+            " N + column 0 + column 1 + column 2 \n",
+            " 0 +   0-0    +   0-1    +   0-2    \n",
+            " 1 +   1-0    +   1-1    +   1-2    \n",
+            " 2 +   2-0    +   2-1    +   2-2    \n",
+            "---+----------+----------+----------\n",
+        )
+    );
+    test_style!(
+        Style::empty().bottom('-').horizontal('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 1    1-0       1-1       1-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 2    2-0       2-1       2-2    \n",
+            "---------------------------------\n",
+        )
+    );
+    test_style!(
+        Style::empty().bottom('-').header('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+            "---------------------------------\n",
+        )
+    );
+
+    test_style!(
+        Style::empty().left('-').top('+'),
+        concat!(
+            "++++++++++++++++++++++++++++++++++\n",
+            "- N  column 0  column 1  column 2 \n",
+            "- 0    0-0       0-1       0-2    \n",
+            "- 1    1-0       1-1       1-2    \n",
+            "- 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().left('-').bottom('+'),
+        concat!(
+            "- N  column 0  column 1  column 2 \n",
+            "- 0    0-0       0-1       0-2    \n",
+            "- 1    1-0       1-1       1-2    \n",
+            "- 2    2-0       2-1       2-2    \n",
+            "++++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().left('-').right('+'),
+        concat!(
+            "- N  column 0  column 1  column 2 +\n",
+            "- 0    0-0       0-1       0-2    +\n",
+            "- 1    1-0       1-1       1-2    +\n",
+            "- 2    2-0       2-1       2-2    +\n",
+        )
+    );
+    test_style!(
+        Style::empty().left('-').vertical('+'),
+        concat!(
+            "- N + column 0 + column 1 + column 2 \n",
+            "- 0 +   0-0    +   0-1    +   0-2    \n",
+            "- 1 +   1-0    +   1-1    +   1-2    \n",
+            "- 2 +   2-0    +   2-1    +   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().left('-').horizontal('+'),
+        concat!(
+            "- N  column 0  column 1  column 2 \n",
+            "- 0    0-0       0-1       0-2    \n",
+            "++++++++++++++++++++++++++++++++++\n",
+            "- 1    1-0       1-1       1-2    \n",
+            "++++++++++++++++++++++++++++++++++\n",
+            "- 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().left('-').header('+'),
+        concat!(
+            "- N  column 0  column 1  column 2 \n",
+            "++++++++++++++++++++++++++++++++++\n",
+            "- 0    0-0       0-1       0-2    \n",
+            "- 1    1-0       1-1       1-2    \n",
+            "- 2    2-0       2-1       2-2    \n",
+        )
+    );
+
+    test_style!(
+        Style::empty().right('-').top('+'),
+        concat!(
+            "++++++++++++++++++++++++++++++++++\n",
+            " N  column 0  column 1  column 2 -\n",
+            " 0    0-0       0-1       0-2    -\n",
+            " 1    1-0       1-1       1-2    -\n",
+            " 2    2-0       2-1       2-2    -\n",
+        )
+    );
+    test_style!(
+        Style::empty().right('-').bottom('+'),
+        concat!(
+            " N  column 0  column 1  column 2 -\n",
+            " 0    0-0       0-1       0-2    -\n",
+            " 1    1-0       1-1       1-2    -\n",
+            " 2    2-0       2-1       2-2    -\n",
+            "++++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().right('-').left('+'),
+        concat!(
+            "+ N  column 0  column 1  column 2 -\n",
+            "+ 0    0-0       0-1       0-2    -\n",
+            "+ 1    1-0       1-1       1-2    -\n",
+            "+ 2    2-0       2-1       2-2    -\n",
+        )
+    );
+    test_style!(
+        Style::empty().right('-').vertical('+'),
+        concat!(
+            " N + column 0 + column 1 + column 2 -\n",
+            " 0 +   0-0    +   0-1    +   0-2    -\n",
+            " 1 +   1-0    +   1-1    +   1-2    -\n",
+            " 2 +   2-0    +   2-1    +   2-2    -\n",
+        )
+    );
+    test_style!(
+        Style::empty().right('-').horizontal('+'),
+        concat!(
+            " N  column 0  column 1  column 2 -\n",
+            " 0    0-0       0-1       0-2    -\n",
+            "++++++++++++++++++++++++++++++++++\n",
+            " 1    1-0       1-1       1-2    -\n",
+            "++++++++++++++++++++++++++++++++++\n",
+            " 2    2-0       2-1       2-2    -\n",
+        )
+    );
+    test_style!(
+        Style::empty().right('-').header('+'),
+        concat!(
+            " N  column 0  column 1  column 2 -\n",
+            "++++++++++++++++++++++++++++++++++\n",
+            " 0    0-0       0-1       0-2    -\n",
+            " 1    1-0       1-1       1-2    -\n",
+            " 2    2-0       2-1       2-2    -\n",
+        )
+    );
+
+    test_style!(
+        Style::empty().vertical('-').top('+'),
+        concat!(
+            "++++++++++++++++++++++++++++++++++++\n",
+            " N - column 0 - column 1 - column 2 \n",
+            " 0 -   0-0    -   0-1    -   0-2    \n",
+            " 1 -   1-0    -   1-1    -   1-2    \n",
+            " 2 -   2-0    -   2-1    -   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().vertical('-').bottom('+'),
+        concat!(
+            " N - column 0 - column 1 - column 2 \n",
+            " 0 -   0-0    -   0-1    -   0-2    \n",
+            " 1 -   1-0    -   1-1    -   1-2    \n",
+            " 2 -   2-0    -   2-1    -   2-2    \n",
+            "++++++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().vertical('-').left('+'),
+        concat!(
+            "+ N - column 0 - column 1 - column 2 \n",
+            "+ 0 -   0-0    -   0-1    -   0-2    \n",
+            "+ 1 -   1-0    -   1-1    -   1-2    \n",
+            "+ 2 -   2-0    -   2-1    -   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().vertical('-').right('+'),
+        concat!(
+            " N - column 0 - column 1 - column 2 +\n",
+            " 0 -   0-0    -   0-1    -   0-2    +\n",
+            " 1 -   1-0    -   1-1    -   1-2    +\n",
+            " 2 -   2-0    -   2-1    -   2-2    +\n",
+        )
+    );
+    test_style!(
+        Style::empty().vertical('-').horizontal('+'),
+        concat!(
+            " N - column 0 - column 1 - column 2 \n",
+            " 0 -   0-0    -   0-1    -   0-2    \n",
+            "++++++++++++++++++++++++++++++++++++\n",
+            " 1 -   1-0    -   1-1    -   1-2    \n",
+            "++++++++++++++++++++++++++++++++++++\n",
+            " 2 -   2-0    -   2-1    -   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().vertical('-').header('+'),
+        concat!(
+            " N - column 0 - column 1 - column 2 \n",
+            "++++++++++++++++++++++++++++++++++++\n",
+            " 0 -   0-0    -   0-1    -   0-2    \n",
+            " 1 -   1-0    -   1-1    -   1-2    \n",
+            " 2 -   2-0    -   2-1    -   2-2    \n",
+        )
+    );
+
+    test_style!(
+        Style::empty().horizontal('-').top('+'),
+        concat!(
+            "+++++++++++++++++++++++++++++++++\n",
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            "---------------------------------\n",
+            " 1    1-0       1-1       1-2    \n",
+            "---------------------------------\n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().horizontal('-').bottom('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            " 0    0-0       0-1       0-2    \n",
+            "---------------------------------\n",
+            " 1    1-0       1-1       1-2    \n",
+            "---------------------------------\n",
+            " 2    2-0       2-1       2-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().horizontal('-').left('+'),
+        concat!(
+            "+ N  column 0  column 1  column 2 \n",
+            "+ 0    0-0       0-1       0-2    \n",
+            "+---------------------------------\n",
+            "+ 1    1-0       1-1       1-2    \n",
+            "+---------------------------------\n",
+            "+ 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().horizontal('-').right('+'),
+        concat!(
+            " N  column 0  column 1  column 2 +\n",
+            " 0    0-0       0-1       0-2    +\n",
+            "---------------------------------+\n",
+            " 1    1-0       1-1       1-2    +\n",
+            "---------------------------------+\n",
+            " 2    2-0       2-1       2-2    +\n",
+        )
+    );
+    test_style!(
+        Style::empty().horizontal('-').vertical('+'),
+        concat!(
+            " N + column 0 + column 1 + column 2 \n",
+            " 0 +   0-0    +   0-1    +   0-2    \n",
+            "---+----------+----------+----------\n",
+            " 1 +   1-0    +   1-1    +   1-2    \n",
+            "---+----------+----------+----------\n",
+            " 2 +   2-0    +   2-1    +   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().horizontal('-').header('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 0    0-0       0-1       0-2    \n",
+            "---------------------------------\n",
+            " 1    1-0       1-1       1-2    \n",
+            "---------------------------------\n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+
+    test_style!(
+        Style::empty().header('-').top('+'),
+        concat!(
+            "+++++++++++++++++++++++++++++++++\n",
+            " N  column 0  column 1  column 2 \n",
+            "---------------------------------\n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().header('-').bottom('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            "---------------------------------\n",
+            " 0    0-0       0-1       0-2    \n",
+            " 1    1-0       1-1       1-2    \n",
+            " 2    2-0       2-1       2-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+        )
+    );
+    test_style!(
+        Style::empty().header('-').left('+'),
+        concat!(
+            "+ N  column 0  column 1  column 2 \n",
+            "+---------------------------------\n",
+            "+ 0    0-0       0-1       0-2    \n",
+            "+ 1    1-0       1-1       1-2    \n",
+            "+ 2    2-0       2-1       2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().header('-').right('+'),
+        concat!(
+            " N  column 0  column 1  column 2 +\n",
+            "---------------------------------+\n",
+            " 0    0-0       0-1       0-2    +\n",
+            " 1    1-0       1-1       1-2    +\n",
+            " 2    2-0       2-1       2-2    +\n",
+        )
+    );
+    test_style!(
+        Style::empty().header('-').vertical('+'),
+        concat!(
+            " N + column 0 + column 1 + column 2 \n",
+            "---+----------+----------+----------\n",
+            " 0 +   0-0    +   0-1    +   0-2    \n",
+            " 1 +   1-0    +   1-1    +   1-2    \n",
+            " 2 +   2-0    +   2-1    +   2-2    \n",
+        )
+    );
+    test_style!(
+        Style::empty().header('-').horizontal('+'),
+        concat!(
+            " N  column 0  column 1  column 2 \n",
+            "---------------------------------\n",
+            " 0    0-0       0-1       0-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 1    1-0       1-1       1-2    \n",
+            "+++++++++++++++++++++++++++++++++\n",
+            " 2    2-0       2-1       2-2    \n",
+        )
+    );
+
+    // Full
+
+    test_style!(
+        Style::empty()
+            .top('-')
+            .bottom('+')
+            .left('|')
+            .right('*')
+            .horizontal('x')
+            .header('x')
+            .vertical('#'),
+        concat!(
+            "|---#----------#----------#----------*\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "xxxx#xxxxxxxxxx#xxxxxxxxxx#xxxxxxxxxxx\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "xxxx#xxxxxxxxxx#xxxxxxxxxx#xxxxxxxxxxx\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "xxxx#xxxxxxxxxx#xxxxxxxxxx#xxxxxxxxxxx\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "|+++#++++++++++#++++++++++#++++++++++*\n",
+        ),
+    );
+
+    let full_style = Style::empty()
+        .top('-')
+        .bottom('+')
+        .left('|')
+        .right('*')
+        .horizontal('x')
+        .header(',')
+        .vertical('#')
+        .bottom_intersection('@')
+        .top_intersection('!')
+        .left_intersection('=')
+        .right_intersection('$')
+        .top_left_corner(';')
+        .bottom_left_corner('?')
+        .top_right_corner('.')
+        .bottom_right_corner('%')
+        .inner_intersection('+')
+        .left_header_intersection('o')
+        .right_header_intersection('w')
+        .header_intersection('m');
+    test_style!(
+        full_style.clone(),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+
+    // Overwrite intersections and corners
+
+    test_style!(
+        full_style.clone().top('q'),
+        concat!(
+            "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().bottom('q'),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n",
+        )
+    );
+    test_style!(
+        full_style.clone().left('w'),
+        concat!(
+            "w---!----------!----------!----------.\n",
+            "w N # column 0 # column 1 # column 2 *\n",
+            "w,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "w 0 #   0-0    #   0-1    #   0-2    *\n",
+            "wxxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "w 1 #   1-0    #   1-1    #   1-2    *\n",
+            "wxxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "w 2 #   2-0    #   2-1    #   2-2    *\n",
+            "w+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().right('i'),
+        concat!(
+            ";---!----------!----------!----------i\n",
+            "| N # column 0 # column 1 # column 2 i\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,i\n",
+            "| 0 #   0-0    #   0-1    #   0-2    i\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxxi\n",
+            "| 1 #   1-0    #   1-1    #   1-2    i\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxxi\n",
+            "| 2 #   2-0    #   2-1    #   2-2    i\n",
+            "?+++@++++++++++@++++++++++@++++++++++i\n",
+        )
+    );
+    test_style!(
+        full_style.clone().horizontal('q'),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().vertical('q'),
+        concat!(
+            ";---q----------q----------q----------.\n",
+            "| N q column 0 q column 1 q column 2 *\n",
+            "o,,,q,,,,,,,,,,q,,,,,,,,,,q,,,,,,,,,,w\n",
+            "| 0 q   0-0    q   0-1    q   0-2    *\n",
+            "=xxxqxxxxxxxxxxqxxxxxxxxxxqxxxxxxxxxx$\n",
+            "| 1 q   1-0    q   1-1    q   1-2    *\n",
+            "=xxxqxxxxxxxxxxqxxxxxxxxxxqxxxxxxxxxx$\n",
+            "| 2 q   2-0    q   2-1    q   2-2    *\n",
+            "?+++q++++++++++q++++++++++q++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().header('q'),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+
+    // Turn off borders
+
+    let empty_table = concat!(
+        " N  column 0  column 1  column 2 \n",
+        " 0    0-0       0-1       0-2    \n",
+        " 1    1-0       1-1       1-2    \n",
+        " 2    2-0       2-1       2-2    \n",
+    );
+    test_style!(Style::empty().top('-').top_off(), empty_table);
+    test_style!(Style::empty().bottom('-').bottom_off(), empty_table);
+    test_style!(Style::empty().right('-').right_off(), empty_table);
+    test_style!(Style::empty().left('-').left_off(), empty_table);
+    test_style!(Style::empty().horizontal('-').horizontal_off(), empty_table);
+    test_style!(Style::empty().vertical('-').vertical_off(), empty_table);
+    test_style!(Style::empty().header('-').header_off(), empty_table);
+
+    test_style!(
+        full_style.clone().top_off(),
+        concat!(
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().bottom_off(),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+        )
+    );
+    test_style!(
+        full_style.clone().right_off(),
+        concat!(
+            ";---!----------!----------!----------\n",
+            "| N # column 0 # column 1 # column 2 \n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,\n",
+            "| 0 #   0-0    #   0-1    #   0-2    \n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx\n",
+            "| 1 #   1-0    #   1-1    #   1-2    \n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx\n",
+            "| 2 #   2-0    #   2-1    #   2-2    \n",
+            "?+++@++++++++++@++++++++++@++++++++++\n",
+        )
+    );
+    test_style!(
+        full_style.clone().left_off(),
+        concat!(
+            "---!----------!----------!----------.\n",
+            " N # column 0 # column 1 # column 2 *\n",
+            ",,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            " 0 #   0-0    #   0-1    #   0-2    *\n",
+            "xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            " 1 #   1-0    #   1-1    #   1-2    *\n",
+            "xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            " 2 #   2-0    #   2-1    #   2-2    *\n",
+            "+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().horizontal_off(),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "o,,,m,,,,,,,,,,m,,,,,,,,,,m,,,,,,,,,,w\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.clone().vertical_off(),
+        concat!(
+            ";---------------------------------.\n",
+            "| N  column 0  column 1  column 2 *\n",
+            "o,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,w\n",
+            "| 0    0-0       0-1       0-2    *\n",
+            "=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$\n",
+            "| 1    1-0       1-1       1-2    *\n",
+            "=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx$\n",
+            "| 2    2-0       2-1       2-2    *\n",
+            "?+++++++++++++++++++++++++++++++++%\n",
+        )
+    );
+    test_style!(
+        full_style.header_off(),
+        concat!(
+            ";---!----------!----------!----------.\n",
+            "| N # column 0 # column 1 # column 2 *\n",
+            "| 0 #   0-0    #   0-1    #   0-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 1 #   1-0    #   1-1    #   1-2    *\n",
+            "=xxx+xxxxxxxxxx+xxxxxxxxxx+xxxxxxxxxx$\n",
+            "| 2 #   2-0    #   2-1    #   2-2    *\n",
+            "?+++@++++++++++@++++++++++@++++++++++%\n",
+        )
+    );
+}
diff --git a/tests/table_test.rs b/tests/table_test.rs
index 6258f19..a4f924a 100644
--- a/tests/table_test.rs
+++ b/tests/table_test.rs
@@ -728,7 +728,7 @@ fn tuple_combination() {
         (Developer("Maxim Zhiburt"), Domain::Unknown),
     ];
 
-    let table = Table::new(data).with(Style::PSQL).to_string();
+    let table = Table::new(data).with(Style::psql()).to_string();
 
     assert_eq!(
         table,
@@ -763,7 +763,7 @@ fn table_trait() {
         (Developer("Maxim Zhiburt"), Domain::Unknown),
     ];
 
-    let table = (&data).table().with(Style::PSQL).to_string();
+    let table = (&data).table().with(Style::psql()).to_string();
 
     assert_eq!(
         table,
@@ -781,7 +781,7 @@ fn table_trait() {
 #[test]
 fn build_table_from_iterator() {
     let data = create_vector::<3, 3>();
-    let table = Table::from_iter(data).with(Style::PSQL).to_string();
+    let table = Table::from_iter(data).with(Style::psql()).to_string();
 
     let expected = concat!(
         " N | column 0 | column 1 | column 2 \n",
@@ -793,3 +793,47 @@ fn build_table_from_iterator() {
 
     assert_eq!(table, expected);
 }
+
+#[test]
+fn table_emojie_utf8_style() {
+    #[derive(Tabled)]
+    struct Language {
+        name: &'static str,
+        designed_by: &'static str,
+        invented_year: usize,
+    }
+
+    let languages = vec![
+        Language {
+            name: "C 💕",
+            designed_by: "Dennis Ritchie",
+            invented_year: 1972,
+        },
+        Language {
+            name: "Rust 👍",
+            designed_by: "Graydon Hoare",
+            invented_year: 2010,
+        },
+        Language {
+            name: "Go 🧋",
+            designed_by: "Rob Pike",
+            invented_year: 2009,
+        },
+    ];
+
+    // Note: It doesn't look good in VS Code
+    let expected = "┌─────────┬────────────────┬───────────────┐\n\
+                         │  name   │  designed_by   │ invented_year │\n\
+                         │  C 💕   │ Dennis Ritchie │     1972      │\n\
+                         │ Rust 👍 │ Graydon Hoare  │     2010      │\n\
+                         │  Go 🧋  │    Rob Pike    │     2009      │\n\
+                         └─────────┴────────────────┴───────────────┘\n";
+
+    let table = Table::new(&languages)
+        .with(tabled::Style::modern().header_off().horizontal_off())
+        .to_string();
+
+    println!("{}", table);
+
+    assert_eq!(table, expected);
+}
diff --git a/tests/width_test.rs b/tests/width_test.rs
index c10a23b..0c3280c 100644
--- a/tests/width_test.rs
+++ b/tests/width_test.rs
@@ -7,7 +7,7 @@ mod util;
 fn max_width() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Column(1..).not(Row(..1))).with(MaxWidth::truncating(2, "...")))
         .to_string();
 
@@ -26,7 +26,7 @@ fn max_width() {
 fn max_width_wrapped() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Column(1..).not(Row(..1))).with(MaxWidth::wrapping(2)))
         .to_string();
 
@@ -70,7 +70,7 @@ fn max_width_wrapped_collored() {
     );
 
     let table = Table::new(data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Full).with(MaxWidth::wrapping(2)))
         .to_string();
 
@@ -83,7 +83,7 @@ fn max_width_wrapped_collored() {
 fn dont_change_content_if_width_is_less_then_max_width() {
     let data = create_vector::<3, 3>();
     let table = Table::new(&data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Full).with(MaxWidth::truncating(1000, "...")))
         .to_string();
 
@@ -111,7 +111,7 @@ fn max_width_with_emoji() {
     );
 
     let table = Table::new(data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Full).with(MaxWidth::truncating(3, "...")))
         .to_string();
 
@@ -138,7 +138,7 @@ fn color_chars_are_stripped() {
     );
 
     let table = Table::new(data)
-        .with(Style::GITHUB_MARKDOWN)
+        .with(Style::github_markdown())
         .with(Modify::new(Full).with(MaxWidth::truncating(3, "...")))
         .to_string();