diff --git a/.github/img/logo-macros.svg b/.github/img/logo-macros.svg
new file mode 100644
index 0000000..0cd8060
--- /dev/null
+++ b/.github/img/logo-macros.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 67c3f7a..110b315 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,6 +22,7 @@ path = "lib/lib.rs"
[features]
cli-stylize = ["dep:bitflags"]
logger = ["dep:log"]
+macros = []
[dependencies]
bitflags = { version = "2.5.0", optional = true }
diff --git a/README.md b/README.md
index c5acd8f..5fe6edf 100644
--- a/README.md
+++ b/README.md
@@ -14,4 +14,5 @@
# Features
- [x] [cli/stylize](lib/cli/stylize)
-- [x] [logging](lib/logger)
\ No newline at end of file
+- [x] [logging](lib/logger)
+- [x] [macros](lib/macros)
\ No newline at end of file
diff --git a/examples/fail_macro.rs b/examples/fail_macro.rs
new file mode 100644
index 0000000..9371acd
--- /dev/null
+++ b/examples/fail_macro.rs
@@ -0,0 +1,18 @@
+use {
+ eyre::{set_hook, DefaultHandler, Result},
+ lool::f,
+};
+
+fn setup_eyre() {
+ let _ = set_hook(Box::new(DefaultHandler::default_with));
+}
+
+fn main() -> Result<()> {
+ setup_eyre();
+
+ if (2 + 2) == 5 {
+ return f!("Oh no! I'm bad at math!");
+ }
+
+ Ok(())
+}
diff --git a/lib/lib.rs b/lib/lib.rs
index e7d96d8..8e3eb3b 100644
--- a/lib/lib.rs
+++ b/lib/lib.rs
@@ -2,3 +2,6 @@ pub mod cli;
#[cfg(feature = "logger")]
pub mod logger;
+
+#[cfg(feature = "macros")]
+pub mod macros;
diff --git a/lib/logger/README.md b/lib/logger/README.md
index 582fd81..b76f03c 100644
--- a/lib/logger/README.md
+++ b/lib/logger/README.md
@@ -16,7 +16,7 @@
This crate is for internal use. It's only published privately.
```bash
-cargo add lool --registry=lugit
+cargo add lool --registry=lugit --features loggers
```
# Setup
diff --git a/lib/macros/README.md b/lib/macros/README.md
new file mode 100644
index 0000000..dd1b2e3
--- /dev/null
+++ b/lib/macros/README.md
@@ -0,0 +1,82 @@
+

+
+
+
+
+
+lool » macros is a collection of utility macros for rust.
+
+
+
+
+
+
+# Installation
+
+This crate is for internal use. It's only published privately.
+
+```bash
+cargo add lool --registry=lugit --features macros
+```
+
+# Macros
+
+## `s`
+
+A macro to create a `String` from a `&str`.
+
+```rs
+use lool::s;
+
+fn main() {
+ let s = s!("Hello, world!");
+ // now `s` is a `String`
+}
+```
+
+## `f` or `fail`
+
+A macro to use with the [`eyre`](https://crates.io/crates/eyre) crate.
+It basically creates an `Err`.
+
+It's almost the same as `bail!` from the `anyhow` crate, but this one doesn't explicitly returns (the `bail!` macro creates a `return` statement).
+
+This macro is equivalent to: `Err(eyre!())`.
+
+```rs
+use lool::f;
+
+fn main() -> eyre::Result<()> {
+ if (2 + 2) == 5 {
+ f!("Oh no! I'm bad at math!");
+ }
+
+ Ok(())
+}
+```
+
+which is equivalent to:
+
+```rs
+use eyre::eyre;
+
+fn main() -> eyre::Result<()> {
+ if (2 + 2) == 5 {
+ return Err(eyre!("Oh no! I'm bad at math!"));
+ }
+
+ Ok(())
+}
+```
+
+It also works as a final statement:
+
+```rs
+use lool::f;
+
+fn fail_always() -> eyre::Result<()> {
+ // no ; at the end
+ f!("I'm a failure")
+}
+```
+
diff --git a/lib/macros/mod.rs b/lib/macros/mod.rs
new file mode 100644
index 0000000..2da6995
--- /dev/null
+++ b/lib/macros/mod.rs
@@ -0,0 +1,83 @@
+/// 🧉 » create string
+/// --
+///
+/// create a new `String` from a string literal or a string expression -
+/// this macro is equivalent to `String::from()`.
+///
+/// ### Example
+/// ```rust
+/// use lool::s;
+/// let s: String = s!("hello world");
+/// ```
+#[macro_export]
+macro_rules! s {
+ ($s:expr) => {
+ String::from($s)
+ };
+}
+
+/// 🧉 » fail macro
+/// --
+///
+/// this macro is equivalent to `Err(eyre!())`.
+///
+/// same as `bail!` but without the explicit return
+///
+/// ### Example
+///
+/// ```should_panic
+/// use lool::fail;
+/// use eyre::Result;
+/// # use eyre::{set_hook, DefaultHandler};
+/// # fn setup_eyre() {
+/// # let _ = set_hook(Box::new(DefaultHandler::default_with));
+/// # }
+///
+/// fn main() -> Result<()> {
+/// # setup_eyre();
+/// fail!("permission denied")
+/// }
+/// ```
+#[macro_export]
+macro_rules! fail {
+ ($msg:literal $(,)?) => {
+ Err(eyre::eyre!($msg))
+ };
+ ($err:expr $(,)?) => {
+ Err(eyre::eyre!($err))
+ };
+ ($fmt:expr, $($arg:tt)*) => {
+ Err(eyre::eyre!($fmt, $($arg)*))
+ };
+}
+
+/// 🧉 » fail macro
+/// --
+///
+/// this macro is equivalent to `Err(eyre!())`.
+///
+/// same as `bail!` but without the explicit return
+///
+/// this is an alias for `fail!`
+///
+/// ### Example
+///
+/// ```should_panic
+/// use lool::f;
+/// use eyre::Result;
+/// # use eyre::{set_hook, DefaultHandler};
+/// # fn setup_eyre() {
+/// # let _ = set_hook(Box::new(DefaultHandler::default_with));
+/// # }
+///
+/// fn main() -> Result<()> {
+/// # setup_eyre();
+/// f!("permission denied")
+/// }
+/// ```
+#[macro_export]
+macro_rules! f {
+ ($($tokens:tt)*) => {
+ lool::fail!($($tokens)*)
+ };
+}