-
+
diff --git a/doc/changelog.md b/doc/changelog.md
index fea420d..a19da81 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -1,102 +1,37 @@
Change Log {#changelog}
==========
-# Version 2.2 - Aubrey Bradimore
+# Version 2.0 - Past Prologue
-## What's Changed
+## Bug Fixes
+* Moved from `pragma once` to `#ifndef` to allow for multiple raberu files to coexist in multiple projects.
+* Fixed a regression in Visual Studio that affected ability to run tests.
+* Fix #6 - Compile-time ID are now properly displayed and compared without any issues due to terminal `\0`.
-### Infrastructure
- * **We are now under the Boost Software Licence 1.0**
- * Enable Android tests and support
- * Clarify some output when failures occur
+## New Features
+* Fix #4 - Simplify and generalize custom keyword generation
+ A new CRTP class `rbr::as_keyword` streamlines the definition of compact keyword by users while
+ supporting the whole range of built-in keywords. Associated documentation has been updated.
-### New Features
- * Implement ALL_EQUAL
- * Test can now use configurable, automatic data generator (https://github.com/jfalcou/tts/pull/53)
- * `TTS_EXPECT_COMPILES/COMPILE_NOT` check if a fragment of code can be compiled or not
- * Reimplement `TTS_WHEN` and `TTS_AND_THEN` to support sub-tests
- * Add typed tests that checks both value and exact type
+* Fix #2 - Implement direct keyword value access
+ Keyword can now fetch themselves from a bundles of options. E.g
-### Bug Fixes
- * Fix Visual Studio interaction with constexpr tests
- * Improve random generators and seed management
+ ``` c++
+ inline constexpr auto coord_ = "coord"_kw;
+ inline constexpr auto is_modal_ = "is_modal"_fl;
-## Detective who?
-[Aubrey Bradimore](https://en.wikipedia.org/wiki/Aubrey_Bradimore), this is a Christmas Release afterall
+ auto x = coord_(coord_ = "Jane"s, is_modal_);
+ ```
-# Version 2.1 - Cordelia Gray
+* Fix #5 - Mass extractors for keyword and values
+ `rbr::keywords` and`rbr::values` can be used to retrieve a tuple-like object containing all the
+ keywords or values from a bundle of options.
-## What's Changed
- * Fix #42 - Proper FetchContent support
- * Better compatibility
- * Enable EMSCRIPTEN tests and supports
- * Add tests over sequences
+* `rbr::get_type` is removed and is replaced by `rbr::fetch` and `rbr::result::fetch_t`.
+ This functions provides an infix syntax for options access.
-## Detective who?
-[Cordelia Gray](https://en.wikipedia.org/wiki/Cordelia_Gray), a very suitable detective
+# Version 1.0 - Emissary
-# Version 2.0 - Kay Scarpetta
+## First autonomous public release.
-**TTS** version 2.0 is taking a major break from an earlier version. Compile-time was creeping upward
-and some features were not that useful. So the code base got streamlined and simplified.
-
-This version is a **Major Release With API Changes** release:
-
-**Breaking API Changes**:
- + Removal of support for colors
- + Removal of support for sub-scenario
- + Silent mode for tests is the default. The only information displayed concerns failures
-
-**Features:**
- + Improved compile-times
- + Output streamlined to fit machine processing in CI context or scripts
- + Better handling of template test cases: less generated symbol, better flexibility in inputs (list of types or types list generator)
-
-## Detective who?
-[Kay Scarpetta](https://en.wikipedia.org/wiki/Kay_Scarpetta), the private forensic consultant.
-
-# Version 1.0 - Phoebe Daring
-
-This version is a **Major Release With API Changes** release:
-
-**Breaking API Changes**:
-
-To support some of the new feature and simplify some macros, **TTS** API is now based on a
-lambda system. If this doesn't change the way tests are performed, it now requires to end all
-tests cases by a `;`.
-
-**Bug Fixes:**
-
- * Fix #3 - `TTS_TPL_CASES` now use meta-function based system for types generation
- * Fix #32 - Provide a way to log arbitrary data when failures occur
- * Fix #33 - Provide the `REQUIRED` option on tests to halt tests at first failure
- * Fix #34 - Provide a command-line option to fix precision when displaying floating points
- * Fix #37 - Stop displaying `char const*` as a string.
-
-## Detective who?
-[Phoebe Daring](https://en.wikipedia.org/wiki/Phoebe_Daring), the first half of the Daring Twins since 1912.
-
-# Version 0.2 - Kate Fansler
-
-This version is a fix+features release:
-
- * Fix #20 - Make string and pointers display in a more intuitive way
- * Fix #23 - Add proper parens in `EXPECT` macro
- * Add support for `constexpr` expectation and relational tests
- * `TTS_CASE_TPL` now generates one scenario per type
- * Fix #21 - Add runtime filtering for tests based on description string
-
-## Detective who?
-[Kate Fansler](https://en.wikipedia.org/wiki/Kate_Fansler), solving academic crimes since 1964.
-
-# Version 0.1 - Cadfael
-
-## First public release.
-
-**TTS** first complete release enables numerically oriented TDD including:
- - precision testing
- - checks over the data set
- - easy to customize the use of user-defined types.
-
-## Detective who?
-[Cadfael](https://en.wikipedia.org/wiki/Cadfael) is probably the eldest of all amateur detectives in history.
+**RABERU** (ラベル組) is now independent of the OFW repository.
diff --git a/doc/custom.hpp b/doc/custom.hpp
new file mode 100644
index 0000000..c36432d
--- /dev/null
+++ b/doc/custom.hpp
@@ -0,0 +1,102 @@
+#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
+
+//==================================================================================================
+/**
+ \page custom Tutorial: Customizing Keyword
+
+ @tableofcontents
+
+ \section custom_01 Using Pre-bound keyword
+
+ Sometimes you wish you could have a terser syntax for keyword parameters.
+ Let's say you want to pass a compile-time unrolling factor to some algorithm.
+
+ @code
+ // This is working but a bit verbose
+ using namespace rbr::literals;
+ inline constexpr auto unroll = rbr::keyword("unrolling"_id);
+
+ auto x = my_algorithm( unroll = std::integral_constant{});
+ @endcode
+
+ One idea is to defines a **pre-bound keyword parameter**, i.e constructs an inline
+ variable initialized with the result of the assignment of a value to a keyword.
+
+ @code
+ using namespace rbr::literals;
+ inline constexpr auto unrolling = rbr::keyword("unrolling"_id);
+
+ template inline constexpr auto unroll = (unrolling = std::integral_constant{});
+ @endcode
+
+ `unroll` is now ready to be passed around. To retrieve it, you'll need to use
+ the `unrolling` keyword.
+
+ @include doc/tutorial04.cpp
+
+ \section custom_02 Custom RABERU Keywords
+
+ The keywords provided by **RABERU** can also be extended to propose a better user experience.
+ This includes using user-defined type instead of **RABERU** long symbol to improve diagnostic
+ , complex checks or provide custom display when using stream insertion of settings.
+
+ \subsection custom-extension Extending RABERU Keywords
+ Let's start again with our unrolling option. This time we want to be able to be sure nobody
+ will use it with a non integral constant value and to display the value in a more informative way.
+ To do so, we can inherits from `rbr::as_keyword`, a CRTP enabled base class:
+
+ @code
+ struct unrolling : rbr::as_keyword
+ {
+ template
+ constexpr auto operator=(std::integral_constant const&) const noexcept
+ {
+ return rbr::option>{};
+ }
+
+ std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
+ };
+
+ template inline constexpr auto unroll = (unrolling{} = std::integral_constant{});
+ @endcode
+
+ What if we call `f( unrolling{} = 3.f );` ? Well, we go this error message:
+
+ @code
+ example.cpp:25:18: error: no viable overloaded '='
+ f( unrolling{} = 3.f );
+ ~~~~~~~~~~~ ^ ~~~
+ :8:18: note: candidate template ignored: could not match 'integral_constant' against 'float'
+ constexpr auto operator=(std::integral_constant const&) const noexcept
+ @endcode
+
+ \subsection custom-display Custom Keywords Display
+ Let's now improve the output of the option. Currently, the output is like:
+
+ @code
+ [unrolling] : 8 (std::integral_constant)
+ @endcode
+
+ A bit verbose especially for end-user.
+ Keyword-like entity can specialize a `display` member function to replace this output by a custom one.
+
+ @code
+ struct unrolling : rbr::as_keyword
+ {
+ template
+ constexpr auto operator=(std::integral_constant const&) const noexcept
+ {
+ return rbr::option>{};
+ }
+
+ std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
+ };
+ @endcode
+
+ The `display` member takes the output stream and the actual value of the option to be displayed.
+ One can then arrange those as they see fit, leading to a better output:
+
+ @include doc/tutorial05.cpp
+
+**/
+//==================================================================================================
diff --git a/doc/layout.xml b/doc/layout.xml
index 54f090b..aff55f9 100644
--- a/doc/layout.xml
+++ b/doc/layout.xml
@@ -3,39 +3,26 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
-
diff --git a/doc/licence.md b/doc/licence.md
index 858f5bc..478b52e 100644
--- a/doc/licence.md
+++ b/doc/licence.md
@@ -1,23 +1,25 @@
Licence {#licence}
=======
-This library is licensed under the [MIT License](http://opensource.org/licenses/MIT):
+This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ none
-Copyright : EVE Contributors & Maintainers
+Copyright : RABERU Project Contributors
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-and associated documentation files (the “Software”), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the
+software and accompanying documentation covered by this license (the "Software") to use, reproduce,
+display, distribute, execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the
+following:
-The above copyright notice and this permission notice shall be included in all copies or substantial
-portions of the Software.
+The copyright notices in the Software and this entire statement, including the above license grant,
+this restriction and the following disclaimer, must be included in all copies of the Software, in
+whole or in part, and all derivative works of the Software, unless such copies or derivative works
+are solely in the form of machine-executable object code generated by a source language processor.
-THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
+BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/page01_setup.md b/doc/page01_setup.md
deleted file mode 100644
index 191a573..0000000
--- a/doc/page01_setup.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# Setup
-
-## Direct file download
-
-1. Download the one header file `raberu.hpp` :
- ```
- wget https://raw.githubusercontent.com/jfalcou/raberu/main/include/raberu.hpp
- ```
-2. Copy it in the location of your choice.
-
-Using **Raberu** boils down to including `raberu.hpp` and compile using C++20.
-
-``` bash
-g++ my_app.cpp -I/path/to/raberu -std=c++20
-```
-
-## CMake FetchContent
-
-You can also use CMake FetchContent operation and use the `raberu::raberu` library
-target that our CMake exports.
-
-``` cmake
-##==================================================================================================
-## Your project setup
-##==================================================================================================
-cmake_minimum_required(VERSION 3.2)
-project(test_raberu LANGUAGES CXX)
-
-include(FetchContent)
-
-##==================================================================================================
-## Fetch Raberu and disable its test targets
-##==================================================================================================
-set(KUMI_BUILD_TEST OFF CACHE INTERNAL "OFF")
-FetchContent_Declare( raberu
- GIT_REPOSITORY https://github.com/jfalcou/raberu.git
- GIT_TAG main
- )
-
-FetchContent_MakeAvailable(raberu)
-
-##==================================================================================================
-## Using Raberu
-##==================================================================================================
-add_executable( my_app my_app.cpp)
-target_link_libraries(my_app raberu::raberu)
-```
-
-## CPM Integration
-You can install **Raberu** directly via [CPM](https://github.com/cpm-cmake/CPM.cmake). After
-[adding CPM to your CMake setup](https://github.com/cpm-cmake/CPM.cmake#adding-cpm), just
-add the following commands:
-
-```cmake
-include(CPM)
-
-CPMAddPackage ( NAME raberu
- URL https://github.com/jfalcou/raberu/archive/refs/tags/v2.0.zip
- VERSION 2.0
- OPTIONS "RABERU_BUILD_TEST OFF"
- )
-```
diff --git a/doc/page02_tutorial.hpp b/doc/page02_tutorial.hpp
deleted file mode 100644
index 797b31d..0000000
--- a/doc/page02_tutorial.hpp
+++ /dev/null
@@ -1,132 +0,0 @@
-#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
-
-//==================================================================================================
-//! \page tutorial Tutorial: Basic of RABERU
-//!
-//! **RABERU** main tool is the rbr::settings class that helps aggregate values into a set of parameters that later be queried. Let's build a small example of a function building a string from the replication of a given character.
-//!
-//! \section tutorial_01 Tutorial Keyword, Options, Settings
-//!
-//! Let's define a small function - `replicate` - that takes a character `c` and an integer `n` as parameters and return a string containing `c` repeated `n` times.
-//! As we want our users to have maximum flexibility, we will pass those parameters as keyword/value pairs.
-//!
-//! @include doc/tutorial01.cpp
-//!
-//! Let's decompose this code:
-//!
-//! + First, we define the `replicate` function. It takes two parameters which model
-//! rbr::concepts::option, ensuring the parameters are valid **RABERU** key/value pairs.
-//! + Those parameters are then turned into an instance of rbr::settings which will provide the interface to query values from the bundle of parameters.
-//! + We retrieve the value associated to the `"replication"_kw` and `"letter"_kw` keywords.
-//! + In the `main` function, we call `replicate` by passing key/value pairs. Note that the keys are the exact same identifiers than those used inside the function. Their order is irrelevant.
-//!
-//! That's it. The `replicate` function can now takes keywords arguments and as long as the proper keywords are used, it will work as intended.
-//!
-//! \section tutorial_02 Flavor of Keywords
-//!
-//! ## Regular keywords
-//!
-//! Let's say you want to pass a compile-time unrolling factor to some algorithm.
-//! You can use a regular keyword as seen in the tutorial:
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! auto x = my_algorithm( "unroll"_kw = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! This is working but a bit verbose. Another issue can be that documenting the fact
-//! that your functions awaits a `"unroll"_kw` maybe cumbersome.
-//!
-//! A nicer way to simplify the user experience is to preemptively defines a keyword variable.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! inline constexpr auto unroll = "unroll"_kw;
-//!
-//! auto x = my_algorithm( unroll = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! Slightly terser and far easier to document.
-//! You can also use the rbr::keyword factory that takes an ID and returns a keyword instance
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! inline constexpr auto unroll = rbr::keyword("unroll"_id);
-//!
-//! auto x = my_algorithm( unroll = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! ## Flags
-//! Sometimes, you just want to check if a given parameter has been passed but you don't really care about an associated value. Such keyword parameters are **flags**, carrying information about their sole presence without the need ot be bound to a value.
-//!
-//! They work in a similar way than regular keyword parameters but use the `_fl` user-defined literal
-//! ior the rbr::flag factory. Their value can be retrieved via rbr::settings::operator[]. If present, the value returned is `std::true_type`, otherwise `std::false_type` is returned.
-//!
-//! @include doc/tutorial02.cpp
-//!
-//! ## Checked keywords
-//! Regular keywords accept value of any types. Flag keyword implicitly behaves as boolean parameters.
-//! What if you need to have a keyword accepting values of a specific type ? Or, in more complex
-//! context, what if you need a keyword accepting values which types satisfy an arbitrary set of
-//! constraints ?
-//!
-//! To do so, we'll need to use the rbr::keyword factory function that
-//! accepts an optional template parameter. If this template parameter is a type,
-//! the keyword is setup to only accept value of this exact type.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! using namespace rbr::literals;
-//!
-//! // color can only accept unsigned 32 bits integer
-//! auto color = rbr::keyword("color"_id);
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! If this template parameter is a unary template meta-function `F`, the keyword is setup to only
-//! accept value which type satisfy `F::value == true`.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! using namespace rbr::literals;
-//!
-//! template struct large_type
-//! {
-//! static constexpr auto value = sizeof(T) >= 4;
-//! };
-//!
-//! // entropy can only accept types of at least 32 bits
-//! inline constexpr auto entropy = rbr::keyword( "entropy"_id);
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! \section tutorial_03 Settings
-//!
-//! Another important **RABERU** component is rbr::settings. It aggregates key/value pairs in a way their
-//! exploitation is simplified. rbr::settings provides functions for retrieving value from keywords,
-//! inspect the stored keywords and more.
-//!
-//! ## Defining a Settings
-//! rbr::settings can be directly constructed from an arbitrary list of options, ie values bound to
-//! a keyword. Once constructed, its operator[] can be used to fetch the value of a given keyword.
-//!
-//! @include doc/tutorial03.cpp
-//!
-//! ## Stream insertion
-//! rbr::settings can be streamed to display the list of keyword/value pairs it contains
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! #include
-//! #include
-//!
-//! int main()
-//! {
-//! using namespace rbr::literals;
-//!
-//! auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl, "value"_kw = 7.7f);
-//!
-//! std::cout << values << "\n";
-//! }
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! The expected output should be:
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//! 'size' : 75 (long long unsigned int)
-//! 'transparent' : 1 (std::integral_constant)
-//! 'value' : 7.7 (float)
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//==================================================================================================
diff --git a/doc/page03_custom.hpp b/doc/page03_custom.hpp
deleted file mode 100644
index df1cb6d..0000000
--- a/doc/page03_custom.hpp
+++ /dev/null
@@ -1,98 +0,0 @@
-#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
-
-//==================================================================================================
-//! \page custom Tutorial: Customizing Keyword
-//!
-//! \section custom_01 Using Pre-bound keyword
-//!
-//! Sometimes you wish you could have a terser syntax for keyword parameters.
-//! Let's say you want to pass a compile-time unrolling factor to some algorithm.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! // This is working but a bit verbose
-//! using namespace rbr::literals;
-//! inline constexpr auto unroll = rbr::keyword("unrolling"_id);
-//!
-//! auto x = my_algorithm( unroll = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! One idea is to defines a **pre-bound keyword parameter**, i.e constructs an inline
-//! variable initialized with the result of the assignment of a value to a keyword.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! using namespace rbr::literals;
-//! inline constexpr auto unrolling = rbr::keyword("unrolling"_id);
-//!
-//! template inline constexpr auto unroll = (unrolling = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! `unroll` is now ready to be passed around. To retrieve it, you'll need to use
-//! the `unrolling` keyword.
-//!
-//! @include doc/tutorial04.cpp
-//!
-//! \section custom_02 Custom RABERU Keywords
-//!
-//! THe keywords provided by **RABERU** can also be extended to propose a better user experience.
-//! This includes using user-defined type instead of **RABERU** long symbol to improve diagnostic
-//! , complex checks or provide custom display when using stream insertion of settings.
-//!
-//! ## Extending RABERU Keywords
-//! Let's start again with our unrolling option. This time we want to be able to be sure nobody
-//! will use it with a non integral constant value and to display the value in a more informative way.
-//! To do so, we can inherits from `rbr::as_keyword`, a CRTP enabled base class:
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! struct unrolling : rbr::as_keyword
-//! {
-//! template
-//! constexpr auto operator=(std::integral_constant const&) const noexcept
-//! {
-//! return rbr::option>{};
-//! }
-//!
-//! std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
-//! };
-//!
-//! template inline constexpr auto unroll = (unrolling{} = std::integral_constant{});
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! What if we call `f( unrolling{} = 3.f );` ? Well, we go this error message:
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! example.cpp:25:18: error: no viable overloaded '='
-//! f( unrolling{} = 3.f );
-//! ~~~~~~~~~~~ ^ ~~~
-//! :8:18: note: candidate template ignored: could not match 'integral_constant' against 'float'
-//! constexpr auto operator=(std::integral_constant const&) const noexcept
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! ## Custom Keywords Display
-//! Let's now improve the output of the option. Currently, the output is like:
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! [unrolling] : 8 (std::integral_constant)
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! A bit verbose especially for end-user.
-//! Keyword-like entity can specialize a `display` member function to replace this output by a custom one.
-//!
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
-//! struct unrolling : rbr::as_keyword
-//! {
-//! template
-//! constexpr auto operator=(std::integral_constant const&) const noexcept
-//! {
-//! return rbr::option>{};
-//! }
-//!
-//! std::ostream& display(std::ostream& os, auto v) const { return os << "Unroll Factor: " << v; }
-//! };
-//! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//!
-//! The `display` member takes the output stream and the actual value of the option to be displayed.
-//! One can then arrange those as they see fit, leading to a better output:
-//!
-//! @include doc/tutorial05.cpp
-//!
-//==================================================================================================
diff --git a/doc/page10_changelog.md b/doc/page10_changelog.md
deleted file mode 100644
index a19da81..0000000
--- a/doc/page10_changelog.md
+++ /dev/null
@@ -1,37 +0,0 @@
-Change Log {#changelog}
-==========
-
-# Version 2.0 - Past Prologue
-
-## Bug Fixes
-* Moved from `pragma once` to `#ifndef` to allow for multiple raberu files to coexist in multiple projects.
-* Fixed a regression in Visual Studio that affected ability to run tests.
-* Fix #6 - Compile-time ID are now properly displayed and compared without any issues due to terminal `\0`.
-
-## New Features
-* Fix #4 - Simplify and generalize custom keyword generation
- A new CRTP class `rbr::as_keyword` streamlines the definition of compact keyword by users while
- supporting the whole range of built-in keywords. Associated documentation has been updated.
-
-* Fix #2 - Implement direct keyword value access
- Keyword can now fetch themselves from a bundles of options. E.g
-
- ``` c++
- inline constexpr auto coord_ = "coord"_kw;
- inline constexpr auto is_modal_ = "is_modal"_fl;
-
- auto x = coord_(coord_ = "Jane"s, is_modal_);
- ```
-
-* Fix #5 - Mass extractors for keyword and values
- `rbr::keywords` and`rbr::values` can be used to retrieve a tuple-like object containing all the
- keywords or values from a bundle of options.
-
-* `rbr::get_type` is removed and is replaced by `rbr::fetch` and `rbr::result::fetch_t`.
- This functions provides an infix syntax for options access.
-
-# Version 1.0 - Emissary
-
-## First autonomous public release.
-
-**RABERU** (ラベル組) is now independent of the OFW repository.
diff --git a/doc/page10_licence.md b/doc/page10_licence.md
deleted file mode 100644
index 478b52e..0000000
--- a/doc/page10_licence.md
+++ /dev/null
@@ -1,25 +0,0 @@
-Licence {#licence}
-=======
-
-This library is licensed under the [Boost Software License](https://opensource.org/licenses/BSL-1.0):
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ none
-Copyright : RABERU Project Contributors
-
-Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the
-software and accompanying documentation covered by this license (the "Software") to use, reproduce,
-display, distribute, execute, and transmit the Software, and to prepare derivative works of the
-Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the
-following:
-
-The copyright notices in the Software and this entire statement, including the above license grant,
-this restriction and the following disclaimer, must be included in all copies of the Software, in
-whole or in part, and all derivative works of the Software, unless such copies or derivative works
-are solely in the form of machine-executable object code generated by a source language processor.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
-NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
-NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE
-BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/setup.hpp b/doc/setup.hpp
new file mode 100644
index 0000000..f8e8a15
--- /dev/null
+++ b/doc/setup.hpp
@@ -0,0 +1,102 @@
+#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
+
+//==================================================================================================
+/**
+ @page setup Setup
+
+ @tableofcontents
+
+ @section setup-source Install from the source
+
+ Code source of **RABERU** is available on GitHub and can be retrieved via the following command:
+
+ @code
+ $ git clone https://github.com/jfalcou/raberu.git
+ @endcode
+
+ Once retrieved, you should have a `raberu` folder which contains the whole source code.
+
+ Create a `build` directory here and enter it. Once in the `build` directory,
+ you can use **CMake** to generate the build system for **RABERU**. We recommend using
+ Ninja but any build system is fine.
+
+ @code
+ $ mkdir build
+ $ cd build
+ $ cmake .. -G Ninja
+ @endcode
+
+ Once **CMake** completes, you can use the `install` target to build and install **RABERU**.
+ By default, the library will be installed in the `/usr/local` directory, thus requiring
+ root privileges.
+
+ @code
+ $ sudo ninja install
+ @endcode
+
+ You can select an alternative installation path by specifying the `CMAKE_INSTALL_PREFIX`
+ option at configuration time.
+
+ @code
+ $ cmake .. -G Ninja -DCMAKE_INSTALL_PREFIX=path/to/install
+ $ ninja install
+ @endcode
+
+ Once installed, **RABERU** is usable directly by providing the path to its installed files.
+
+ @section setup-standalone Standalone setup
+
+ You can also use **RABERU** via a single standalone file that can be vendored in your own project without
+ having to deal with **RABERU** as a dependency.
+
+ Simply use `wget` to fetch the latest version and place it where you want:
+
+ @code
+ wget https://raw.githubusercontent.com/jfalcou/raberu/main/standalone/raberu/raberu.hpp
+ @endcode
+
+ Use **RABERU** by just compiling your code with the include path pointing to the location of this single file.
+
+ @section setup-fetchcontent CMake FetchContent
+
+ You can also use CMake FetchContent operation and use the `raberu::raberu` library target that our CMake exports.
+
+ @code{cmake}
+ ##==================================================================================================
+ ## Your project setup
+ ##==================================================================================================
+ cmake_minimum_required(VERSION 3.22)
+ project(raberu-fetch LANGUAGES CXX)
+
+ include(FetchContent)
+ FetchContent_Declare(raberu GIT_REPOSITORY "https://github.com/jfalcou/raberu.git")
+ FetchContent_MakeAvailable(raberu)
+
+ add_executable(test_raberu ../main.cpp)
+ target_link_libraries(test_raberu PUBLIC raberu::raberu)
+ @endcode
+
+ @section setup-cpm Setup with CPM
+
+ The **RABERU** library can be setup using [CPM](https://github.com/cpm-cmake/CPM.cmake):
+
+ @code{cmake}
+ ##==================================================================================================
+ ## Your project setup
+ ##==================================================================================================
+ cmake_minimum_required(VERSION 3.18)
+ project(raberu-cpm LANGUAGES CXX)
+
+ # Setup CPM - See https://github.com/cpm-cmake/CPM.cmake#adding-cpm
+ include(cpm.cmake)
+
+ CPMAddPackage ( NAME raberu
+ GIT_REPOSITORY "https://github.com/jfalcou/raberu.git"
+ OPTIONS "RABERU_BUILD_TEST OFF"
+ )
+
+ add_executable(test_raberu ../main.cpp)
+ target_link_libraries(test_raberu PUBLIC raberu::raberu)
+ @endcode
+**/
+//==================================================================================================
diff --git a/doc/tutorial.hpp b/doc/tutorial.hpp
new file mode 100644
index 0000000..e48b472
--- /dev/null
+++ b/doc/tutorial.hpp
@@ -0,0 +1,144 @@
+#error DO NOT INCLUDE - DOCUMENTATION PURPOSE ONLY
+
+//==================================================================================================
+/**
+ \page tutorial RABERU 101
+
+ @tableofcontents
+
+ The **RABERU** library provides a way to define and use named parameters, *i.e* a list of values assigned to
+ arbitrary keyword-like identifiers, to functions.
+
+ It does so by providing:
+
+ + a protocol to define such keywords.
+ + a type to process such aggregate of parameters.
+ + a `constexpr`-compatible implementation for all of those.
+
+
+ \section tutorial_01 Keyword, Options, Settings
+
+ Let's define a small function - `replicate` - that takes a character `c` and an integer `n` as parameters and
+ return a string containing `c` repeated `n` times. As we want our users to have maximum flexibility, we will
+ pass those parameters as keyword/value pairs.
+
+ @include doc/tutorial01.cpp
+
+ Let's decompose this code:
+
+ + First, we define the `replicate` function. It takes two parameters which model
+ rbr::concepts::option, ensuring the parameters are valid **RABERU** key/value pairs.
+ + Those parameters are then turned into an instance of rbr::settings which will provide the interface to query values from the bundle of parameters.
+ + We retrieve the value associated to the `"replication"_kw` and `"letter"_kw` keywords.
+ + In the `main` function, we call `replicate` by passing key/value pairs. Note that the keys are the exact same identifiers than those used inside the function. Their order is irrelevant.
+
+ That's it. The `replicate` function can now takes keywords arguments and as long as the proper keywords are used, it will work as intended.
+
+ \section tutorial_02 Flavor of Keywords
+
+ \subsection tutorial-keywords Regular keywords
+
+ Let's say you want to pass a compile-time unrolling factor to some algorithm.
+ You can use a regular keyword as seen in the tutorial:
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ auto x = my_algorithm( "unroll"_kw = std::integral_constant{});
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ This is working but a bit verbose. Another issue can be that documenting the fact
+ that your functions awaits a `"unroll"_kw` maybe cumbersome.
+
+ A nicer way to simplify the user experience is to preemptively defines a keyword variable.
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ inline constexpr auto unroll = "unroll"_kw;
+
+ auto x = my_algorithm( unroll = std::integral_constant{});
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Slightly terser and far easier to document.
+ You can also use the rbr::keyword factory that takes an ID and returns a keyword instance
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ inline constexpr auto unroll = rbr::keyword("unroll"_id);
+
+ auto x = my_algorithm( unroll = std::integral_constant{});
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ \subsection tutorial-flags Flags
+ Sometimes, you just want to check if a given parameter has been passed but you don't really care about an associated value. Such keyword parameters are **flags**, carrying information about their sole presence without the need ot be bound to a value.
+
+ They work in a similar way than regular keyword parameters but use the `_fl` user-defined literal
+ ior the rbr::flag factory. Their value can be retrieved via rbr::settings::operator[]. If present, the value returned is `std::true_type`, otherwise `std::false_type` is returned.
+
+ @include doc/tutorial02.cpp
+
+ \subsection tutorial-checked Checked keywords
+ Regular keywords accept value of any types. Flag keyword implicitly behaves as boolean parameters.
+ What if you need to have a keyword accepting values of a specific type ? Or, in more complex
+ context, what if you need a keyword accepting values which types satisfy an arbitrary set of
+ constraints ?
+
+ To do so, we'll need to use the rbr::keyword factory function that
+ accepts an optional template parameter. If this template parameter is a type,
+ the keyword is setup to only accept value of this exact type.
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ using namespace rbr::literals;
+
+ // color can only accept unsigned 32 bits integer
+ auto color = rbr::keyword("color"_id);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ If this template parameter is a unary template meta-function `F`, the keyword is setup to only
+ accept value which type satisfy `F::value == true`.
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ using namespace rbr::literals;
+
+ template struct large_type
+ {
+ static constexpr auto value = sizeof(T) >= 4;
+ };
+
+ // entropy can only accept types of at least 32 bits
+ inline constexpr auto entropy = rbr::keyword( "entropy"_id);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ \section tutorial_03 Settings
+
+ Another important **RABERU** component is rbr::settings. It aggregates key/value pairs in a way their
+ exploitation is simplified. rbr::settings provides functions for retrieving value from keywords,
+ inspect the stored keywords and more.
+
+ \subsection tutorial-settings Defining a Settings
+ rbr::settings can be directly constructed from an arbitrary list of options, ie values bound to
+ a keyword. Once constructed, its operator[] can be used to fetch the value of a given keyword.
+
+ @include doc/tutorial03.cpp
+
+ \subsection tutorial-stream Stream insertion
+ rbr::settings can be streamed to display the list of keyword/value pairs it contains
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c++
+ #include
+ #include
+
+ int main()
+ {
+ using namespace rbr::literals;
+
+ auto values = rbr::settings("size"_kw = 75ULL, "transparent"_fl, "value"_kw = 7.7f);
+
+ std::cout << values << "\n";
+ }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The expected output should be:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 'size' : 75 (long long unsigned int)
+ 'transparent' : 1 (std::integral_constant)
+ 'value' : 7.7 (float)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**/
+//==================================================================================================
diff --git a/test/doc/tutorial05.cpp b/test/doc/tutorial05.cpp
index 2653136..0dd8504 100644
--- a/test/doc/tutorial05.cpp
+++ b/test/doc/tutorial05.cpp
@@ -7,10 +7,6 @@
#include
#include
-#include
-#include
-#include
-
struct unrolling : rbr::as_keyword
{
template