diff --git a/Cargo.toml b/Cargo.toml
index 3d8e8dd3..7d79968a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,4 +25,5 @@ default = ["termcolor"]
[dependencies]
log = { version = "0.4.*", features = ["std"] }
termcolor = { version = "1.1.*", optional = true }
+paris = { version = "1.5.7", optional = true }
chrono = "0.4.1"
diff --git a/README.md b/README.md
index 2428131b..cfa4deb1 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,25 @@ simplelog = "^0.10.0"
```
to your `Cargo.toml`
+## ANSI color and style support
+
+This crate can internally depend on a [paris](https://github.com/0x20F/paris) crate to provide support for ANSI color and styles.
+To use this feature you need to set a _paris_ feature, like this:
+```
+[dependencies]
+simplelog = { version = "^0.10.0", features = ["paris"] }
+```
+in your `Cargo.toml`
+
+After this you can use e.g. the following call:
+```rust
+info!("I can write bold text or use tags to color it>");
+```
+
+This will automatically generates terminal control sequences for desired styles.
+
+More formatting info: [paris crate documentation](https://github.com/0x20F/paris)
+
## [Documentation](https://docs.rs/simplelog/)
## Contributing
diff --git a/examples/custom_colors.rs b/examples/custom_colors.rs
index f3c1a0ea..8d45a501 100644
--- a/examples/custom_colors.rs
+++ b/examples/custom_colors.rs
@@ -1,4 +1,4 @@
-#[cfg(feature = "termcolor")]
+#[cfg(all(feature = "termcolor", not(feature = "paris")))]
use log::*;
#[cfg(feature = "termcolor")]
use simplelog::*;
diff --git a/examples/default_colors.rs b/examples/default_colors.rs
index 3c6984ce..1d8d141b 100644
--- a/examples/default_colors.rs
+++ b/examples/default_colors.rs
@@ -1,4 +1,4 @@
-#[cfg(feature = "termcolor")]
+#[cfg(all(feature = "termcolor", not(feature = "paris")))]
use log::*;
#[cfg(feature = "termcolor")]
use simplelog::*;
diff --git a/examples/rgb_colors.rs b/examples/rgb_colors.rs
index 6cffa9cc..8fc1c15a 100644
--- a/examples/rgb_colors.rs
+++ b/examples/rgb_colors.rs
@@ -1,4 +1,8 @@
-#[cfg(all(not(target_family = "windows"), feature = "termcolor"))]
+#[cfg(all(
+ not(target_family = "windows"),
+ feature = "termcolor",
+ not(feature = "paris")
+))]
use log::*;
#[cfg(all(not(target_family = "windows"), feature = "termcolor"))]
use simplelog::*;
diff --git a/examples/usage.rs b/examples/usage.rs
index 7e17295c..8d4959c3 100644
--- a/examples/usage.rs
+++ b/examples/usage.rs
@@ -1,3 +1,4 @@
+#[cfg(not(feature = "paris"))]
use log::*;
use simplelog::*;
diff --git a/src/lib.rs b/src/lib.rs
index b3fb2248..481404db 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -36,9 +36,14 @@ pub use termcolor::{Color, ColorChoice};
pub use log::{Level, LevelFilter};
use log::Log;
-#[cfg(test)]
+#[cfg(all(test, not(feature = "paris")))]
use log::*;
+#[cfg(feature = "paris")]
+pub(crate) mod paris_macros;
+#[cfg(feature = "paris")]
+pub extern crate paris;
+
/// Trait to have a common interface to obtain the Level of Loggers
///
/// Necessary for CombinedLogger to calculate
diff --git a/src/paris_macros/mod.rs b/src/paris_macros/mod.rs
new file mode 100644
index 00000000..3baebcfb
--- /dev/null
+++ b/src/paris_macros/mod.rs
@@ -0,0 +1,130 @@
+/// Logs a message at the info level.
+///
+/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
+/// contains special tags for controlling ANSI colors and styles
+/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
+///
+/// # Examples
+///
+/// ```edition2018
+/// use log::info;
+///
+/// # fn main() {
+/// # struct Connection { port: u32, speed: f32 }
+/// let conn_info = Connection { port: 40, speed: 3.20 };
+///
+/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
+/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
+/// conn_info.port, conn_info.speed);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! info {
+ ($($args:tt)+) => {
+ log::info!("{}", paris::formatter::colorize_string(format!($($args)*)));
+ };
+}
+
+/// Logs a message at the debug level.
+///
+/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
+/// contains special tags for controlling ANSI colors and styles
+/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
+///
+/// # Examples
+///
+/// ```edition2018
+/// use log::debug;
+///
+/// # fn main() {
+/// # struct Position { x: f32, y: f32 }
+/// let pos = Position { x: 3.234, y: -1.223 };
+///
+/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
+/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! debug {
+ ($($args:tt)+) => {
+ log::debug!("{}", paris::formatter::colorize_string(format!($($args)*)));
+ };
+}
+
+/// Logs a message at the trace level.
+///
+/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
+/// contains special tags for controlling ANSI colors and styles
+/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
+///
+/// # Examples
+///
+/// ```edition2018
+/// use log::trace;
+///
+/// # fn main() {
+/// # struct Position { x: f32, y: f32 }
+/// let pos = Position { x: 3.234, y: -1.223 };
+///
+/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
+/// trace!(target: "app_events", "x is {} and y is {}",
+/// if pos.x >= 0.0 { "positive" } else { "negative" },
+/// if pos.y >= 0.0 { "positive" } else { "negative" });
+/// # }
+/// ```
+#[macro_export]
+macro_rules! trace {
+ ($($args:tt)+) => {
+ log::trace!("{}", paris::formatter::colorize_string(format!($($args)*)));
+ };
+}
+
+/// Logs a message at the warn level.
+///
+/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
+/// contains special tags for controlling ANSI colors and styles
+/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
+///
+/// # Examples
+///
+/// ```edition2018
+/// use log::warn;
+///
+/// # fn main() {
+/// let warn_description = "Invalid Input";
+///
+/// warn!("Warning! {}!", warn_description);
+/// warn!(target: "input_events", "App received warning: {}", warn_description);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! warn {
+ ($($args:tt)+) => {
+ log::warn!("{}", paris::formatter::colorize_string(format!($($args)*)));
+ };
+}
+
+/// Logs a message at the error level.
+///
+/// Passed data uses a colorize_string formatter from a `paris` crate, so it can
+/// contains special tags for controlling ANSI colors and styles
+/// More info: https://docs.rs/paris/1.5.7/paris/formatter/fn.colorize_string.html
+///
+/// # Examples
+///
+/// ```edition2018
+/// use log::error;
+///
+/// # fn main() {
+/// let (err_info, port) = ("No connection", 22);
+///
+/// error!("Error: {} on port {}", err_info, port);
+/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
+/// # }
+/// ```
+#[macro_export]
+macro_rules! error {
+ ($($args:tt)+) => {
+ log::error!("{}", paris::formatter::colorize_string(format!($($args)*)));
+ };
+}