changeset 773:8c44bbcbbab9

Misc: style, cleanup and update
author David Demelier <markand@malikania.fr>
date Fri, 26 Oct 2018 13:01:00 +0200
parents f5ccf65ae929
children bfc51f8a00f3
files .editorconfig CHANGES.md CMakeLists.txt CONTRIBUTE.md STYLE.md cmake/IrccdOptions.cmake cmake/IrccdPackage.cmake cmake/IrccdSystem.cmake cmake/IrccdVersion.cmake cmake/check/PutTime.cmake cmake/export/CMakeLists.txt cmake/function/IrccdBuildHtml.cmake cmake/function/IrccdDefineExecutable.cmake cmake/function/IrccdDefineLibrary.cmake cmake/function/IrccdDefineMan.cmake cmake/function/IrccdDefinePlugin.cmake cmake/function/IrccdDefineTest.cmake cmake/function/IrccdIndentMessage.cmake cmake/function/IrccdVeraCheck.cmake cmake/internal/Irccd2Config.cmake.in cmake/internal/irccd2.pc.in cmake/internal/sysconfig.hpp.in cmake/packages/FindEditline.cmake cmake/packages/FindPandoc.cmake doc/CMakeLists.txt doc/doxygen/CMakeLists.txt doc/examples/CMakeLists.txt doc/html/CMakeLists.txt irccd-test/CMakeLists.txt irccd-test/main.cpp irccd/CMakeLists.txt irccd/main.cpp irccdctl/CMakeLists.txt irccdctl/alias.cpp irccdctl/alias.hpp irccdctl/cli.cpp irccdctl/cli.hpp irccdctl/main.cpp libirccd-core/CMakeLists.txt libirccd-core/irccd/acceptor.hpp libirccd-core/irccd/config.cpp libirccd-core/irccd/config.hpp libirccd-core/irccd/connector.hpp libirccd-core/irccd/fs_util.cpp libirccd-core/irccd/fs_util.hpp libirccd-core/irccd/ini.cpp libirccd-core/irccd/ini.hpp libirccd-core/irccd/ini_util.hpp libirccd-core/irccd/json_util.cpp libirccd-core/irccd/json_util.hpp libirccd-core/irccd/socket_acceptor.hpp libirccd-core/irccd/socket_connector.hpp libirccd-core/irccd/socket_stream.hpp libirccd-core/irccd/stream.hpp libirccd-core/irccd/string_util.cpp libirccd-core/irccd/string_util.hpp libirccd-core/irccd/system.cpp libirccd-core/irccd/tls_acceptor.hpp libirccd-core/irccd/tls_connector.hpp libirccd-core/irccd/tls_stream.hpp libirccd-core/irccd/xdg.hpp libirccd-ctl/CMakeLists.txt libirccd-ctl/irccd/ctl/controller.cpp libirccd-ctl/irccd/ctl/controller.hpp libirccd-js/CMakeLists.txt libirccd-js/irccd/js/directory_js_api.cpp libirccd-js/irccd/js/directory_js_api.hpp libirccd-js/irccd/js/duk.cpp libirccd-js/irccd/js/duk.hpp libirccd-js/irccd/js/elapsed_timer_js_api.cpp libirccd-js/irccd/js/elapsed_timer_js_api.hpp libirccd-js/irccd/js/file_js_api.cpp libirccd-js/irccd/js/file_js_api.hpp libirccd-js/irccd/js/irccd_js_api.cpp libirccd-js/irccd/js/irccd_js_api.hpp libirccd-js/irccd/js/js_api.cpp libirccd-js/irccd/js/js_api.hpp libirccd-js/irccd/js/js_plugin.cpp libirccd-js/irccd/js/js_plugin.hpp libirccd-js/irccd/js/logger_js_api.cpp libirccd-js/irccd/js/logger_js_api.hpp libirccd-js/irccd/js/plugin_js_api.cpp libirccd-js/irccd/js/plugin_js_api.hpp libirccd-js/irccd/js/server_js_api.cpp libirccd-js/irccd/js/server_js_api.hpp libirccd-js/irccd/js/system_js_api.cpp libirccd-js/irccd/js/system_js_api.hpp libirccd-js/irccd/js/timer_js_api.cpp libirccd-js/irccd/js/timer_js_api.hpp libirccd-js/irccd/js/unicode.cpp libirccd-js/irccd/js/unicode.hpp libirccd-js/irccd/js/unicode_js_api.cpp libirccd-js/irccd/js/unicode_js_api.hpp libirccd-js/irccd/js/util_js_api.cpp libirccd-js/irccd/js/util_js_api.hpp libirccd-test/CMakeLists.txt libirccd-test/irccd/test/cli_fixture.cpp libirccd-test/irccd/test/cli_fixture.hpp libirccd-test/irccd/test/command_fixture.cpp libirccd-test/irccd/test/command_fixture.hpp libirccd-test/irccd/test/debug_server.cpp libirccd-test/irccd/test/debug_server.hpp libirccd-test/irccd/test/irccd_fixture.cpp libirccd-test/irccd/test/irccd_fixture.hpp libirccd-test/irccd/test/js_fixture.cpp libirccd-test/irccd/test/js_fixture.hpp libirccd-test/irccd/test/js_plugin_fixture.cpp libirccd-test/irccd/test/js_plugin_fixture.hpp libirccd-test/irccd/test/mock.cpp libirccd-test/irccd/test/mock.hpp libirccd-test/irccd/test/mock_plugin.cpp libirccd-test/irccd/test/mock_plugin.hpp libirccd-test/irccd/test/mock_server.cpp libirccd-test/irccd/test/mock_server.hpp libirccd/CMakeLists.txt libirccd/irccd/daemon/command.cpp libirccd/irccd/daemon/command.hpp libirccd/irccd/daemon/dynlib_plugin.cpp libirccd/irccd/daemon/dynlib_plugin.hpp libirccd/irccd/daemon/irc.cpp libirccd/irccd/daemon/irc.hpp libirccd/irccd/daemon/irccd.cpp libirccd/irccd/daemon/irccd.hpp libirccd/irccd/daemon/logger.cpp libirccd/irccd/daemon/logger.hpp libirccd/irccd/daemon/plugin.cpp libirccd/irccd/daemon/plugin.hpp libirccd/irccd/daemon/plugin_service.cpp libirccd/irccd/daemon/plugin_service.hpp libirccd/irccd/daemon/rule.cpp libirccd/irccd/daemon/rule.hpp libirccd/irccd/daemon/rule_service.cpp libirccd/irccd/daemon/rule_service.hpp libirccd/irccd/daemon/rule_util.cpp libirccd/irccd/daemon/rule_util.hpp libirccd/irccd/daemon/server.cpp libirccd/irccd/daemon/server.hpp libirccd/irccd/daemon/server_service.cpp libirccd/irccd/daemon/server_service.hpp libirccd/irccd/daemon/server_util.cpp libirccd/irccd/daemon/server_util.hpp libirccd/irccd/daemon/transport_client.cpp libirccd/irccd/daemon/transport_client.hpp libirccd/irccd/daemon/transport_server.cpp libirccd/irccd/daemon/transport_server.hpp libirccd/irccd/daemon/transport_service.cpp libirccd/irccd/daemon/transport_service.hpp libirccd/irccd/daemon/transport_util.cpp plugins/CMakeLists.txt plugins/ask/ask.js plugins/auth/auth.js plugins/hangman/hangman.js plugins/history/history.js plugins/joke/joke.js plugins/links/CMakeLists.txt plugins/links/links.cpp plugins/links/links.hpp plugins/links/requester.cpp plugins/links/requester.hpp plugins/links/scope_exit.cpp plugins/links/scope_exit.hpp plugins/links/uri.cpp plugins/links/uri.hpp plugins/logger/logger.js plugins/plugin/plugin.js plugins/roulette/roulette.js plugins/tictactoe/tictactoe.js systemd/CMakeLists.txt tests/CMakeLists.txt tests/src/irccdctl/CMakeLists.txt tests/src/irccdctl/cli-plugin-config/CMakeLists.txt tests/src/irccdctl/cli-plugin-config/main.cpp tests/src/irccdctl/cli-plugin-info/CMakeLists.txt tests/src/irccdctl/cli-plugin-info/main.cpp tests/src/irccdctl/cli-plugin-list/CMakeLists.txt tests/src/irccdctl/cli-plugin-list/main.cpp tests/src/irccdctl/cli-plugin-load/CMakeLists.txt tests/src/irccdctl/cli-plugin-load/main.cpp tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt tests/src/irccdctl/cli-plugin-reload/main.cpp tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt tests/src/irccdctl/cli-plugin-unload/main.cpp tests/src/irccdctl/cli-rule-add/CMakeLists.txt tests/src/irccdctl/cli-rule-add/main.cpp tests/src/irccdctl/cli-rule-edit/CMakeLists.txt tests/src/irccdctl/cli-rule-edit/main.cpp tests/src/irccdctl/cli-rule-info/CMakeLists.txt tests/src/irccdctl/cli-rule-info/main.cpp tests/src/irccdctl/cli-rule-list/CMakeLists.txt tests/src/irccdctl/cli-rule-list/main.cpp tests/src/irccdctl/cli-rule-move/CMakeLists.txt tests/src/irccdctl/cli-rule-move/main.cpp tests/src/irccdctl/cli-rule-remove/CMakeLists.txt tests/src/irccdctl/cli-rule-remove/main.cpp tests/src/irccdctl/cli-server-disconnect/CMakeLists.txt tests/src/irccdctl/cli-server-disconnect/main.cpp tests/src/irccdctl/cli-server-info/CMakeLists.txt tests/src/irccdctl/cli-server-info/main.cpp tests/src/irccdctl/cli-server-invite/CMakeLists.txt tests/src/irccdctl/cli-server-invite/main.cpp tests/src/irccdctl/cli-server-join/CMakeLists.txt tests/src/irccdctl/cli-server-join/main.cpp tests/src/irccdctl/cli-server-kick/CMakeLists.txt tests/src/irccdctl/cli-server-kick/main.cpp tests/src/irccdctl/cli-server-list/CMakeLists.txt tests/src/irccdctl/cli-server-list/main.cpp tests/src/irccdctl/cli-server-me/CMakeLists.txt tests/src/irccdctl/cli-server-me/main.cpp tests/src/irccdctl/cli-server-message/CMakeLists.txt tests/src/irccdctl/cli-server-message/main.cpp tests/src/irccdctl/cli-server-mode/CMakeLists.txt tests/src/irccdctl/cli-server-mode/main.cpp tests/src/irccdctl/cli-server-nick/CMakeLists.txt tests/src/irccdctl/cli-server-nick/main.cpp tests/src/irccdctl/cli-server-notice/CMakeLists.txt tests/src/irccdctl/cli-server-notice/main.cpp tests/src/irccdctl/cli-server-part/CMakeLists.txt tests/src/irccdctl/cli-server-part/main.cpp tests/src/irccdctl/cli-server-reconnect/CMakeLists.txt tests/src/irccdctl/cli-server-reconnect/main.cpp tests/src/irccdctl/cli-server-topic/CMakeLists.txt tests/src/irccdctl/cli-server-topic/main.cpp tests/src/libcommon/fs-util/CMakeLists.txt tests/src/libcommon/fs-util/main.cpp tests/src/libcommon/io/CMakeLists.txt tests/src/libcommon/io/main.cpp tests/src/libcommon/string-util/CMakeLists.txt tests/src/libcommon/string-util/main.cpp tests/src/libirccd-js/js-api-directory/CMakeLists.txt tests/src/libirccd-js/js-api-directory/main.cpp tests/src/libirccd-js/js-api-elapsedtimer/CMakeLists.txt tests/src/libirccd-js/js-api-elapsedtimer/main.cpp tests/src/libirccd-js/js-api-file/CMakeLists.txt tests/src/libirccd-js/js-api-file/main.cpp tests/src/libirccd-js/js-api-irccd/CMakeLists.txt tests/src/libirccd-js/js-api-irccd/main.cpp tests/src/libirccd-js/js-api-logger/CMakeLists.txt tests/src/libirccd-js/js-api-logger/main.cpp tests/src/libirccd-js/js-api-system/CMakeLists.txt tests/src/libirccd-js/js-api-system/main.cpp tests/src/libirccd-js/js-api-timer/CMakeLists.txt tests/src/libirccd-js/js-api-timer/main.cpp tests/src/libirccd-js/js-api-timer/timer.js tests/src/libirccd-js/js-api-unicode/CMakeLists.txt tests/src/libirccd-js/js-api-unicode/main.cpp tests/src/libirccd-js/js-api-util/CMakeLists.txt tests/src/libirccd-js/js-api-util/main.cpp tests/src/libirccd-js/js-plugin/CMakeLists.txt tests/src/libirccd-js/js-plugin/config-assign.js tests/src/libirccd-js/js-plugin/main.cpp tests/src/libirccd/command-plugin-config/CMakeLists.txt tests/src/libirccd/command-plugin-config/main.cpp tests/src/libirccd/command-plugin-info/CMakeLists.txt tests/src/libirccd/command-plugin-info/main.cpp tests/src/libirccd/command-plugin-list/CMakeLists.txt tests/src/libirccd/command-plugin-list/main.cpp tests/src/libirccd/command-plugin-load/CMakeLists.txt tests/src/libirccd/command-plugin-load/main.cpp tests/src/libirccd/command-plugin-reload/main.cpp tests/src/libirccd/command-plugin-unload/CMakeLists.txt tests/src/libirccd/command-plugin-unload/main.cpp tests/src/libirccd/command-rule-add/CMakeLists.txt tests/src/libirccd/command-rule-add/main.cpp tests/src/libirccd/command-rule-edit/CMakeLists.txt tests/src/libirccd/command-rule-edit/main.cpp tests/src/libirccd/command-rule-info/CMakeLists.txt tests/src/libirccd/command-rule-info/main.cpp tests/src/libirccd/command-rule-list/CMakeLists.txt tests/src/libirccd/command-rule-list/main.cpp tests/src/libirccd/command-rule-move/CMakeLists.txt tests/src/libirccd/command-rule-move/main.cpp tests/src/libirccd/command-rule-remove/CMakeLists.txt tests/src/libirccd/command-rule-remove/main.cpp tests/src/libirccd/command-server-connect/CMakeLists.txt tests/src/libirccd/command-server-connect/main.cpp tests/src/libirccd/command-server-disconnect/CMakeLists.txt tests/src/libirccd/command-server-disconnect/main.cpp tests/src/libirccd/command-server-info/CMakeLists.txt tests/src/libirccd/command-server-info/main.cpp tests/src/libirccd/command-server-invite/CMakeLists.txt tests/src/libirccd/command-server-invite/main.cpp tests/src/libirccd/command-server-join/CMakeLists.txt tests/src/libirccd/command-server-join/main.cpp tests/src/libirccd/command-server-kick/CMakeLists.txt tests/src/libirccd/command-server-kick/main.cpp tests/src/libirccd/command-server-list/CMakeLists.txt tests/src/libirccd/command-server-list/main.cpp tests/src/libirccd/command-server-me/CMakeLists.txt tests/src/libirccd/command-server-me/main.cpp tests/src/libirccd/command-server-message/CMakeLists.txt tests/src/libirccd/command-server-message/main.cpp tests/src/libirccd/command-server-mode/CMakeLists.txt tests/src/libirccd/command-server-mode/main.cpp tests/src/libirccd/command-server-nick/CMakeLists.txt tests/src/libirccd/command-server-nick/main.cpp tests/src/libirccd/command-server-notice/CMakeLists.txt tests/src/libirccd/command-server-notice/main.cpp tests/src/libirccd/command-server-part/CMakeLists.txt tests/src/libirccd/command-server-part/main.cpp tests/src/libirccd/command-server-reconnect/CMakeLists.txt tests/src/libirccd/command-server-reconnect/main.cpp tests/src/libirccd/command-server-topic/CMakeLists.txt tests/src/libirccd/command-server-topic/main.cpp tests/src/libirccd/dynlib-plugin/CMakeLists.txt tests/src/libirccd/dynlib-plugin/main.cpp tests/src/libirccd/dynlib-plugin/test_plugin.cpp tests/src/libirccd/irc/CMakeLists.txt tests/src/libirccd/irc/main.cpp tests/src/libirccd/logger/CMakeLists.txt tests/src/libirccd/logger/main.cpp tests/src/libirccd/rule-util/CMakeLists.txt tests/src/libirccd/rule-util/main.cpp tests/src/libirccd/rules/CMakeLists.txt tests/src/libirccd/rules/main.cpp tests/src/plugins/ask/CMakeLists.txt tests/src/plugins/ask/main.cpp tests/src/plugins/auth/CMakeLists.txt tests/src/plugins/auth/main.cpp tests/src/plugins/hangman/CMakeLists.txt tests/src/plugins/hangman/main.cpp tests/src/plugins/history/CMakeLists.txt tests/src/plugins/history/main.cpp tests/src/plugins/joke/CMakeLists.txt tests/src/plugins/joke/error-empty.json tests/src/plugins/joke/error-invalid.json tests/src/plugins/joke/error-not-array.json tests/src/plugins/joke/error-toobig.json tests/src/plugins/joke/jokes.json tests/src/plugins/joke/main.cpp tests/src/plugins/logger/CMakeLists.txt tests/src/plugins/logger/main.cpp tests/src/plugins/plugin/CMakeLists.txt tests/src/plugins/plugin/main.cpp tests/src/plugins/tictactoe/CMakeLists.txt tests/src/plugins/tictactoe/main.cpp win32/CMakeLists.txt
diffstat 336 files changed, 25654 insertions(+), 25342 deletions(-) [+]
line wrap: on
line diff
--- a/.editorconfig	Wed Oct 24 13:24:03 2018 +0200
+++ b/.editorconfig	Fri Oct 26 13:01:00 2018 +0200
@@ -4,9 +4,9 @@
 charset = utf-8
 end_of_line = lf
 insert_final_newline = true
-indent_style = space
-indent_size = 4
+indent_style = tab
+indent_size = 8
 trim_trailing_whitespace = true
 
-[*.html]
-indent_size = 2
+[*.{html,xml,yml}]
+indent_size = 4
--- a/CHANGES.md	Wed Oct 24 13:24:03 2018 +0200
+++ b/CHANGES.md	Fri Oct 26 13:01:00 2018 +0200
@@ -6,137 +6,137 @@
 
 Irccd:
 
-  - The default server identity now uses the system account name if possible by
-    default (#607),
-  - New sections `[paths]` and `[paths.plugin]` have been added to control
-    standard paths for both irccd and plugins (#611),
-  - If Mercurial is found, the version is bundled in `irccd --version`,
-  - Irccd no longer supports uid, gid, pid and daemon features (#846).
+- The default server identity now uses the system account name if possible by
+  default (#607),
+- New sections `[paths]` and `[paths.plugin]` have been added to control
+  standard paths for both irccd and plugins (#611),
+- If Mercurial is found, the version is bundled in `irccd --version`,
+- Irccd no longer supports uid, gid, pid and daemon features (#846).
 
 Irccd test:
 
-  - A brand new `irccd-test` program has been added to tests plugins on the
-    command line (#569).
+- A brand new `irccd-test` program has been added to tests plugins on the
+  command line (#569).
 
 CMake:
 
-  - CMake no longer create a fake installation directory while building (#674),
-  - All targets are placed into the `bin` directory while building (#715).
+- CMake no longer create a fake installation directory while building (#674),
+- All targets are placed into the `bin` directory while building (#715).
 
 Network API:
 
-  - Network commands return an error code instead of a string (#739).
+- Network commands return an error code instead of a string (#739).
 
 Javascript API:
 
-  - The Irccd.Timer API now runs on top of Boost.Asio and no longer have custom
-    buggy code (#595),
-  - New Irccd.Server.isSelf function (#735).
+- The Irccd.Timer API now runs on top of Boost.Asio and no longer have custom
+  buggy code (#595),
+- New Irccd.Server.isSelf function (#735).
 
 Internal:
 
-  - The code is now based on Boost for many internal parts of the core, (#593),
-    (#594), (#595), (#681), (#697),
-  - The libircclient has been replaced by a simple homemade library (#581).
+- The code is now based on Boost for many internal parts of the core, (#593),
+  (#594), (#595), (#681), (#697),
+- The libircclient has been replaced by a simple homemade library (#581).
 
 Plugins:
 
-  - Introduce brand new joke plugin (#609),
-  - Introduce brand new tictactoe plugin (#393),
-  - Introduce brand new links plugin (#872).
+- Introduce brand new joke plugin (#609),
+- Introduce brand new tictactoe plugin (#393),
+- Introduce brand new links plugin (#872).
 
 irccd 2.2.0 2017-09-26
 ----------------------
 
-  - Add new Irccd.Util.cut function (#635),
-  - Add new irccdctl commands to edit rules (#641),
-  - Plugin plugin: add options max-list-lines, max-list-columns (#618),
-  - Import Duktape 2.1.0 (#648),
-  - Fix identity.ctcp-version option (#690).
+- Add new Irccd.Util.cut function (#635),
+- Add new irccdctl commands to edit rules (#641),
+- Plugin plugin: add options max-list-lines, max-list-columns (#618),
+- Import Duktape 2.1.0 (#648),
+- Fix identity.ctcp-version option (#690).
 
 irccd 2.1.3 2017-07-28
 ----------------------
 
-  - Rules are now case insensitive (#645),
-  - Plugin hangman, history and logger are now case insensitive (#642),
-  - Plugin hangman: fix successive word selection (#644).
+- Rules are now case insensitive (#645),
+- Plugin hangman, history and logger are now case insensitive (#642),
+- Plugin hangman: fix successive word selection (#644).
 
 irccd 2.1.2 2017-06-02
 ----------------------
 
-  - Fix SSL initialization error in libircclient (#653),
-  - Fix various SSL warnings (#652),
-  - Fix build on Linux with musl (#649),
-  - Fix case sensitivity in hangman and roulette (#642).
+- Fix SSL initialization error in libircclient (#653),
+- Fix various SSL warnings (#652),
+- Fix build on Linux with musl (#649),
+- Fix case sensitivity in hangman and roulette (#642).
 
 irccd 2.1.1 2017-03-07
 ----------------------
 
-  - Fix invalid documented option transport.family,
-  - Fix error when logs.type is set to console,
-  - Fix invalid IPV6_V6ONLY option in transports.
+- Fix invalid documented option transport.family,
+- Fix error when logs.type is set to console,
+- Fix invalid IPV6\_V6ONLY option in transports.
 
 irccd 2.1.0 2017-02-01
 ----------------------
 
 Irccd:
 
-  - Add SSL support in transports,
-  - Add authentication support in transports,
-  - Fix a warning about daemon on macOS.
+- Add SSL support in transports,
+- Add authentication support in transports,
+- Fix a warning about daemon on macOS.
 
 Javascript API:
 
-  - New Irccd.File.lines function,
-  - Various improvements in Irccd.File API.
+- New Irccd.File.lines function,
+- Various improvements in Irccd.File API.
 
 Plugins:
 
-  - Add new format section for plugins,
-  - Add unit tests for plugins.
+- Add new format section for plugins,
+- Add unit tests for plugins.
 
 Irccdctl:
 
-  - Added brand new plugin-config command,
-  - Added aliases,
-  - Added unit tests for irccdctl commands.
+- Added brand new plugin-config command,
+- Added aliases,
+- Added unit tests for irccdctl commands.
 
 Libraries:
 
-  - Replaced jansson with Niels Lohmann's JSON library,
-  - Updated Duktape to 1.5.1.
+- Replaced jansson with Niels Lohmann's JSON library,
+- Updated Duktape to 1.5.1.
 
 Misc:
 
-  - Patterns can now use shell escape sequences,
-  - Added .editorconfig file,
-  - Split documentation into topics,
-  - The code is now split into several individual libraries.
+- Patterns can now use shell escape sequences,
+- Added .editorconfig file,
+- Split documentation into topics,
+- The code is now split into several individual libraries.
 
 Windows:
 
-  - Get rid of QtIFW and uses NSIS, WIX on Windows,
-  - Installer have components,
-  - Copy DLL files automatically into fakeroot and install,
-  - Added better support for cross-compiling using MinGW.
+- Get rid of QtIFW and uses NSIS, WIX on Windows,
+- Installer have components,
+- Copy DLL files automatically into fakeroot and install,
+- Added better support for cross-compiling using MinGW.
 
 irccd 2.0.3 2016-11-01
 ----------------------
 
-  - Fix various errors in logger plugin,
-  - Fix quakenet support in auth plugin.
+- Fix various errors in logger plugin,
+- Fix quakenet support in auth plugin.
 
 irccd 2.0.2 2016-04-19
 ----------------------
 
-  - Fix CMake error preventing installation of irccd and irccdctl.
+- Fix CMake error preventing installation of irccd and irccdctl.
 
 irccd 2.0.1 2016-03-13
 ----------------------
 
-  - Plugin plugin: fix invalid usage.
+- Plugin plugin: fix invalid usage.
 
 irccd 2.0.0 2016-03-01
 ----------------------
 
-  - Initial 2.0.0 release.
+- Initial 2.0.0 release.
--- a/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -55,7 +55,7 @@
 
 # Helper to set global internal variables.
 function(setg var value)
-    set("${var}" "${value}" CACHE INTERNAL "")
+	set("${var}" "${value}" CACHE INTERNAL "")
 endfunction ()
 
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${irccd_SOURCE_DIR}/cmake/packages)
@@ -93,7 +93,7 @@
 add_subdirectory(libirccd-test)
 
 if (IRCCD_HAVE_JS)
-    add_subdirectory(libirccd-js)
+	add_subdirectory(libirccd-js)
 endif ()
 
 add_subdirectory(irccd)
@@ -102,60 +102,60 @@
 add_subdirectory(systemd)
 
 if (IRCCD_HAVE_JS)
-    add_subdirectory(plugins)
+	add_subdirectory(plugins)
 endif ()
 
 # Platform specific.
 if (WIN32)
-    add_subdirectory(win32)
+	add_subdirectory(win32)
 endif ()
 
 # Tests.
 if (IRCCD_WITH_TESTS)
-    include(CTest)
-    add_subdirectory(tests)
+	include(CTest)
+	add_subdirectory(tests)
 endif ()
 
 add_subdirectory(cmake/export)
 
 message("Compiling with the following flags:")
-message("    General flags:    ${CMAKE_CXX_FLAGS}")
-message("    Debug flags:      ${CMAKE_CXX_FLAGS_DEBUG}")
-message("    Release flags:    ${CMAKE_CXX_FLAGS_RELEASE}")
+message("       General flags:  ${CMAKE_CXX_FLAGS}")
+message("       Debug flags:    ${CMAKE_CXX_FLAGS_DEBUG}")
+message("       Release flags:  ${CMAKE_CXX_FLAGS_RELEASE}")
 message("")
 
 message("Compiling irccd with following options:")
-message("    Libedit:          ${IRCCD_WITH_LIBEDIT_MSG}")
-message("    OpenSSL:          ${IRCCD_WITH_SSL_MSG}")
-message("    Javascript:       ${IRCCD_WITH_JS_MSG}")
-message("    Tests:            ${IRCCD_WITH_TESTS_MSG}")
-message("    User docs:        ${IRCCD_WITH_HTML_MSG}")
-message("    Doxygen:          ${IRCCD_WITH_DOXYGEN_MSG}")
-message("    Package:          ${IRCCD_PACKAGE_MSG}")
-message("    Vera:             ${IRCCD_WITH_VERA_MSG}")
+message("       Libedit:        ${IRCCD_WITH_LIBEDIT_MSG}")
+message("       OpenSSL:        ${IRCCD_WITH_SSL_MSG}")
+message("       Javascript:     ${IRCCD_WITH_JS_MSG}")
+message("       Tests:          ${IRCCD_WITH_TESTS_MSG}")
+message("       User docs:      ${IRCCD_WITH_HTML_MSG}")
+message("       Doxygen:        ${IRCCD_WITH_DOXYGEN_MSG}")
+message("       Package:        ${IRCCD_PACKAGE_MSG}")
+message("       Vera:           ${IRCCD_WITH_VERA_MSG}")
 message("")
 
 message("Installing plugins:")
 foreach (plugin ${IRCCD_PLUGINS})
-    string(TOUPPER ${plugin} name)
-    irccd_indent_message("    ${plugin}: " "${IRCCD_WITH_PLUGIN_${name}_MSG}" 22)
+	string(TOUPPER ${plugin} name)
+	irccd_indent_message("       ${plugin}: " "${IRCCD_WITH_PLUGIN_${name}_MSG}" 22)
 endforeach ()
 message("")
 
 if (WIN32)
-    message("Installing these DLLs:")
-    foreach (name ${IRCCD_DLLS})
-        irccd_indent_message("    ${name}: " "${${name}}" 30)
-    endforeach ()
-    message("")
+	message("Installing these DLLs:")
+	foreach (name ${IRCCD_DLLS})
+		irccd_indent_message("       ${name}: " "${${name}}" 30)
+	endforeach ()
+	message("")
 
-    if (IRCCD_DLLS_NOT_FOUND)
-        message("The following DLLs were not found:")
-        foreach (name ${IRCCD_DLLS_NOT_FOUND})
-            message("    ${name}")
-        endforeach ()
-        message("")
-    endif ()
+	if (IRCCD_DLLS_NOT_FOUND)
+		message("The following DLLs were not found:")
+		foreach (name ${IRCCD_DLLS_NOT_FOUND})
+			message("       ${name}")
+		endforeach ()
+		message("")
+	endif ()
 endif ()
 
 include(cmake/IrccdPackage.cmake)
@@ -163,13 +163,13 @@
 
 # Metadata files
 add_custom_target(
-    metadata
-    SOURCES
-        ${CMAKE_SOURCE_DIR}/CHANGES.md
-        ${CMAKE_SOURCE_DIR}/CONTRIBUTE.md
-        ${CMAKE_SOURCE_DIR}/CREDITS.md
-        ${CMAKE_SOURCE_DIR}/INSTALL.md
-        ${CMAKE_SOURCE_DIR}/MIGRATING.md
-        ${CMAKE_SOURCE_DIR}/README.md
-        ${CMAKE_SOURCE_DIR}/STYLE.md
+	metadata
+	SOURCES
+		${CMAKE_SOURCE_DIR}/CHANGES.md
+		${CMAKE_SOURCE_DIR}/CONTRIBUTE.md
+		${CMAKE_SOURCE_DIR}/CREDITS.md
+		${CMAKE_SOURCE_DIR}/INSTALL.md
+		${CMAKE_SOURCE_DIR}/MIGRATING.md
+		${CMAKE_SOURCE_DIR}/README.md
+		${CMAKE_SOURCE_DIR}/STYLE.md
 )
--- a/CONTRIBUTE.md	Wed Oct 24 13:24:03 2018 +0200
+++ b/CONTRIBUTE.md	Fri Oct 26 13:01:00 2018 +0200
@@ -1,14 +1,14 @@
 IRC Client Daemon CONTRIBUTING GUIDE
 ====================================
 
-Read this guide if you want to contribute to irccd. The purpose of this document
-is to describe the steps to submit a patch.
+Read this guide if you want to contribute to irccd. The purpose of this
+document is to describe the steps to submit a patch.
 
 You may submit a patch when:
 
-  - You want to fix a bug / typo,
-  - You want to add a new feature,
-  - You want to change something.
+- You want to fix a bug / typo,
+- You want to add a new feature,
+- You want to change something.
 
 There a lot of steps before submitting a patch. First, be sure to respect the
 style defined in the STYLE.md file. We never accept patches that do not match
@@ -17,20 +17,90 @@
 Subscribe to the mailing list
 -----------------------------
 
-Discussion and patches are sent to the *irccd (at) malikania (dot) fr* mailing
-list. You need to subscribe by dropping a mail to
-*irccd+subscribe (at) malikania (dot) fr* first.
+Discussion and patches are sent to the *irccd@malikania.fr* mailing list.
+You need to subscribe by dropping a mail to
+*irccd+subscribe@malikania.fr* first.
+
+Enable patchbomb extension
+--------------------------
+
+While this step is optional, it brings the `hg email` command which makes most
+of your submission for you.
+
+To enable it, add the following into your .hgrc (you may also use the hgrc file
+from the repository in .hg/hgrc).
+
+    [extensions]
+    patchbomb =
+
+Then, you need to specify a mail server, if you want to use smtp, you can use
+something like this:
+
+    [email]
+    from = Your Name <youraddress@yourdomain.tld>
+    to = irccd@malikania.fr
+
+    [smtp]
+    host = yourdomain.tld
+    port = 587
+    tls = starttls
+    username = your_account
+    password = your_password
+
+Note: the password is optional, if not set it will be asked each time you run
+the `hg email command`.
+
+More options are available, see:
+
+- `hg help hgrc.email`,
+- `hg help hgrc.smtp`,
+- `hg help patchbomb`
+- `hg help email`
+
+### Note to GMail users
+
+By default, your GMail account may use 2-steps authentication which causes
+troubles with the `hg email` command, you must create a specific application
+password.
+
+1. Go to https://security.google.com/settings/security/apppasswords
+2. Create an application password, it will be auto generated,
+3. Use this password or store it directly in the `smtp.password` option.
+
+Use the following settings:
+
+    [smtp]
+    host = gmail.com
+    port = 587
+    tls = starttls
+    username = your_account@gmail.com
+    password = the_generated_application_password
 
 Create your patch
 -----------------
 
-Usually, when you create a patch, you should have your own copy of irccd in your
-directory.
+Usually, when you create a patch, you should have your own copy of irccd
+in your directory.
+
+The following steps assumes that you have already cloned the irccd
+repository somewhere.
+
+Note: the recommended way is to create one unique revision.
+
+### Commit messages
 
-The following steps assumes that you have already cloned the irccd repository
-somewhere.
+Commit messages are written using the following syntax:
+
+    Topic: short message less than 80 characters
+
+    Optional additional description if needed.
 
-**Note**: the recommended way is to create one unique revision.
+Replace `Topic` with one of the following:
+
+- **CMake**: for the build system,
+- **Docs**: for the documentation,
+- **Misc**: for miscellaneous files,
+- **Tests**: for the unit tests.
 
 ### Quick way
 
@@ -79,12 +149,12 @@
     tag:         tip
     user:        François Jean <fj@gmail.com>
     date:        Thu Dec 08 16:08:40 2016 +0100
-    summary:     Irccdctl: do the same for irccdctl
+    summary:     Topic: some other changes
 
     changeset:   21:f27e577c5504
     user:        François Jean <fj@gmail.com>
     date:        Thu Dec 08 16:03:06 2016 +0100
-    summary:     Irccd: added initial support for multiple connections
+    summary:     Topic: some changes
 
     changeset:   20:777023816ff9
     bookmark:    @
@@ -127,13 +197,17 @@
 repository, you can remove the revisions you have commited or keep them.
 
 If you want to remove the revisions, you can use the `hg strip` command (from
-the strip extension.
+the strip extension).
 
-**Warning**: it will **remove** the revisions from history so use with care.
+Warning: it will **remove** the revisions from history so use with care.
 
     $ hg strip -r 21:22         # using the example above
     $ hg book -d feature-xyz    # delete the bookmark
 
+Newer versions of Mercurial support `-B` argument:
+
+    $ hg strip -B feature-xyz   # shortcut
+
 You can just go back on the @ bookmark as it's the safest choice.
 
     $ hg pull                   # fetch changesets
--- a/STYLE.md	Wed Oct 24 13:24:03 2018 +0200
+++ b/STYLE.md	Fri Oct 26 13:01:00 2018 +0200
@@ -1,5 +1,53 @@
-irccd CODING STYLE
-==================
+IRC Client Daemon CODING STYLE
+==============================
+
+File content
+============
+
+- Use UTF-8 charset,
+- Use Unix line endings,
+- Never write two blank consecutives blank lines.
+
+Indent
+======
+
+Use tabs to indent and spaces for alignment. Tabs are meant and designed for
+indenting code and have the advantage of being configurable. On the other hand
+to keep code clean, you must align content with spaces only *within* a line.
+
+Note: we recommend 8 columns to avoid high number of indentations.
+
+Example (show whitespace in your editor)
+
+```cpp
+class foo {
+public:
+	enum type {
+		dummy_value,            // dummy comment
+		other_value             // other comment
+	};
+
+	void long_function_name(very_long_type x1,
+	                        very_long_type x2)
+	{
+		const map<string, string> m{
+			{ "hostname",   "127.0.0.1"     },
+			{ "port",       "6667"          }
+		};
+	}
+};
+```
+
+As a rule of thumb, tabs must always be all length.
+
+Example of incorrect usage:
+
+```cpp
+	{ "hostname",	"127.0.0.1"	},
+	{ "port",	"6667"		}
+```
+
+This example will not align correctly if tabstops are not set to 8.
 
 C++
 ===
@@ -7,46 +55,46 @@
 Style
 -----
 
-  - Always use 4 spaces as indentation,
-  - Use UTF-8 charset,
-  - Use Unix line endings,
-  - Do not exceed 120 characters for lines of code,
-  - Do not exceed 80 characters for comments,
-  - Never write two blank consecutives blank lines,
-  - Do not use bad words.
+- Do not exceed 120 columns for lines of code,
+- Do not exceed 80 columns for comments,
 
 ### Braces
 
 Braces follow the K&R style, they are never placed on their own lines except for
 function definitions.
 
-Do not put braces for single line statements except for clarity.
-
-    if (condition) {
-        apply();
-        add();
-    } else
-        ok();
+Do not put braces for single line statements.
 
-    if (condition)
-        validate();
+```cpp
+if (condition) {
+	apply();
+	add();
+} else
+	ok();
 
-    if (foo) {
-        state = long + conditional + that + requires + several + lines +
-            to + complete;
-    }
+if (condition)
+	validate();
+
+if (foo)
+	state = long + conditional + that + requires + several + lines +
+	        to + complete;
+```
 
 Functions require braces on their own lines.
 
-    void function()
-    {
-    }
+```cpp
+void function()
+{
+}
+```
 
 And a lambda has its braces on the same lines too:
 
-    sort([&] (auto&) {
-        return true;
-    });
+```cpp
+sort([&] (auto&) {
+	return true;
+});
+```
 
 ### Spaces
 
@@ -55,60 +103,76 @@
 
 Normal function calls do not require it.
 
-    if (foo)
-        destroy(sizeof (int));
+```cpp
+if (foo)
+	destroy(sizeof (int));
+```
 
 ### References and pointers
 
 References and pointers are always next to the type name and not the variable.
 
-    T& get(const std::string& name);
+```cpp
+auto get(const std::string& name) -> T&;
+
+int* p = &x;
+```
+
+### Trailing return syntax
 
-    int* p = &x;
+We use trailing return syntax everywhere, it has the following benefits:
+
+- Inner types don't need to be prefixed by class name,
+- Functions are kept aligned correctly, focusing on the function name.
+
+```cpp
+auto func() -> std::string;
+```
 
 ### Naming
 
-  - English names,
-  - Member variables have trailing underscore (e.g foo\_bar\_),
-  - No hungarian notation.
+- English names,
+- Member variables have trailing underscore (e.g foo\_bar\_),
+- No hungarian notation.
 
 Everything is in `underscore_case` except template parameters and macros.
 
-    #if defined(FOO)
-    #   include <foo.hpp>
-    #endif
+```cpp
+#if defined(FOO)
+#	include <foo.hpp>
+#endif
 
-    namespace baz {
+namespace baz {
 
-    class object {
-    private:
-        std::string name_;
+class object {
+private:
+	std::string name_;
 
-    public:
-        inline const std::string& name() const noexcept
-        {
-            return name_;
-        }
-    };
+public:
+	auto name() const noexcept -> const std::string&;
+};
 
-    template <typename Archive>
-    void open(const Archive& ar)
-    {
-        bool is_valid = false;
-    }
+template <typename Archive>
+void open(const Archive& ar)
+{
+	bool is_valid = false;
+}
 
-    } // !baz
+} // !baz
+```
 
 ### Header guards
 
 Do not use `#pragma once`.
 
-Header guards are usually named **PROJECT_COMPONENT_FILENAME_HPP**.
+Header guards are usually named `PROJECT_COMPONENT_FILENAME_HPP`.
 
-    #ifndef FOO_COMMON_UTIL_HPP
-    #define FOO_COMMON_UTIL_HPP
+```cpp
+#ifndef FOO_COMMON_UTIL_HPP
+#define FOO_COMMON_UTIL_HPP
 
-    #endif // !FOO_COMMON_UTIL_HPP
+#endif // !FOO_COMMON_UTIL_HPP
+```
 
 ### Enums
 
@@ -117,29 +181,33 @@
 
 Enum class are encouraged.
 
-    enum class color {
-        blue,
-        red,
-        green
-    };
+```cpp
+enum class color {
+	blue,
+	red,
+	green
+};
+```
 
 ### Switch
 
 In a switch case statement, you **must** not declare variables and not indent
 cases.
 
-    switch (variable) {
-    case foo:
-        do_some_stuff();
-        break;
-    default:
-        break;
-    }
+```cpp
+switch (variable) {
+case foo:
+	do_some_stuff();
+	break;
+default:
+	break;
+}
+```
 
 ### Files
 
-  - Use `.cpp` and `.hpp` as file extensions,
-  - Filenames are all lowercase.
+- Use `.cpp` and `.hpp` as file extensions,
+- Filenames are all lowercase.
 
 ### Comments
 
@@ -147,60 +215,51 @@
 like this. However any public function in the .hpp **must** be documented as
 doxygen without exception.
 
-    /*
-     * Multi line comments look like
-     * this.
-     */
+```cpp
+/*
+ * Multi line comments look like
+ * this.
+ */
 
-    // Short comment
+// Short comment
+```
 
 Use `#if 0` to comment blocks of code.
 
+```cpp
 #if 0
-    broken_stuff();
+	broken_stuff();
 #endif
+```
 
 ### Includes
 
 The includes should always come in the following order.
 
-  1. C++ headers
-  2. C header
-  3. Third party libraries
-  4. Application headers in ""
+1. C++ headers
+2. C header
+3. Third party libraries
+4. Application headers in ""
 
-    #include <cstring>
-    #include <cerrno>
-
-    #include <sys/stat.h>
-
-    #include <libircclient.h>
-
-    #include "foo.h"
+```cpp
+#include <cstring>
+#include <cerrno>
 
-**Note**: always use C++ headers for C equivalent, stdio.h -> cstdio, etc.
-
-### Commit messages
+#include <sys/stat.h>
 
-Commit messages are written using the following syntax:
-
-    Topic: short message less than 80 characters
+#include <libircclient.h>
 
-    Optional additional description if needed.
-
-Replace `Topic` with one of the following:
+#include "foo.h"
+```
 
-  - **CMake**: for the build system,
-  - **Docs**: for the documentation,
-  - **Misc**: for miscellaneous files,
-  - **Tests**: for the unit tests.
+Note: always use C++ headers for C equivalent, stdio.h -> cstdio, etc.
 
 Programming
 -----------
 
 ### C language
 
-Do not use old C stuff like `void *`, `srand/rand`, `printf` or anything that
+Do not use old C stuff like `void*`, `srand/rand`, `printf` or anything that
 can be rewritten in modern C++.
 
 ### RTTI
@@ -214,18 +273,22 @@
 non-const reference as output parameter is **discouraged** and should be avoided
 in many case because it does not allow chaining of expressions like:
 
-    std::cout << reverse(upper(clean("  hello world!  "))) << std::endl;
+```cpp
+std::cout << reverse(upper(clean("  hello world!  "))) << std::endl;
+```
 
 If your function is designed to return a modified value passed as argument, it
 is better to take it by value and modify it directly.
 
-    std::string clean(std::string input)
-    {
-        if (!input.empty() && input.back() == '\r')
-            input.pop_back();
+```cpp
+auto clean(std::string input) -> std::string
+{
+	if (!input.empty() && input.back() == '\r')
+		input.pop_back();
 
-        return input;
-    }
+	return input;
+}
+```
 
 Never pass primitive types as const value.
 
@@ -237,26 +300,30 @@
 For example, you may use `assert` to verify that the developer access the data
 between the bounds of an array:
 
-    T& operator[](unsigned index)
-    {
-        assert(index < length_);
+```cpp
+auto operator[](unsigned index) -> T&
+{
+	assert(index < length_);
 
-        return data_[index];
-    }
+	return data_[index];
+}
+```
 
 The `assert` macro is not meant to check that a function succeeded, this code
 must not be written that way:
 
-    assert(listen(10));
+```cpp
+assert(listen(10));
+```
 
 ### Exceptions
 
 You must use exceptions to indicate an error that was unexpected such as:
 
-  - Failing to open a file,
-  - I/O unexpected errors,
-  - Parsing errors,
-  - User errors.
+- Failing to open a file,
+- I/O unexpected errors,
+- Parsing errors,
+- User errors.
 
 You may use the C++ standard exceptions defined in the stdexcept header but if
 you need to carry more data within your exception, you should derive from
@@ -274,66 +341,89 @@
 
 Example:
 
-    namespace util {
+```cpp
+namespace util {
 
-    std::string clean(std::string input);
+auto clean(std::string input) -> std::string;
 
-    } // !util
+} // !util
+```
 
 ### Variables initialization
 
 Use parentheses to initialize non primitive types:
 
-    throw std::runtime_error("foo");
+```cpp
+throw std::runtime_error("foo");
 
-    my_class obj("bar");
+my_class obj("bar");
+```
 
 Use brace initialization when you want to use an initializer list, type
 elision:
 
-    std::vector<int> v{1, 2, 3};
+```cpp
+std::vector<int> v{1, 2, 3};
 
-    foo({1, 2});                    // type deduced
+foo({1, 2});					// type deduced
 
-    return { "true", false };       // std::pair returned
+return { "true", false };	   // std::pair returned
+```
 
 Use the assignment for primitive types:
 
-    int x = 123;
-    bool is_valid = true;
+```cpp
+int x = 123;
+bool is_valid = true;
+```
 
 ### Classes
 
 Classes are usually defined in the following order:
 
-  1. Public inner types (enums, classes),
-  2. Protected/private members
-  3. Public functions
+1. Public inner types (enums, classes),
+2. Protected/private members and functions
+3. Public static functions.
+3. Public member functions
+4. Public virtual functions.
 
-    class foo {
-    public:
-        enum class type {
-            a,
-            b
-        };
+```cpp
+class foo {
+public:
+	enum class type {
+		a,
+		b
+	};
 
-    private:
-        int member_{0};
+private:
+	int member_{0};
 
-    public:
-        void some_function();
-    };
+public:
+	void some_function();
+};
+```
 
 ### Structs
 
-Do not use C structs unless you have very good reason to do so. If you want to
-pack some data, just use `class` and make all fields public.
+Use structs for objects that only need to store public data and have no
+invariants. For example PODs and traits match this criteria:
+
+```cpp
+struct point {
+	int x{0};
+	int y{0};
+};
 
-    class point {
-    public:
-        int x{0};
-        int y{0};
-    };
+template <>
+struct info_traits<point> {
+	template <typename Archive>
+	static void serialize(Archive& ar, const point& point)
+	{
+		ar.write(point.x);
+		ar.write(point.y);
+	}
+};
+```
 
 ### Return
 
@@ -342,39 +432,284 @@
 
 This code is preferred:
 
-    if (a_condition_is_not_valid)
-        return nullptr;
-    if (an_other_condition)
-        return nullptr;
+```cpp
+if (a_condition_is_not_valid)
+	return nullptr;
+if (an_other_condition)
+	return nullptr;
 
-    auto x = std::make_shared<object>();
+auto x = std::make_shared<object>();
 
-    x->start();
-    x->save();
+x->start();
+x->save();
 
-    return x;
+return x;
+```
 
 Additional rules:
 
-  - Do never put parentheses between the returned value,
-  - Do not put a else branch after a return.
+- Do never put parentheses between the returned value,
+- Do not put a else branch after a return.
 
 ### Auto
 
 We encorage usage of `auto`, it reduces code maintainance as you don't need to
 change your code when your rename types.
 
-````cpp
+```cpp
 auto it = std::find_if(v.begin(), v.end(), [&] (const auto& obj) {
-    return obj.key() == "foo";
+	return obj.key() == "foo";
 });
 
 for (const auto& pair : a_map)
-    std::cout << pair.first << " = " << pair.second << std::endl;
-````
+	std::cout << pair.first << " = " << pair.second << std::endl;
+```
 
 But do not use `auto` to write code like in python, this is not acceptable:
 
-````cpp
-    auto o = my_object("foo");
-````
+```cpp
+auto o = my_object("foo");
+```
+
+### String views
+
+Use `std::string_view` each time you need a string that you will not own, this
+includes: temporary arguments, return values, compile time constants.
+
+```cpp
+const std::string_view version("1.0");
+
+void load(std::string_view id, std::string_view path)
+{
+	std::cout << "loading: " << id << " from path: " << path << std::endl;
+}
+```
+
+### Optional values
+
+Use `std::optional` to indicate a null value considered as valid. For example,
+searching a value that may not exist.
+
+```cpp
+auto find(std::string_view id) -> std::optional<int>
+{
+	if (auto it = foo.find(id); it != foo.end())
+		return it->second;
+
+	return std::nullopt;
+}
+```
+
+### Avoid definitions in headers
+
+Try to avoid as much as possible function definition in header file. It slow
+down compilation because the compiler has to parse the syntax over and over.
+It's even worse as you may need to recompile a lot of files when you change a
+header rather than a source file.
+
+CMake
+=====
+
+Style
+-----
+
+- Try to keep line shorter than 80 columns
+
+### Spaces
+
+Each programming keyword (e.g. `if`, `foreach`, `while`) requires a single space
+before its argument, otherwise write opening parenthese directly after.
+
+```cmake
+foreach (c ${COMPONENTS})
+	string(TOUPPER ${c} CMP)
+
+	if (${WITH_${CMP}})
+		add_executable(${c} ${c}.cpp)
+	endif ()
+endforeach ()
+```
+
+### Line breaks
+
+When CMake lines goes too long, you should indent arguments at the same level,
+it's also common to see named argument values indented even more.
+
+```cmake
+set(
+	FILES
+	${myapp_SOURCE_DIR}/main.cpp
+	${myapp_SOURCE_DIR}/foo.cpp
+	${myapp_SOURCE_DIR}/bar.cpp
+)
+
+command_with_lot_of_arguments(
+	TARGET foo
+	INSTALL On
+	SOURCES
+		${myapp_SOURCE_DIR}/main.cpp
+		${myapp_SOURCE_DIR}/foo.cpp
+		${myapp_SOURCE_DIR}/bar.cpp
+	COMMENT "Some comment"
+```
+
+Modern CMake
+------------
+
+CMake evolves over time, if you have read very old articles there is a chance
+that what you have read is actually deprecated and replaced by other features.
+The following list is a short summary of modern CMake features that you must
+use.
+
+### Imported targets
+
+When they are available, use imported targets rather than plain variables. They
+offer complete dependency tracking with options and include directories as well.
+
+```cmake
+find_package(Boost COMPONENTS system)
+target_link_libraries(main Boost::system)
+```
+
+### Generator expressions
+
+Use generator expressions when it make sense. For example you should use them
+for variables that are not used at generation time (e.g CMAKE\_BUILD\_TYPE).
+
+```cmake
+target_include_directories(
+	myapp
+		$<BUILD_INTERFACE:${myapp_SOURCE_DIR}>
+		$<INSTALL_INTERFACE:include>
+)
+```
+
+Warning: do never test against `CMAKE_BUILD_TYPE` in any CMakeLists.txt, IDEs
+         like Visual Studio will mismatch what you'll put in the conditions.
+
+### Avoid global scoping
+
+The following commands must be avoided as much as possible:
+
+- `link_directories`,
+- `link_libraries`,
+- `include_directories`,
+- `add_definitions`.
+
+They pollute the global namespace, all targets defined after these commands will
+be built against those settings. Instead, you should use the per-targets
+commands.
+
+```cmake
+target_include_directories(
+	mylib
+	PUBLIC
+		$<BUILD_INTERFACE:${mylib_SOURCE_DIR}>
+		$<INSTALL_INTERFACE:include>
+)
+target_link_libraries(mylib foo)
+```
+
+### Defining sources
+
+You MUST never use any kind of `file(GLOB)` commands to list sources for an
+executable. CMake is designed to be re-called by itself only when required,
+having such a construct will not let CMake be able to detect if you have
+added/removed files in your source directory. Instead, you MUST always specify
+all source by hands.
+
+```cmake
+set(
+	FILES
+	${myapp_SOURCE_DIR}/main.cpp
+	${myapp_SOURCE_DIR}/a.cpp
+	${myapp_SOURCE_DIR}/b.cpp
+)
+
+add_executable(myapp ${FILES})
+```
+
+Markdown
+========
+
+Headers
+-------
+
+For 1st and 2nd level headers, use `===` and `---` delimiters and underline the
+whole title. Otherwise use `###`.
+
+```markdown
+Top level title
+===============
+
+Sub title
+---------
+
+### Header 3
+
+#### Header 4
+
+##### Header 5
+
+###### Header 6
+```
+
+Lists
+-----
+
+Use hyphens for unordered lists for consistency, do not indent top level lists,
+then indent by two spaces each level
+
+```markdown
+- unordered list 1
+- unordered list 2
+  - sub unordered item
+
+1. unordered list 1
+2. unordered list 2
+  2.1. sub unordered item
+```
+
+Code blocks
+-----------
+
+You can use three backticks and the language specifier or just indent a block by
+for leading spaces if you don't need syntax.
+
+	```cpp
+	std::cout << "hello world" << std::endl;
+	```
+
+And without syntax:
+
+```markdown
+	This is simple code block.
+```
+
+Tables
+------
+
+Tables are supported and formatted as following:
+
+```markdown
+| header 1 | header 2 |
+|----------|----------|
+| item 1   | item 2   |
+```
+
+Alerts
+------
+
+It's possible to prefix a paragraph by one of the following topic, it renders a
+different block depending on the output format:
+
+- Note:
+- Warning:
+- Danger:
+
+Then, if the paragraph is too long, indent the text correctly.
+
+```markdown
+Note: this is an information block that is too long to fit between the limits so
+      it is split and indented.
+```
--- a/cmake/IrccdOptions.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/IrccdOptions.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -38,23 +38,23 @@
 
 # Manual pages on Windows are pretty useless.
 if (WIN32)
-    set(DEFAULT_MAN "No")
+	set(DEFAULT_MAN "No")
 else ()
-    set(DEFAULT_MAN "Yes")
+	set(DEFAULT_MAN "Yes")
 endif ()
 
 # Systemd unit file
 if (CMAKE_SYSTEM_NAME MATCHES "Linux")
-    set(DEFAULT_SYSTEMD "Yes")
+	set(DEFAULT_SYSTEMD "Yes")
 else ()
-    set(DEFAULT_SYSTEMD "No")
+	set(DEFAULT_SYSTEMD "No")
 endif ()
 
 # pkg-config is only relevant on UNIX or MinGW
 if (MINGW OR UNIX)
-    set(DEFAULT_PKGCONFIG "Yes")
+	set(DEFAULT_PKGCONFIG "Yes")
 else ()
-    set(DEFAULT_PKGCONFIG "No")
+	set(DEFAULT_PKGCONFIG "No")
 endif ()
 
 option(IRCCD_WITH_DOCS "Enable building of all documentation" On)
@@ -75,17 +75,17 @@
 #
 
 if (IRCCD_WITH_JS)
-    add_subdirectory(extern/duktape)
-    set(IRCCD_HAVE_JS On)
-    set(IRCCD_WITH_JS_MSG "Yes")
+	add_subdirectory(extern/duktape)
+	set(IRCCD_HAVE_JS On)
+	set(IRCCD_WITH_JS_MSG "Yes")
 else ()
-    set(IRCCD_WITH_JS_MSG "No")
+	set(IRCCD_WITH_JS_MSG "No")
 endif ()
 
 if (IRCCD_WITH_TESTS)
-    set(IRCCD_WITH_TESTS_MSG "Yes")
+	set(IRCCD_WITH_TESTS_MSG "Yes")
 else ()
-    set(IRCCD_WITH_TESTS_MSG "No")
+	set(IRCCD_WITH_TESTS_MSG "No")
 endif ()
 
 #
@@ -100,65 +100,65 @@
 find_package(Editline)
 
 if (NOT IRCCD_WITH_DOCS)
-    set(IRCCD_WITH_HTML FALSE)
-    set(IRCCD_WITH_DOXYGEN FALSE)
-    set(IRCCD_WITH_MAN FALSE)
+	set(IRCCD_WITH_HTML FALSE)
+	set(IRCCD_WITH_DOXYGEN FALSE)
+	set(IRCCD_WITH_MAN FALSE)
 endif ()
 
 if (IRCCD_WITH_LIBEDIT)
-    if (Editline_FOUND)
-        set(IRCCD_HAVE_LIBEDIT On)
-        set(IRCCD_WITH_LIBEDIT_MSG "Yes")
-    else ()
-        set(IRCCD_WITH_LIBEDIT_MSG "No (libedit not found)")
-    endif ()
+	if (Editline_FOUND)
+		set(IRCCD_HAVE_LIBEDIT On)
+		set(IRCCD_WITH_LIBEDIT_MSG "Yes")
+	else ()
+		set(IRCCD_WITH_LIBEDIT_MSG "No (libedit not found)")
+	endif ()
 else ()
-    set(IRCCD_WITH_LIBEDIT_MSG "No (disabled by user)")
+	set(IRCCD_WITH_LIBEDIT_MSG "No (disabled by user)")
 endif ()
 
 if (IRCCD_WITH_SSL)
-    if (OPENSSL_FOUND)
-        set(IRCCD_HAVE_SSL On)
-        set(IRCCD_WITH_SSL_MSG "Yes")
-    else ()
-        set(IRCCD_WITH_SSL_MSG "No (OpenSSL not found)")
-    endif ()
+	if (OPENSSL_FOUND)
+		set(IRCCD_HAVE_SSL On)
+		set(IRCCD_WITH_SSL_MSG "Yes")
+	else ()
+		set(IRCCD_WITH_SSL_MSG "No (OpenSSL not found)")
+	endif ()
 else()
-    set(IRCCD_WITH_SSL_MSG "No (disabled by user)")
+	set(IRCCD_WITH_SSL_MSG "No (disabled by user)")
 endif ()
 
 if (IRCCD_WITH_DOXYGEN)
-    if (DOXYGEN_FOUND)
-        set(IRCCD_HAVE_DOXYGEN On)
-        set(IRCCD_WITH_DOXYGEN_MSG "Yes")
-    else ()
-        set(IRCCD_WITH_DOXYGEN_MSG "No (doxygen not found)")
-    endif ()
+	if (DOXYGEN_FOUND)
+		set(IRCCD_HAVE_DOXYGEN On)
+		set(IRCCD_WITH_DOXYGEN_MSG "Yes")
+	else ()
+		set(IRCCD_WITH_DOXYGEN_MSG "No (doxygen not found)")
+	endif ()
 else ()
-    set(IRCCD_WITH_DOXYGEN_MSG "No (disabled by user)")
+	set(IRCCD_WITH_DOXYGEN_MSG "No (disabled by user)")
 endif ()
 
 if (IRCCD_WITH_HTML)
-    if (Pandoc_FOUND)
-        set(IRCCD_HAVE_HTML On)
-        set(IRCCD_WITH_HTML_MSG "Yes")
-    else ()
-        set(IRCCD_WITH_HTML_MSG "No (pandoc not found)")
-    endif ()
+	if (Pandoc_FOUND)
+		set(IRCCD_HAVE_HTML On)
+		set(IRCCD_WITH_HTML_MSG "Yes")
+	else ()
+		set(IRCCD_WITH_HTML_MSG "No (pandoc not found)")
+	endif ()
 else ()
-    set(IRCCD_WITH_HTML_MSG "No (disabled by user)")
+	set(IRCCD_WITH_HTML_MSG "No (disabled by user)")
 endif ()
 
 if (IRCCD_WITH_VERA)
-    if (TCL_FOUND)
-        add_subdirectory(extern/vera)
-        set(IRCCD_HAVE_VERA On)
-        set(IRCCD_WITH_VERA_MSG "Yes")
-    else ()
-        set(IRCCD_WITH_VERA_MSG "No (TCL not found)")
-    endif ()
+	if (TCL_FOUND)
+		add_subdirectory(extern/vera)
+		set(IRCCD_HAVE_VERA On)
+		set(IRCCD_WITH_VERA_MSG "Yes")
+	else ()
+		set(IRCCD_WITH_VERA_MSG "No (TCL not found)")
+	endif ()
 else ()
-    set(IRCCD_WITH_VERA_MSG "No (disabled by user)")
+	set(IRCCD_WITH_VERA_MSG "No (disabled by user)")
 endif ()
 
 #
@@ -171,18 +171,18 @@
 set(IRCCD_PACKAGE FALSE)
 
 if (NOT WITH_HTML)
-    set(IRCCD_PACKAGE_MSG "No (HTML documentation disabled)")
+	set(IRCCD_PACKAGE_MSG "No (HTML documentation disabled)")
 else ()
-    # Now check that a plugin has not been disabled.
-    set(IRCCD_PACKAGE TRUE)
-    set(IRCCD_PACKAGE_MSG "Yes")
+	# Now check that a plugin has not been disabled.
+	set(IRCCD_PACKAGE TRUE)
+	set(IRCCD_PACKAGE_MSG "Yes")
 
-    foreach (plugin ${IRCCD_PLUGINS})
-        string(TOUPPER ${plugin} optname)
+	foreach (plugin ${IRCCD_PLUGINS})
+		string(TOUPPER ${plugin} optname)
 
-        if (NOT IRCCD_WITH_PLUGIN_${optname})
-            set(IRCCD_PACKAGE FALSE)
-            set(IRCCD_PACKAGE_MSG "No (Plugin ${plugin} disabled)")
-        endif ()
-    endforeach ()
+		if (NOT IRCCD_WITH_PLUGIN_${optname})
+			set(IRCCD_PACKAGE FALSE)
+			set(IRCCD_PACKAGE_MSG "No (Plugin ${plugin} disabled)")
+		endif ()
+	endforeach ()
 endif ()
--- a/cmake/IrccdPackage.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/IrccdPackage.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -43,11 +43,11 @@
 #
 
 if (WIN32)
-    set(CPACK_GENERATOR "NSIS")
+	set(CPACK_GENERATOR "NSIS")
 
-    if (IRCCD_64BITS)
-        set(CPACK_PACKAGE_FILE_NAME "irccd-${IRCCD_VERSION}-Windows-amd64")
-    else ()
-        set(CPACK_PACKAGE_FILE_NAME "irccd-${IRCCD_VERSION}-Windows-x86")
-    endif ()
+	if (IRCCD_64BITS)
+		set(CPACK_PACKAGE_FILE_NAME "irccd-${IRCCD_VERSION}-Windows-amd64")
+	else ()
+		set(CPACK_PACKAGE_FILE_NAME "irccd-${IRCCD_VERSION}-Windows-x86")
+	endif ()
 endif ()
--- a/cmake/IrccdSystem.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/IrccdSystem.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -27,49 +27,14 @@
 # -------------------------------------------------------------------
 #
 
-#
-# Recent versions of CMake has nice C++ feature detection for modern
-# C++ but they are still a bit buggy so we use this
-# instead.
-#
-if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
-    #
-    # For GCC, we require at least GCC 5.1
-    #
-    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.1")
-        message(FATAL_ERROR "You need at least GCC 5.1")
-    endif ()
-
-    set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++14 ${CMAKE_CXX_FLAGS}")
-elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-    #
-    # LLVM/clang implemented C++14 starting from version 3.4 but the
-    # switch -std=c++14 was not available.
-    #
-    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.4")
-        message(FATAL_ERROR "You need at least Clang 3.4")
-    endif ()
-
-    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "3.5")
-        set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++1y ${CMAKE_CXX_FLAGS}")
-    else ()
-        set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++14 ${CMAKE_CXX_FLAGS}")
-    endif ()
-elseif (MSVC14)
-    set(CMAKE_C_FLAGS "/DWIN32_LEAN_AND_MEAN /DNOMINMAX /wd4267 /wd4800 /D_CRT_SECURE_NO_WARNINGS ${CMAKE_C_FLAGS}")
-    set(CMAKE_CXX_FLAGS "/DWIN32_LEAN_AND_MEAN /DNOMINMAX /wd4267 /wd4800 /D_CRT_SECURE_NO_WARNINGS /EHsc ${CMAKE_CXX_FLAGS}")
-else ()
-    message(WARNING "Unsupported ${CMAKE_CXX_COMPILER_ID}, may not build correctly.")
-endif ()
-
 if (MINGW)
-    set(CMAKE_CXX_FLAGS "-D_WIN32_WINNT=0x0600 ${CMAKE_CXX_FLAGS}")
+	set(CMAKE_CXX_FLAGS "-D_WIN32_WINNT=0x0600 ${CMAKE_CXX_FLAGS}")
 endif ()
 
 if (CMAKE_SIZEOF_VOID_P MATCHES "8")
-    set(IRCCD_64BITS TRUE)
+	set(IRCCD_64BITS TRUE)
 else ()
-    set(IRCCD_64BITS FALSE)
+	set(IRCCD_64BITS FALSE)
 endif ()
 
 #
@@ -128,7 +93,7 @@
 check_function_exists(getlogin IRCCD_HAVE_GETLOGIN)
 
 if (NOT IRCCD_HAVE_UNISTD_H)
-    set(IRCCD_HAVE_GETLOGIN FALSE)
+	set(IRCCD_HAVE_GETLOGIN FALSE)
 endif ()
 
 # popen() function
@@ -149,7 +114,7 @@
 
 # If the sys/stat.h is not found, we disable stat(2)
 if (NOT IRCCD_HAVE_SYS_STAT_H OR NOT IRCCD_HAVE_SYS_TYPES_H)
-    set(IRCCD_HAVE_STAT FALSE)
+	set(IRCCD_HAVE_STAT FALSE)
 endif ()
 
 # syslog functions
@@ -163,7 +128,7 @@
 check_function_exists(closelog IRCCD_HAVE_CLOSELOG)
 
 if (NOT IRCCD_HAVE_SYSLOG_H OR NOT IRCCD_HAVE_OPENLOG OR NOT IRCCD_HAVE_CLOSELOG)
-    set(IRCCD_HAVE_SYSLOG FALSE)
+	set(IRCCD_HAVE_SYSLOG FALSE)
 endif ()
 
 # Check for struct stat fields.
@@ -185,16 +150,16 @@
 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/irccd)
 
 configure_file(
-    ${CMAKE_CURRENT_LIST_DIR}/internal/sysconfig.hpp.in
-    ${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
+	${CMAKE_CURRENT_LIST_DIR}/internal/sysconfig.hpp.in
+	${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
 )
 
 include_directories(
-    ${CMAKE_BINARY_DIR}
-    ${CMAKE_BINARY_DIR}/irccd
+	${CMAKE_BINARY_DIR}
+	${CMAKE_BINARY_DIR}/irccd
 )
 
 install(
-    FILES ${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
-    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/irccd
+	FILES ${CMAKE_BINARY_DIR}/irccd/sysconfig.hpp
+	DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/irccd
 )
--- a/cmake/IrccdVersion.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/IrccdVersion.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -20,11 +20,11 @@
 find_program(HG_EXECUTABLE hg)
 
 if (HG_EXECUTABLE)
-    execute_process(
-        COMMAND hg log -r . -T " ({rev}:{node|short})"
-        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
-        OUTPUT_VARIABLE HG_REV
-    )
+	execute_process(
+		COMMAND hg log -r . -T " ({rev}:{node|short})"
+		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+		OUTPUT_VARIABLE HG_REV
+	)
 endif ()
 
 # Irccd version.
--- a/cmake/check/PutTime.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/check/PutTime.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -22,15 +22,15 @@
 # std::put_time does not exists on Debian 8, probably too old libstdc++.
 #
 check_cxx_source_compiles(
-    "#include <iomanip>
-     #include <iostream>
+	"#include <iomanip>
+	 #include <iostream>
 
-     int main()
-     {
-        std::cout << std::put_time(nullptr, \"\");
+	 int main()
+	 {
+		std::cout << std::put_time(nullptr, \"\");
 
-        return 0;
-     }
-    "
-    IRCCD_HAVE_STD_PUT_TIME
+		return 0;
+	 }
+	"
+	IRCCD_HAVE_STD_PUT_TIME
 )
--- a/cmake/export/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/export/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -20,45 +20,45 @@
 
 # CMake export files.
 write_basic_package_version_file(
-    ${CMAKE_CURRENT_BINARY_DIR}/irccd-config-version.cmake
-    VERSION ${IRCCD_VERSION}
-    COMPATIBILITY SameMajorVersion
+	${CMAKE_CURRENT_BINARY_DIR}/irccd-config-version.cmake
+	VERSION ${IRCCD_VERSION}
+	COMPATIBILITY SameMajorVersion
 )
 
 install(
-    EXPORT irccd-targets
-    FILE irccd-targets.cmake
-    NAMESPACE irccd::
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/irccd
+	EXPORT irccd-targets
+	FILE irccd-targets.cmake
+	NAMESPACE irccd::
+	DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/irccd
 )
 
 install(
-    FILES
-        ${CMAKE_CURRENT_SOURCE_DIR}/irccd-config.cmake
-        ${CMAKE_CURRENT_BINARY_DIR}/irccd-config-version.cmake
-    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/irccd
-    COMPONENT Devel
+	FILES
+		${CMAKE_CURRENT_SOURCE_DIR}/irccd-config.cmake
+		${CMAKE_CURRENT_BINARY_DIR}/irccd-config-version.cmake
+	DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/irccd
+	COMPONENT Devel
 )
 
 # pkg-config files.
 if (IRCCD_WITH_PKGCONFIG)
-    # Since javascript is optional, add it only if required.
-    if (IRCCD_HAVE_JS)
-        set(IRCCD_EXTRA_REQUIRES libirccd-js)
-    endif ()
-    if (IRCCD_HAVE_SSL)
-        set(IRCCD_EXTRA_LIBS "-lssl -lcrypto")
-    endif ()
+	# Since javascript is optional, add it only if required.
+	if (IRCCD_HAVE_JS)
+		set(IRCCD_EXTRA_REQUIRES libirccd-js)
+	endif ()
+	if (IRCCD_HAVE_SSL)
+		set(IRCCD_EXTRA_LIBS "-lssl -lcrypto")
+	endif ()
 
-    foreach (pkg libirccd-core libirccd libirccd-ctl libirccd-js libirccd-test)
-        configure_file(
-            ${CMAKE_CURRENT_SOURCE_DIR}/${pkg}.pc
-            ${CMAKE_CURRENT_BINARY_DIR}/${pkg}.pc
-            @ONLY
-        )
-        install(
-            FILES ${CMAKE_CURRENT_BINARY_DIR}/${pkg}.pc
-            DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
-        )
-    endforeach ()
+	foreach (pkg libirccd-core libirccd libirccd-ctl libirccd-js libirccd-test)
+		configure_file(
+			${CMAKE_CURRENT_SOURCE_DIR}/${pkg}.pc
+			${CMAKE_CURRENT_BINARY_DIR}/${pkg}.pc
+			@ONLY
+		)
+		install(
+			FILES ${CMAKE_CURRENT_BINARY_DIR}/${pkg}.pc
+			DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
+		)
+	endforeach ()
 endif ()
--- a/cmake/function/IrccdBuildHtml.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdBuildHtml.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -23,10 +23,10 @@
 # ----------------
 #
 # irccd_build_html(
-#   COMPONENT (Optional) install the output documentation as the given component
-#   OUTPUT (Optional) override output path
-#   OUTPUT_VAR (Optional) store the output file in the output variable
-#   SOURCE the source markdown file
+#   COMPONENT           (Optional) install the output documentation as the given component
+#   OUTPUT              (Optional) override output path
+#   OUTPUT_VAR          (Optional) store the output file in the output variable
+#   SOURCE              the source markdown file
 # )
 #
 # Create a rule to build the markdown file specified by SOURCE parameter.
@@ -48,7 +48,6 @@
 #   OUTPUT dev/howto-create-a-plugin
 #   SOURCE myfile.md
 #   OUTPUT_VAR output
-#   VARIABLES ... (Optional) variables to pass to pandoc
 # )
 #
 # add_custom_target(mytarget DEPENDS ${output})
@@ -57,83 +56,83 @@
 #
 
 macro(irccd_build_html)
-    set(oneValueArgs COMPONENT OUTPUT OUTPUT_VAR SOURCE)
-    set(multiValueArgs VARIABLES)
+	set(oneValueArgs COMPONENT OUTPUT OUTPUT_VAR SOURCE)
+	set(multiValueArgs VARIABLES)
 
-    cmake_parse_arguments(HTML "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+	cmake_parse_arguments(HTML "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT HTML_SOURCE)
-        message(FATAL_ERROR "Missing SOURCE parameter")
-    endif ()
+	if (NOT HTML_SOURCE)
+		message(FATAL_ERROR "Missing SOURCE parameter")
+	endif ()
 
-    #
-    # Example with SOURCES set to CMAKE_CURRENT_SOURCE_DIR/api/event/onMessage.md
-    #
-    # Extract the following variables:
-    #
-    # dirname:      api/event
-    # basename:     onMessage
-    # baseurl:      ../../
-    #
-    if (HTML_OUTPUT)
-        if (IS_ABSOLUTE ${HTML_OUTPUT})
-            message(FATAL_ERROR "OUTPUT variable must not be absolute")
-        endif ()
+	#
+	# Example with SOURCES set to CMAKE_CURRENT_SOURCE_DIR/api/event/onMessage.md
+	#
+	# Extract the following variables:
+	#
+	# dirname:	  api/event
+	# basename:	 onMessage
+	# baseurl:	  ../../
+	#
+	if (HTML_OUTPUT)
+		if (IS_ABSOLUTE ${HTML_OUTPUT})
+			message(FATAL_ERROR "OUTPUT variable must not be absolute")
+		endif ()
 
-        get_filename_component(dirname ${HTML_OUTPUT} DIRECTORY)
-        get_filename_component(basename ${HTML_OUTPUT} NAME)
-    else()
-        get_filename_component(dirname ${HTML_SOURCE} DIRECTORY)
-        file(RELATIVE_PATH dirname ${CMAKE_CURRENT_SOURCE_DIR} ${dirname})
-        get_filename_component(basename ${HTML_SOURCE} NAME)
-    endif ()
+		get_filename_component(dirname ${HTML_OUTPUT} DIRECTORY)
+		get_filename_component(basename ${HTML_OUTPUT} NAME)
+	else()
+		get_filename_component(dirname ${HTML_SOURCE} DIRECTORY)
+		file(RELATIVE_PATH dirname ${CMAKE_CURRENT_SOURCE_DIR} ${dirname})
+		get_filename_component(basename ${HTML_SOURCE} NAME)
+	endif ()
 
-    # Remove extension from basename.
-    string(REGEX REPLACE "^(.*)\\.md$" "\\1" basename ${basename})
+	# Remove extension from basename.
+	string(REGEX REPLACE "^(.*)\\.md$" "\\1" basename ${basename})
 
-    file(
-        RELATIVE_PATH
-        baseurl
-        ${CMAKE_CURRENT_BINARY_DIR}/${dirname}
-        ${CMAKE_CURRENT_BINARY_DIR}/
-    )
+	file(
+		RELATIVE_PATH
+		baseurl
+		${CMAKE_CURRENT_BINARY_DIR}/${dirname}
+		${CMAKE_CURRENT_BINARY_DIR}/
+	)
 
-    if (baseurl STREQUAL "")
-        set(baseurl "./")
-    endif ()
+	if (baseurl STREQUAL "")
+		set(baseurl "./")
+	endif ()
 
-    # Replace CMake variables.
-    configure_file(
-        ${HTML_SOURCE}
-        ${doc_BINARY_DIR}/${dirname}/${basename}.md
-        @ONLY
-    )
+	# Replace CMake variables.
+	configure_file(
+		${HTML_SOURCE}
+		${doc_BINARY_DIR}/${dirname}/${basename}.md
+		@ONLY
+	)
 
-    set(input ${doc_BINARY_DIR}/${dirname}/${basename}.md)
-    set(output ${doc_BINARY_DIR}/html/${dirname}/${basename}.html)
+	set(input ${doc_BINARY_DIR}/${dirname}/${basename}.md)
+	set(output ${doc_BINARY_DIR}/html/${dirname}/${basename}.html)
 
-    # Pandoc the file.
-    pandoc(
-        OUTPUT ${output}
-        SOURCES ${input}
-        DEPENDS ${HTML_SOURCE} ${input}
-        TEMPLATE ${html_SOURCE_DIR}/template.html
-        VARIABLE baseurl:${baseurl} ${HTML_VARIABLES}
-        FROM markdown
-        TO html5
-        STANDALONE TOC MAKE_DIRECTORY
-    )
+	# Pandoc the file.
+	pandoc(
+		OUTPUT ${output}
+		SOURCES ${input}
+		DEPENDS ${HTML_SOURCE} ${input}
+		TEMPLATE ${html_SOURCE_DIR}/template.html
+		VARIABLE baseurl:${baseurl} ${HTML_VARIABLES}
+		FROM markdown
+		TO html5
+		STANDALONE TOC MAKE_DIRECTORY
+	)
 
-    # Install the documentation file as component if provided.
-    if (HTML_COMPONENT)
-        install(
-            FILES ${output}
-            COMPONENT ${HTML_COMPONENT}
-            DESTINATION ${CMAKE_INSTALL_DOCDIR}/${dirname}
-        )
-    endif ()
+	# Install the documentation file as component if provided.
+	if (HTML_COMPONENT)
+		install(
+			FILES ${output}
+			COMPONENT ${HTML_COMPONENT}
+			DESTINATION ${CMAKE_INSTALL_DOCDIR}/${dirname}
+		)
+	endif ()
 
-    if (HTML_OUTPUT_VAR)
-        set(${HTML_OUTPUT_VAR} ${output})
-    endif ()
+	if (HTML_OUTPUT_VAR)
+		set(${HTML_OUTPUT_VAR} ${output})
+	endif ()
 endmacro ()
--- a/cmake/function/IrccdDefineExecutable.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdDefineExecutable.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -21,13 +21,13 @@
 # -----------------------
 #
 # irccd_define_executable(
-#    TARGET target name
-#    EXPORT (Optional) export executable through CMake
-#    DESCRIPTION short description (Required if installed)
-#    SOURCES src1, src2, srcn
-#    FLAGS (Optional) C/C++ flags (without -D)
-#    LIBRARIES (Optional) libraries to link
-#    INCLUDES (Optional) includes for the target
+#   TARGET      target name
+#   EXPORT      (Optional) export executable through CMake
+#   DESCRIPTION short description (Required if installed)
+#   SOURCES     src1, src2, srcn
+#   FLAGS       (Optional) C/C++ flags (without -D)
+#   LIBRARIES   (Optional) libraries to link
+#   INCLUDES    (Optional) includes for the target
 # )
 #
 # Create an executable that can be installed or not.
@@ -36,56 +36,56 @@
 include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake)
 
 function(irccd_define_executable)
-    set(options EXPORT)
-    set(oneValueArgs DESCRIPTION TARGET)
-    set(multiValueArgs SOURCES FLAGS LIBRARIES INCLUDES OPTIONS)
+	set(options EXPORT)
+	set(oneValueArgs DESCRIPTION TARGET)
+	set(multiValueArgs SOURCES FLAGS LIBRARIES INCLUDES OPTIONS)
 
-    cmake_parse_arguments(EXE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+	cmake_parse_arguments(EXE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT EXE_TARGET)
-        message(FATAL_ERROR "Please set TARGET")
-    endif ()
-    if (NOT EXE_SOURCES)
-        message(FATAL_ERROR "Please set SOURCES")
-    endif ()
-    if (NOT EXE_DESCRIPTION)
-        message(FATAL_ERROR "DESCRIPTION required")
-    endif ()
+	if (NOT EXE_TARGET)
+		message(FATAL_ERROR "Please set TARGET")
+	endif ()
+	if (NOT EXE_SOURCES)
+		message(FATAL_ERROR "Please set SOURCES")
+	endif ()
+	if (NOT EXE_DESCRIPTION)
+		message(FATAL_ERROR "DESCRIPTION required")
+	endif ()
 
-    add_executable(${EXE_TARGET} ${EXE_SOURCES})
-    target_include_directories(${EXE_TARGET} PRIVATE ${EXE_INCLUDES})
-    target_compile_definitions(${EXE_TARGET} PRIVATE ${EXE_FLAGS})
-    target_compile_options(${EXE_TARGET} PRIVATE ${EXE_OPTIONS})
-    target_link_libraries(${EXE_TARGET} ${EXE_LIBRARIES})
+	add_executable(${EXE_TARGET} ${EXE_SOURCES})
+	target_include_directories(${EXE_TARGET} PRIVATE ${EXE_INCLUDES})
+	target_compile_definitions(${EXE_TARGET} PRIVATE ${EXE_FLAGS})
+	target_compile_options(${EXE_TARGET} PRIVATE ${EXE_OPTIONS})
+	target_link_libraries(${EXE_TARGET} ${EXE_LIBRARIES})
 
-    set_target_properties(
-        ${EXE_TARGET}
-        PROPERTIES
-            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-    )
-    foreach (c ${CMAKE_CONFIGURATION_TYPES})
-        string(TOUPPER ${c} cu)
-        set_target_properties(
-            ${EXE_TARGET}
-            PROPERTIES
-                RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
-        )
-    endforeach()
+	set_target_properties(
+		${EXE_TARGET}
+		PROPERTIES
+			RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+	)
+	foreach (c ${CMAKE_CONFIGURATION_TYPES})
+		string(TOUPPER ${c} cu)
+		set_target_properties(
+			${EXE_TARGET}
+			PROPERTIES
+				RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
+		)
+	endforeach()
 
-    if (EXE_EXPORT)
-        install(
-            TARGETS ${EXE_TARGET}
-            EXPORT irccd-targets
-            COMPONENT ${EXE_TARGET}
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-        )
-    endif ()
+	if (EXE_EXPORT)
+		install(
+			TARGETS ${EXE_TARGET}
+			EXPORT irccd-targets
+			COMPONENT ${EXE_TARGET}
+			RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+		)
+	endif ()
 
-    # Put the application into a cpack group.
-    string(TOUPPER ${EXE_TARGET} CMP)
-    setg(CPACK_COMPONENT_${CMP}_DISPLAY_NAME "${EXE_TARGET} executable")
-    setg(CPACK_COMPONENT_${CMP}_DESCRIPTION ${EXE_DESCRIPTION})
-    setg(CPACK_COMPONENT_${CMP}_GROUP "Applications")
+	# Put the application into a cpack group.
+	string(TOUPPER ${EXE_TARGET} CMP)
+	setg(CPACK_COMPONENT_${CMP}_DISPLAY_NAME "${EXE_TARGET} executable")
+	setg(CPACK_COMPONENT_${CMP}_DESCRIPTION ${EXE_DESCRIPTION})
+	setg(CPACK_COMPONENT_${CMP}_GROUP "Applications")
 
-    irccd_vera_check(${EXE_TARGET} "${EXE_SOURCES}")
+	irccd_vera_check(${EXE_TARGET} "${EXE_SOURCES}")
 endfunction()
--- a/cmake/function/IrccdDefineLibrary.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdDefineLibrary.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -21,83 +21,78 @@
 # --------------------
 #
 # irccd_define_library(
-#    TARGET target name
-#    EXPORT (Optional) set to true to export library through irccd
-#    EXTERN (Optional) set to true to mark library as external
-#    HEADERS (Optional) headers to install
-#    HEADERS_DIRECTORY (Optional) subdirectory where to install headers
-#    SOURCES src1, src2, srcn
-#    FLAGS (Optional) C/C++ flags (without -D)
-#    LIBRARIES (Optional) libraries to link
-#    LOCAL_INCLUDES (Optional) local includes for the target only
-#    PUBLIC_INCLUDES (Optional) includes to share with target dependencies
+#   TARGET              target name
+#   SOURCES             src1, src2, srcn
+#   EXPORT              (Optional) set to true to export library through irccd
+#   HEADERS             (Optional) headers to install
+#   HEADERS_DIRECTORY   (Optional) subdirectory where to install headers
+#   FLAGS               (Optional) C/C++ flags (without -D)
+#   LIBRARIES           (Optional) libraries to link
+#   LOCAL_INCLUDES      (Optional) local includes for the target only
+#   PUBLIC_INCLUDES     (Optional) includes to share with target dependencies
 # )
 #
 
 include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake)
 
 function(irccd_define_library)
-    set(options EXPORT)
-    set(oneValueArgs HEADERS_DIRECTORY TARGET)
-    set(multiValueArgs HEADERS SOURCES FLAGS LIBRARIES LOCAL_INCLUDES PUBLIC_INCLUDES)
+	set(options EXPORT)
+	set(oneValueArgs HEADERS_DIRECTORY TARGET)
+	set(multiValueArgs HEADERS SOURCES FLAGS LIBRARIES LOCAL_INCLUDES PUBLIC_INCLUDES)
 
-    cmake_parse_arguments(LIB "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+	cmake_parse_arguments(LIB "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT LIB_TARGET)
-        message(FATAL_ERROR "Please set TARGET")
-    endif ()
-    if (NOT LIB_SOURCES)
-        message(FATAL_ERROR "Please set SOURCES")
-    endif ()
+	if (NOT LIB_TARGET)
+		message(FATAL_ERROR "Please set TARGET")
+	endif ()
+	if (NOT LIB_SOURCES)
+		message(FATAL_ERROR "Please set SOURCES")
+	endif ()
 
-    add_library(${LIB_TARGET} ${LIB_SOURCES} ${LIB_HEADERS})
-    target_include_directories(${LIB_TARGET} PRIVATE ${LIB_LOCAL_INCLUDES} PUBLIC ${LIB_PUBLIC_INCLUDES})
-    target_compile_definitions(
-        ${LIB_TARGET}
-        PRIVATE
-            CMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}"
-            CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
-        PUBLIC
-            ${LIB_FLAGS}
-    )
-    target_link_libraries(${LIB_TARGET} ${LIB_LIBRARIES})
-    set_target_properties(
-        ${LIB_TARGET}
-        PROPERTIES
-            PREFIX ""
-            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-    )
-    foreach (c ${CMAKE_CONFIGURATION_TYPES})
-        string(TOUPPER ${c} cu)
-        set_target_properties(
-            ${LIB_TARGET}
-            PROPERTIES
-                RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
-        )
-    endforeach()
+	add_library(${LIB_TARGET} ${LIB_SOURCES} ${LIB_HEADERS})
+	target_include_directories(${LIB_TARGET} PRIVATE ${LIB_LOCAL_INCLUDES} PUBLIC ${LIB_PUBLIC_INCLUDES})
+	target_compile_definitions(
+		${LIB_TARGET}
+		PRIVATE
+			CMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}"
+			CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
+		PUBLIC
+			${LIB_FLAGS}
+	)
+	target_link_libraries(${LIB_TARGET} ${LIB_LIBRARIES})
+	set_target_properties(
+		${LIB_TARGET}
+		PROPERTIES
+			PREFIX ""
+			RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+	)
+	foreach (c ${CMAKE_CONFIGURATION_TYPES})
+		string(TOUPPER ${c} cu)
+		set_target_properties(
+			${LIB_TARGET}
+			PROPERTIES
+				RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
+		)
+	endforeach()
 
-    if (NOT ${LIB_EXTERN})
-        irccd_vera_check(${LIB_TARGET} "${LIB_SOURCES}")
-    endif ()
+	if (${LIB_EXPORT})
+		install(
+			TARGETS ${LIB_TARGET}
+			EXPORT irccd-targets
+			RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+			ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+			LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+		)
+	endif ()
 
-    if (${LIB_EXPORT})
-        install(
-            TARGETS ${LIB_TARGET}
-            EXPORT irccd-targets
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-            ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        )
-    endif ()
+	if (LIB_HEADERS)
+		if (NOT LIB_HEADERS_DIRECTORY)
+			message(FATAL_ERROR "HEADERS_DIRECTORY must be defined")
+		endif ()
 
-    if (LIB_HEADERS)
-        if (NOT LIB_HEADERS_DIRECTORY)
-            message(FATAL_ERROR "HEADERS_DIRECTORY must be defined")
-        endif ()
-
-        install(
-            FILES ${LIB_HEADERS}
-            DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${LIB_HEADERS_DIRECTORY}
-        )
-    endif ()
+		install(
+			FILES ${LIB_HEADERS}
+			DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${LIB_HEADERS_DIRECTORY}
+		)
+	endif ()
 endfunction()
--- a/cmake/function/IrccdDefineMan.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdDefineMan.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -23,17 +23,17 @@
 # irccd_define_man(file, man)
 #
 # Parameters:
-#    file       The file name to build
-#    man        The man section
+#   file        The file name to build
+#   man         The man section
 #
 # This function configure the manual and install it if IRCCD_WITH_MAN is set.
 #
 
 function(irccd_define_man file man)
-    if (IRCCD_WITH_MAN)
-        set(input ${doc_SOURCE_DIR}/man/${file}.in)
-        set(output ${CMAKE_CURRENT_BINARY_DIR}/${file})
-        configure_file(${input} ${output} @ONLY)
-        install(FILES ${output} DESTINATION ${CMAKE_INSTALL_MANDIR}/${man})
-    endif ()
+	if (IRCCD_WITH_MAN)
+		set(input ${doc_SOURCE_DIR}/man/${file}.in)
+		set(output ${CMAKE_CURRENT_BINARY_DIR}/${file})
+		configure_file(${input} ${output} @ONLY)
+		install(FILES ${output} DESTINATION ${CMAKE_INSTALL_MANDIR}/${man})
+	endif ()
 endfunction()
--- a/cmake/function/IrccdDefinePlugin.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdDefinePlugin.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -20,21 +20,26 @@
 # irccd_define_plugin
 # -------------------
 #
+# Synopsis for Javascript plugins.
+#
 # irccd_define_plugin(
-#   NAME canonical plugin name
-#   TYPE JS or NATIVE
-#   DOCS documentation files in markdown
-#
-#   Options for TYPE JS:
+#   NAME        canonical plugin name
+#   TYPE        JS
+#   DOCS        documentation files in markdown
+#   SCRIPT      absolute path to the Javascript file (ending with .js)
+# )
 #
-#   SCRIPT absolute path to the Javascript file (ending with .js)
-#
-#   Options for TYPE NATIVE:
+# Synopsis for native plugins.
 #
-#   SOURCES c++ source files
-#   LIBRARIES additional libraries
+# irccd_define_plugin(
+#   NAME        canonical plugin name
+#   TYPE        NATIVE
+#   DOCS        documentation files in markdown
+#   SOURCES     c++ source files
+#   LIBRARIES   additional libraries
+# )
 #
-# Create a Javascript or Native plugin.
+# Create a Javascript or native plugin.
 #
 # The NAME parameter identifies the plugin. The same name will be used for the
 # plugin filename.
@@ -52,102 +57,102 @@
 #
 
 function(_irccd_define_javascript_plugin)
-    if (NOT PLG_SCRIPT)
-        message(FATAL_ERROR "Missing SCRIPT parameter")
-    endif ()
+	if (NOT PLG_SCRIPT)
+		message(FATAL_ERROR "Missing SCRIPT parameter")
+	endif ()
 
-    get_filename_component(name ${PLG_SCRIPT} NAME)
+	get_filename_component(name ${PLG_SCRIPT} NAME)
 
-    configure_file(
-        ${PLG_SCRIPT}
-        ${CMAKE_CURRENT_BINARY_DIR}/${name}
-    )
+	configure_file(
+		${PLG_SCRIPT}
+		${CMAKE_CURRENT_BINARY_DIR}/${name}
+	)
 
-    install(
-        FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}
-        COMPONENT ${PLG_NAME}
-        DESTINATION ${CMAKE_INSTALL_LIBDIR}/irccd
-    )
+	install(
+		FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}
+		COMPONENT ${PLG_NAME}
+		DESTINATION ${CMAKE_INSTALL_LIBDIR}/irccd
+	)
 
-    add_custom_target(
-        plugin-${PLG_NAME}
-        ALL
-        DEPENDS ${PLG_OUTPUT_DOC}
-        SOURCES ${PLG_SCRIPT} ${PLG_DOCS}
-    )
+	add_custom_target(
+		plugin-${PLG_NAME}
+		ALL
+		DEPENDS ${PLG_OUTPUT_DOC}
+		SOURCES ${PLG_SCRIPT} ${PLG_DOCS}
+	)
 endfunction()
 
 function(_irccd_define_native_plugin)
-    if (NOT PLG_SOURCES)
-        message(FATAL_ERROR "Missing SOURCES parameter")
-    endif ()
+	if (NOT PLG_SOURCES)
+		message(FATAL_ERROR "Missing SOURCES parameter")
+	endif ()
 
-    add_library(plugin-${PLG_NAME} MODULE ${PLG_SOURCES} ${PLG_OUTPUT_DOC} ${PLG_DOCS})
-    target_link_libraries(plugin-${PLG_NAME} libirccd ${PLG_LIBRARIES})
+	add_library(plugin-${PLG_NAME} MODULE ${PLG_SOURCES} ${PLG_OUTPUT_DOC} ${PLG_DOCS})
+	target_link_libraries(plugin-${PLG_NAME} libirccd ${PLG_LIBRARIES})
 
-    # Change output name.
-    set_target_properties(
-        plugin-${PLG_NAME}
-        PROPERTIES
-            PREFIX ""
-            OUTPUT_NAME ${PLG_NAME}
-    )
-    foreach (cfg ${CMAKE_CONFIGURATION_TYPES})
-        string(TOUPPER ${cfg} CFG)
-        set_target_properties(
-            plugin-${PLG_NAME}
-            PROPERTIES
-                PREFIX ""
-                OUTPUT_NAME_${CFG} ${PLG_NAME}
-        )
-    endforeach ()
+	# Change output name.
+	set_target_properties(
+		plugin-${PLG_NAME}
+		PROPERTIES
+			PREFIX ""
+			OUTPUT_NAME ${PLG_NAME}
+	)
+	foreach (cfg ${CMAKE_CONFIGURATION_TYPES})
+		string(TOUPPER ${cfg} CFG)
+		set_target_properties(
+			plugin-${PLG_NAME}
+			PROPERTIES
+				PREFIX ""
+				OUTPUT_NAME_${CFG} ${PLG_NAME}
+		)
+	endforeach ()
 
-    install(
-        TARGETS plugin-${PLG_NAME}
-        COMPONENT ${PLG_NAME}
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/irccd
-    )
+	install(
+		TARGETS plugin-${PLG_NAME}
+		COMPONENT ${PLG_NAME}
+		LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/irccd
+	)
 endfunction()
 
 function(irccd_define_plugin)
-    set(options "")
-    set(oneValueArgs NAME DOCS TYPE SCRIPT)
-    set(multiValueArgs SOURCES LIBRARIES)
+	set(options "")
+	set(oneValueArgs NAME DOCS TYPE SCRIPT)
+	set(multiValueArgs SOURCES LIBRARIES)
 
-    cmake_parse_arguments(PLG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+	cmake_parse_arguments(PLG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT PLG_NAME)
-        message(FATAL_ERROR "Missing NAME parameter")
-    endif ()
+	if (NOT PLG_NAME)
+		message(FATAL_ERROR "Missing NAME parameter")
+	endif ()
 
-    string(TOUPPER ${PLG_NAME} PLG_UPPER_NAME)
-    option(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME} "Enable ${PLG_NAME} plugin" On)
+	string(TOUPPER ${PLG_NAME} PLG_UPPER_NAME)
+	option(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME} "Enable ${PLG_NAME} plugin" On)
 
-    if (NOT IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME})
-        setg(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME}_MSG "No (disabled by user)")
-    else ()
-        setg(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME}_MSG "Yes")
+	if (NOT IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME})
+		setg(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME}_MSG "No (disabled by user)")
+	else ()
+		setg(IRCCD_WITH_PLUGIN_${PLG_UPPER_NAME}_MSG "Yes")
 
-        # Optional documentation.
-        if (PLG_DOCS AND HAVE_HTML)
-            irccd_build_html(
-                SOURCE ${PLG_DOCS}
-                OUTPUT plugin/${PLG_NAME}
-                COMPONENT ${PLG_NAME}
-                OUTPUT_VAR PLG_OUTPUT_DOC
-            )
-        endif ()
+		# Optional documentation.
+		if (PLG_DOCS AND HAVE_HTML)
+			irccd_build_html(
+				SOURCE ${PLG_DOCS}
+				OUTPUT plugin/${PLG_NAME}
+				COMPONENT ${PLG_NAME}
+				OUTPUT_VAR PLG_OUTPUT_DOC
+			)
+		endif ()
 
-        if (PLG_TYPE MATCHES "JS")
-            _irccd_define_javascript_plugin()
-        elseif (PLG_TYPE MATCHES "NATIVE")
-            _irccd_define_native_plugin()
-        else ()
-            message(FATAL_ERROR "Invalid TYPE given, must be JS or NATIVE")
-        endif ()
+		if (PLG_TYPE MATCHES "JS")
+			_irccd_define_javascript_plugin()
+		elseif (PLG_TYPE MATCHES "NATIVE")
+			_irccd_define_native_plugin()
+		else ()
+			message(FATAL_ERROR "Invalid TYPE given, must be JS or NATIVE")
+		endif ()
 
-        # Component grouping in installer.
-        setg(CPACK_COMPONENT_${PLG_UPPER_NAME}_GROUP "Plugins")
-        setg(CPACK_COMPONENT_${PLG_UPPER_NAME}_DESCRIPTION "Install ${PLG_NAME} plugin.")
-    endif ()
+		# Component grouping in installer.
+		setg(CPACK_COMPONENT_${PLG_UPPER_NAME}_GROUP "Plugins")
+		setg(CPACK_COMPONENT_${PLG_UPPER_NAME}_DESCRIPTION "Install ${PLG_NAME} plugin.")
+	endif ()
 endfunction()
--- a/cmake/function/IrccdDefineTest.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdDefineTest.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -21,11 +21,11 @@
 # -----------------
 #
 # irccd_define_test(
-#    NAME the test name
-#    SOURCES the sources files
-#    LIBRARIES (Optional) libraries to link
-#    FLAGS (Optional) compilation flags
-#    DEPENDS (Optional) list of dependencies
+#   NAME        the test name
+#   SOURCES     the sources files
+#   LIBRARIES   (Optional) libraries to link
+#   FLAGS       (Optional) compilation flags
+#   DEPENDS     (Optional) list of dependencies
 # )
 #
 # Create a unit test named test-${NAME}
@@ -38,75 +38,75 @@
 include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake)
 
 function(irccd_define_test)
-    set(oneValueArgs NAME)
-    set(multiValueArgs DEPENDS SOURCES LIBRARIES FLAGS)
+	set(oneValueArgs NAME)
+	set(multiValueArgs DEPENDS SOURCES LIBRARIES FLAGS)
 
-    cmake_parse_arguments(TEST "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+	cmake_parse_arguments(TEST "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-    if (NOT TEST_NAME)
-        message(FATAL_ERROR "Please set NAME")
-    endif ()
-    if (NOT TEST_SOURCES)
-        message(FATAL_ERROR "Please set SOURCES")
-    endif ()
+	if (NOT TEST_NAME)
+		message(FATAL_ERROR "Please set NAME")
+	endif ()
+	if (NOT TEST_SOURCES)
+		message(FATAL_ERROR "Please set SOURCES")
+	endif ()
 
-    list(
-        APPEND
-        TEST_LIBRARIES
-            libirccd-test
-            ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
-    )
+	list(
+		APPEND
+		TEST_LIBRARIES
+			libirccd-test
+			${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
+	)
 
-    add_executable(test-${TEST_NAME} ${TEST_SOURCES})
+	add_executable(test-${TEST_NAME} ${TEST_SOURCES})
 
-    if (TEST_DEPENDS)
-        add_dependencies(test-${TEST_NAME} ${TEST_DEPENDS})
-    endif ()
+	if (TEST_DEPENDS)
+		add_dependencies(test-${TEST_NAME} ${TEST_DEPENDS})
+	endif ()
 
-    target_link_libraries(test-${TEST_NAME} ${TEST_LIBRARIES})
+	target_link_libraries(test-${TEST_NAME} ${TEST_LIBRARIES})
 
-    target_include_directories(
-        test-${TEST_NAME}
-        PRIVATE
-            ${irccd_SOURCE_DIR}
-    )
+	target_include_directories(
+		test-${TEST_NAME}
+		PRIVATE
+			${irccd_SOURCE_DIR}
+	)
 
-    target_compile_definitions(
-        test-${TEST_NAME}
-        PRIVATE
-            ${TEST_FLAGS}
-            BOOST_TEST_DYN_LINK
-            TESTS_SOURCE_DIR="${tests_SOURCE_DIR}"
-            TESTS_BINARY_DIR="${tests_SOURCE_DIR}"
-            CMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}"
-            CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
-            CMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}"
-            CMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
-    )
+	target_compile_definitions(
+		test-${TEST_NAME}
+		PRIVATE
+			${TEST_FLAGS}
+			BOOST_TEST_DYN_LINK
+			TESTS_SOURCE_DIR="${tests_SOURCE_DIR}"
+			TESTS_BINARY_DIR="${tests_SOURCE_DIR}"
+			CMAKE_BINARY_DIR="${CMAKE_BINARY_DIR}"
+			CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
+			CMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}"
+			CMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
+	)
 
-    # Tests are all in the same directory
-    set_target_properties(
-        test-${TEST_NAME}
-        PROPERTIES
-            PROJECT_LABEL ${TEST_NAME}
-            FOLDER test
-            RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
-    )
-    foreach (c ${CMAKE_CONFIGURATION_TYPES})
-        string(TOUPPER ${c} cu)
-        set_target_properties(
-            test-${TEST_NAME}
-            PROPERTIES
-                RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
-        )
-    endforeach()
+	# Tests are all in the same directory
+	set_target_properties(
+		test-${TEST_NAME}
+		PROPERTIES
+			PROJECT_LABEL ${TEST_NAME}
+			FOLDER test
+			RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+	)
+	foreach (c ${CMAKE_CONFIGURATION_TYPES})
+		string(TOUPPER ${c} cu)
+		set_target_properties(
+			test-${TEST_NAME}
+			PROPERTIES
+				RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c}
+		)
+	endforeach()
 
-    # And test
-    add_test(
-        NAME test-${TEST_NAME}
-        COMMAND test-${TEST_NAME}
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests
-    )
+	# And test
+	add_test(
+		NAME test-${TEST_NAME}
+		COMMAND test-${TEST_NAME}
+		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests
+	)
 
-    irccd_vera_check(test-${TEST_NAME} "${TEST_SOURCES}")
+	irccd_vera_check(test-${TEST_NAME} "${TEST_SOURCES}")
 endfunction()
--- a/cmake/function/IrccdIndentMessage.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdIndentMessage.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -35,12 +35,12 @@
 #
 
 function(irccd_indent_message var value padding)
-    string(LENGTH "${var}" length)
+	string(LENGTH "${var}" length)
 
-    while (${length} LESS ${padding})
-        math(EXPR length "${length} + 1")
-        set(space "${space} ")
-    endwhile ()
+	while (${length} LESS ${padding})
+		math(EXPR length "${length} + 1")
+		set(space "${space} ")
+	endwhile ()
 
-    message("${var}${space}${value}")
+	message("${var}${space}${value}")
 endfunction()
--- a/cmake/function/IrccdVeraCheck.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/function/IrccdVeraCheck.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -31,27 +31,27 @@
 #
 
 function(irccd_vera_check target sources)
-    if (IRCCD_HAVE_VERA)
-        set(valid ".cpp;.c;.hpp;.h")
+	if (IRCCD_HAVE_VERA)
+		set(valid ".cpp;.c;.hpp;.h")
 
-        # Cleanup non relevant files.
-        foreach (s ${sources})
-            get_filename_component(s ${s} ABSOLUTE)
-            get_filename_component(ext ${s} EXT)
+		# Cleanup non relevant files.
+		foreach (s ${sources})
+			get_filename_component(s ${s} ABSOLUTE)
+			get_filename_component(ext ${s} EXT)
 
-            foreach (e ${valid})
-                if (${ext} STREQUAL ${e})
-                    list(APPEND newsources ${s})
-                endif ()
-            endforeach ()
-        endforeach ()
+			foreach (e ${valid})
+				if (${ext} STREQUAL ${e})
+					list(APPEND newsources ${s})
+				endif ()
+			endforeach ()
+		endforeach ()
 
-        add_custom_command(
-            TARGET ${target}
-            COMMAND
-                $<TARGET_FILE:vera> -w --root ${CMAKE_SOURCE_DIR}/vera ${newsources}
-            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-            VERBATIM
-        )
-    endif ()
+		add_custom_command(
+			TARGET ${target}
+			COMMAND
+				$<TARGET_FILE:vera> -w --root ${CMAKE_SOURCE_DIR}/vera ${newsources}
+			WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+			VERBATIM
+		)
+	endif ()
 endfunction()
--- a/cmake/internal/Irccd2Config.cmake.in	Wed Oct 24 13:24:03 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-include("${CMAKE_CURRENT_LIST_DIR}/Irccd2Targets.cmake")
--- a/cmake/internal/irccd2.pc.in	Wed Oct 24 13:24:03 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-# pkg-config file for irccd @IRCCD_VERSION@
-prefix=@CMAKE_INSTALL_PREFIX@
-libdir=${prefix}/lib
-includedir=${prefix}/include
-
-Name: irccd
-Version: @IRCCD_VERSION@
-Description: IRC Client Daemon library
-URL: http://projects.malikania.fr/irccd
-Libs: -L${libdir} -lirccd2$<$<CONFIG:Debug>:d>
-Cflags: -I${includedir}
--- a/cmake/internal/sysconfig.hpp.in	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/internal/sysconfig.hpp.in	Fri Oct 26 13:01:00 2018 +0200
@@ -23,15 +23,15 @@
  * Fix annoying "Please include winsock2.h before windows.h"
  */
 #if defined(_WIN32)
-#   if !defined(WIN32_MEAN_AND_LEAN)
-#       define WIN32_MEAN_AND_LEAN
-#   endif
-#   if !defined(NOMINMAX)
-#       define NOMINMAX
-#   endif
+#	if !defined(WIN32_MEAN_AND_LEAN)
+#		define WIN32_MEAN_AND_LEAN
+#	endif
+#	if !defined(NOMINMAX)
+#		define NOMINMAX
+#	endif
 
-#   include <winsock2.h>
-#   include <windows.h>
+#	include <winsock2.h>
+#	include <windows.h>
 #endif
 
 namespace irccd {
@@ -41,23 +41,23 @@
  * ------------------------------------------------------------------
  */
 
-#define IRCCD_VERSION_MAJOR         @IRCCD_VERSION_MAJOR@
-#define IRCCD_VERSION_MINOR         @IRCCD_VERSION_MINOR@
-#define IRCCD_VERSION_PATCH         @IRCCD_VERSION_PATCH@
-#define IRCCD_VERSION_SHLIB         @IRCCD_VERSION_SHLIB@
-#define IRCCD_VERSION               "@IRCCD_VERSION@"
+#define IRCCD_VERSION_MAJOR             @IRCCD_VERSION_MAJOR@
+#define IRCCD_VERSION_MINOR             @IRCCD_VERSION_MINOR@
+#define IRCCD_VERSION_PATCH             @IRCCD_VERSION_PATCH@
+#define IRCCD_VERSION_SHLIB             @IRCCD_VERSION_SHLIB@
+#define IRCCD_VERSION                   "@IRCCD_VERSION@"
 
 /*
  * User definable options.
  * ------------------------------------------------------------------
  */
 
-#define IRCCD_INSTALL_PREFIX        "@CMAKE_INSTALL_PREFIX@"
-#define IRCCD_INSTALL_LOCALSTATEDIR "@CMAKE_INSTALL_LOCALSTATEDIR@"
-#define IRCCD_INSTALL_DATADIR       "@CMAKE_INSTALL_DATADIR@"
-#define IRCCD_INSTALL_BINDIR        "@CMAKE_INSTALL_BINDIR@"
-#define IRCCD_INSTALL_LIBDIR        "@CMAKE_INSTALL_LIBDIR@"
-#define IRCCD_INSTALL_SYSCONFDIR    "@CMAKE_INSTALL_SYSCONFDIR@"
+#define IRCCD_INSTALL_PREFIX            "@CMAKE_INSTALL_PREFIX@"
+#define IRCCD_INSTALL_LOCALSTATEDIR     "@CMAKE_INSTALL_LOCALSTATEDIR@"
+#define IRCCD_INSTALL_DATADIR           "@CMAKE_INSTALL_DATADIR@"
+#define IRCCD_INSTALL_BINDIR            "@CMAKE_INSTALL_BINDIR@"
+#define IRCCD_INSTALL_LIBDIR            "@CMAKE_INSTALL_LIBDIR@"
+#define IRCCD_INSTALL_SYSCONFDIR        "@CMAKE_INSTALL_SYSCONFDIR@"
 
 #cmakedefine IRCCD_HAVE_JS
 #cmakedefine IRCCD_HAVE_SSL
@@ -92,10 +92,10 @@
  * \brief Describe irccd version.
  */
 struct version {
-    const unsigned major{IRCCD_VERSION_MAJOR};  //!< major
-    const unsigned minor{IRCCD_VERSION_MINOR};  //!< minor
-    const unsigned patch{IRCCD_VERSION_PATCH};  //!< patch
-    const unsigned abi{IRCCD_VERSION_SHLIB};    //!< ABI compatibility
+	const unsigned major{IRCCD_VERSION_MAJOR};      //!< major
+	const unsigned minor{IRCCD_VERSION_MINOR};      //!< minor
+	const unsigned patch{IRCCD_VERSION_PATCH};      //!< patch
+	const unsigned abi{IRCCD_VERSION_SHLIB};        //!< ABI compatibility
 };
 
 } // !irccd
--- a/cmake/packages/FindEditline.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/packages/FindEditline.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -13,9 +13,9 @@
 include(FindPackageHandleStandardArgs)
 
 find_package_handle_standard_args(
-    Editline
-    FOUND_VAR Editline_FOUND
-    REQUIRED_VARS Editline_LIBRARY Editline_INCLUDE_DIR
+	Editline
+	FOUND_VAR Editline_FOUND
+	REQUIRED_VARS Editline_LIBRARY Editline_INCLUDE_DIR
 )
 
 set(Editline_LIBRARIES ${Editline_LIBRARY})
--- a/cmake/packages/FindPandoc.cmake	Wed Oct 24 13:24:03 2018 +0200
+++ b/cmake/packages/FindPandoc.cmake	Fri Oct 26 13:01:00 2018 +0200
@@ -75,9 +75,9 @@
 #
 
 find_program(
-    Pandoc_EXECUTABLE
-    NAMES pandoc
-    DOC "Pandoc executable"
+	Pandoc_EXECUTABLE
+	NAMES pandoc
+	DOC "Pandoc executable"
 )
 
 include(FindPackageHandleStandardArgs)
@@ -85,145 +85,145 @@
 
 # Extract the version
 if (Pandoc_EXECUTABLE)
-    execute_process(
-        COMMAND pandoc --version
-        OUTPUT_VARIABLE _pandoc_version_tmp
-    )
+	execute_process(
+		COMMAND pandoc --version
+		OUTPUT_VARIABLE _pandoc_version_tmp
+	)
 
-    string(REGEX REPLACE "^pandoc ([0-9]*\\.[0-9]*\\.[0-9]*).*$" "\\1" Pandoc_VERSION ${_pandoc_version_tmp})
+	string(REGEX REPLACE "^pandoc ([0-9]*\\.[0-9]*\\.[0-9]*).*$" "\\1" Pandoc_VERSION ${_pandoc_version_tmp})
 endif ()
 
 find_package_handle_standard_args(
-    Pandoc
-    FOUND_VAR Pandoc_FOUND
-    VERSION_VAR Pandoc_VERSION
-    REQUIRED_VARS Pandoc_EXECUTABLE
+	Pandoc
+	FOUND_VAR Pandoc_FOUND
+	VERSION_VAR Pandoc_VERSION
+	REQUIRED_VARS Pandoc_EXECUTABLE
 )
 
 if (Pandoc_FOUND)
-    function(pandoc)
-        set(options MAKE_DIRECTORY STANDALONE TOC)
-        set(oneValueArgs FILTER FROM TARGET TEMPLATE TO OUTPUT WORKING_DIRECTORY)
-        set(multiValueArgs ARGS FOOTER HEADER METADATA SOURCES VARIABLE DEPENDS)
+	function(pandoc)
+		set(options MAKE_DIRECTORY STANDALONE TOC)
+		set(oneValueArgs FILTER FROM TARGET TEMPLATE TO OUTPUT WORKING_DIRECTORY)
+		set(multiValueArgs ARGS FOOTER HEADER METADATA SOURCES VARIABLE DEPENDS)
 
-        #
-        # The following variables will be set in that scope:
-        #   _pandoc_arguments       List of all arguments that will passed to pandoc invocation.
-        #   _pandoc_depends         List of all dependencies attached to the add_custom_command.
-        #   _pandoc_mkdir           The mkdir command if MAKE_DIRECTORY is set
-        #   _pandoc_output_base     The base output directory
-        #
-        cmake_parse_arguments(PANDOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+		#
+		# The following variables will be set in that scope:
+		#   _pandoc_arguments	   List of all arguments that will passed to pandoc invocation.
+		#   _pandoc_depends		 List of all dependencies attached to the add_custom_command.
+		#   _pandoc_mkdir		   The mkdir command if MAKE_DIRECTORY is set
+		#   _pandoc_output_base	 The base output directory
+		#
+		cmake_parse_arguments(PANDOC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
 
-        #
-        # Output and sources are mandatory
-        #
-        if (NOT PANDOC_OUTPUT)
-            message(FATAL_ERROR "Please define OUTPUT")
-        elseif (NOT PANDOC_SOURCES)
-            message(FATAL_ERROR "Please defines SOURCES")
-        endif ()
+		#
+		# Output and sources are mandatory
+		#
+		if (NOT PANDOC_OUTPUT)
+			message(FATAL_ERROR "Please define OUTPUT")
+		elseif (NOT PANDOC_SOURCES)
+			message(FATAL_ERROR "Please defines SOURCES")
+		endif ()
 
-        #
-        # Handle the filter with care.
-        #
-        # 1. If it is a target, depend on it and use a generator
-        #    expression to get its full path on the disk.
-        # 2. If it is not a target, just use the user provided path.
-        #
-        if (PANDOC_FILTER)
-            # If it is a target, add a dependency so that it is built
-            if (TARGET ${PANDOC_FILTER})
-                list(APPEND _pandoc_arguments --filter "$<TARGET_FILE:${PANDOC_FILTER}>")
-                list(APPEND _pandoc_depends ${PANDOC_FILTER})
-            else ()
-                list(APPEND _pandoc_arguments --filter ${PANDOC_FILTER})
-            endif ()
-        endif ()
+		#
+		# Handle the filter with care.
+		#
+		# 1. If it is a target, depend on it and use a generator
+		#	expression to get its full path on the disk.
+		# 2. If it is not a target, just use the user provided path.
+		#
+		if (PANDOC_FILTER)
+			# If it is a target, add a dependency so that it is built
+			if (TARGET ${PANDOC_FILTER})
+				list(APPEND _pandoc_arguments --filter "$<TARGET_FILE:${PANDOC_FILTER}>")
+				list(APPEND _pandoc_depends ${PANDOC_FILTER})
+			else ()
+				list(APPEND _pandoc_arguments --filter ${PANDOC_FILTER})
+			endif ()
+		endif ()
 
-        if (PANDOC_TOC)
-            list(APPEND _pandoc_arguments --toc)
-        endif ()
-        if (PANDOC_STANDALONE)
-            list(APPEND _pandoc_arguments -s)
-        endif ()
-        if (PANDOC_FROM)
-            list(APPEND _pandoc_arguments -f ${PANDOC_FROM})
-        endif ()
-        if (PANDOC_TO)
-            list(APPEND _pandoc_arguments -t ${PANDOC_TO})
-        endif ()
-        if (PANDOC_TEMPLATE)
-            list(APPEND _pandoc_arguments --template ${PANDOC_TEMPLATE})
-            list(APPEND _pandoc_depends ${PANDOC_TEMPLATE})
-        endif ()
+		if (PANDOC_TOC)
+			list(APPEND _pandoc_arguments --toc)
+		endif ()
+		if (PANDOC_STANDALONE)
+			list(APPEND _pandoc_arguments -s)
+		endif ()
+		if (PANDOC_FROM)
+			list(APPEND _pandoc_arguments -f ${PANDOC_FROM})
+		endif ()
+		if (PANDOC_TO)
+			list(APPEND _pandoc_arguments -t ${PANDOC_TO})
+		endif ()
+		if (PANDOC_TEMPLATE)
+			list(APPEND _pandoc_arguments --template ${PANDOC_TEMPLATE})
+			list(APPEND _pandoc_depends ${PANDOC_TEMPLATE})
+		endif ()
 
-        # Header, footers and body
-        foreach (h ${PANDOC_HEADER})
-            list(APPEND _pandoc_arguments -H ${h})
-            list(APPEND _pandoc_depends ${h})
-        endforeach ()
-        foreach (b ${PANDOC_BODY})
-            list(APPEND _pandoc_arguments -B ${b})
-            list(APPEND _pandoc_depends ${b})
-        endforeach ()
-        foreach (f ${PANDOC_FOOTER})
-            list(APPEND _pandoc_arguments -A ${f})
-            list(APPEND _pandoc_depends ${f})
-        endforeach ()
+		# Header, footers and body
+		foreach (h ${PANDOC_HEADER})
+			list(APPEND _pandoc_arguments -H ${h})
+			list(APPEND _pandoc_depends ${h})
+		endforeach ()
+		foreach (b ${PANDOC_BODY})
+			list(APPEND _pandoc_arguments -B ${b})
+			list(APPEND _pandoc_depends ${b})
+		endforeach ()
+		foreach (f ${PANDOC_FOOTER})
+			list(APPEND _pandoc_arguments -A ${f})
+			list(APPEND _pandoc_depends ${f})
+		endforeach ()
 
-        # Variables and metadata
-        foreach (var ${PANDOC_VARIABLE})
-            list(APPEND _pandoc_arguments -V ${var})
-        endforeach ()
-        foreach (meta ${PANDOC_METADATA})
-            list(APPEND _pandoc_arguments -M ${meta})
-        endforeach ()
+		# Variables and metadata
+		foreach (var ${PANDOC_VARIABLE})
+			list(APPEND _pandoc_arguments -V ${var})
+		endforeach ()
+		foreach (meta ${PANDOC_METADATA})
+			list(APPEND _pandoc_arguments -M ${meta})
+		endforeach ()
 
-        # Optional list of arguments
-        foreach (arg ${PANDOC_ARGS})
-            list(APPEND _pandoc_arguments ${arg})
-        endforeach ()
+		# Optional list of arguments
+		foreach (arg ${PANDOC_ARGS})
+			list(APPEND _pandoc_arguments ${arg})
+		endforeach ()
 
-        # Output and sources
-        list(APPEND _pandoc_arguments -o ${PANDOC_OUTPUT})
+		# Output and sources
+		list(APPEND _pandoc_arguments -o ${PANDOC_OUTPUT})
 
-        #
-        # The following variables are set within the loop:
-        #
-        #   _pandoc_input       The absolute path to the input file.
-        #   _pandoc_output_base The base output directory.
-        #
-        foreach (s ${PANDOC_SOURCES})
-            get_filename_component(_pandoc_input ${s} ABSOLUTE)
-            get_filename_component(_pandoc_output_base ${PANDOC_OUTPUT} DIRECTORY)
-            list(APPEND _pandoc_depends ${_pandoc_input})
-            list(APPEND _pandoc_arguments ${_pandoc_input})
-        endforeach ()
+		#
+		# The following variables are set within the loop:
+		#
+		#   _pandoc_input	   The absolute path to the input file.
+		#   _pandoc_output_base The base output directory.
+		#
+		foreach (s ${PANDOC_SOURCES})
+			get_filename_component(_pandoc_input ${s} ABSOLUTE)
+			get_filename_component(_pandoc_output_base ${PANDOC_OUTPUT} DIRECTORY)
+			list(APPEND _pandoc_depends ${_pandoc_input})
+			list(APPEND _pandoc_arguments ${_pandoc_input})
+		endforeach ()
 
-        # Create the output directory if requested
-        if (PANDOC_MAKE_DIRECTORY)
-            set(_pandoc_mkdir ${CMAKE_COMMAND} -E make_directory ${_pandoc_output_base})
-        endif ()
+		# Create the output directory if requested
+		if (PANDOC_MAKE_DIRECTORY)
+			set(_pandoc_mkdir ${CMAKE_COMMAND} -E make_directory ${_pandoc_output_base})
+		endif ()
 
-        add_custom_command(
-            OUTPUT ${PANDOC_OUTPUT}
-            COMMAND    ${_pandoc_mkdir}
-            COMMAND    ${Pandoc_EXECUTABLE} ${_pandoc_arguments}
-            DEPENDS ${_pandoc_depends} ${PANDOC_DEPENDS}
-            WORKING_DIRECTORY ${PANDOC_WORKING_DIRECTORY}
-            VERBATIM
-        )
+		add_custom_command(
+			OUTPUT ${PANDOC_OUTPUT}
+			COMMAND	${_pandoc_mkdir}
+			COMMAND	${Pandoc_EXECUTABLE} ${_pandoc_arguments}
+			DEPENDS ${_pandoc_depends} ${PANDOC_DEPENDS}
+			WORKING_DIRECTORY ${PANDOC_WORKING_DIRECTORY}
+			VERBATIM
+		)
 
-        if (PANDOC_TARGET)
-            add_custom_target(
-                ${PANDOC_TARGET} ${PANDOC_ALL}
-                SOURCES ${_pandoc_depends}
-                DEPENDS ${PANDOC_OUTPUT}
-                WORKING_DIRECTORY ${PANDOC_WORKING_DIRECTORY}
-            )
-        endif ()
-    endfunction()
+		if (PANDOC_TARGET)
+			add_custom_target(
+				${PANDOC_TARGET} ${PANDOC_ALL}
+				SOURCES ${_pandoc_depends}
+				DEPENDS ${PANDOC_OUTPUT}
+				WORKING_DIRECTORY ${PANDOC_WORKING_DIRECTORY}
+			)
+		endif ()
+	endfunction()
 endif ()
 
 mark_as_advanced(Pandoc_EXECUTABLE)
--- a/doc/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/doc/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,12 +19,12 @@
 project(doc)
 
 if (IRCCD_HAVE_DOXYGEN)
-    add_subdirectory(doxygen)
+	add_subdirectory(doxygen)
 endif ()
 
 add_subdirectory(examples)
 #add_subdirectory(man)
 
 if (IRCCD_HAVE_HTML)
-    add_subdirectory(html)
+	add_subdirectory(html)
 endif ()
--- a/doc/doxygen/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/doc/doxygen/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,26 +17,26 @@
 project(doxygen)
 
 if (NOT DOXYGEN_DOT_FOUND)
-    set(DOXYGEN_HAVE_DOT "NO")
-    set(DOXYGEN_DOT_PATH "")
+	set(DOXYGEN_HAVE_DOT "NO")
+	set(DOXYGEN_DOT_PATH "")
 else ()
-    set(DOXYGEN_HAVE_DOT "YES")
-    set(DOXYGEN_DOT_PATH "\"${DOXYGEN_DOT_EXECUTABLE}\"")
+	set(DOXYGEN_HAVE_DOT "YES")
+	set(DOXYGEN_DOT_PATH "\"${DOXYGEN_DOT_EXECUTABLE}\"")
 endif ()
 
 configure_file(
-    ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
-    ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+	${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
+	${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
 )
 
 add_custom_target(
-    doxygen
-    ALL
-    COMMENT "Generating doxygen documentation"
-    COMMAND
-        ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}
-    COMMAND
-        ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
-    WORKING_DIRECTORY
-        ${CMAKE_SOURCE_DIR}
+	doxygen
+	ALL
+	COMMENT "Generating doxygen documentation"
+	COMMAND
+		${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}
+	COMMAND
+		${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+	WORKING_DIRECTORY
+		${CMAKE_SOURCE_DIR}
 )
--- a/doc/examples/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/doc/examples/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,21 +19,21 @@
 project(examples)
 
 configure_file(
-    ${examples_SOURCE_DIR}/irccd.conf.sample
-    ${examples_BINARY_DIR}/irccd.conf
+	${examples_SOURCE_DIR}/irccd.conf.sample
+	${examples_BINARY_DIR}/irccd.conf
 )
 
 configure_file(
-    ${examples_SOURCE_DIR}/irccdctl.conf.sample
-    ${examples_BINARY_DIR}/irccdctl.conf
+	${examples_SOURCE_DIR}/irccdctl.conf.sample
+	${examples_BINARY_DIR}/irccdctl.conf
 )
 
 install(
-    FILES
-        ${examples_SOURCE_DIR}/irccd.conf.sample
-        ${examples_SOURCE_DIR}/irccdctl.conf.sample
-    COMPONENT examples
-    DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}
+	FILES
+		${examples_SOURCE_DIR}/irccd.conf.sample
+		${examples_SOURCE_DIR}/irccdctl.conf.sample
+	COMPONENT examples
+	DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}
 )
 
 setg(CPACK_COMPONENT_EXAMPLES_HIDDEN On)
--- a/doc/html/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/doc/html/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,191 +19,191 @@
 project(html)
 
 set(
-    HTML_API_SOURCES
-    api/event/onCommand.md
-    api/event/onConnect.md
-    api/event/onDisconnect.md
-    api/event/onInvite.md
-    api/event/onJoin.md
-    api/event/onKick.md
-    api/event/onLoad.md
-    api/event/onMe.md
-    api/event/onMessage.md
-    api/event/onMode.md
-    api/event/onNames.md
-    api/event/onNick.md
-    api/event/onNotice.md
-    api/event/onPart.md
-    api/event/onReload.md
-    api/event/onTopic.md
-    api/event/onUnload.md
-    api/event/onWhois.md
-    api/index.md
-    api/module/Irccd.Directory/index.md
-    api/module/Irccd.Directory/Irccd.Directory.find.md
-    api/module/Irccd.Directory/Irccd.Directory.mkdir.md
-    api/module/Irccd.Directory/Irccd.Directory.prototype.constructor.md
-    api/module/Irccd.Directory/Irccd.Directory.prototype.find.md
-    api/module/Irccd.Directory/Irccd.Directory.prototype.remove.md
-    api/module/Irccd.Directory/Irccd.Directory.remove.md
-    api/module/Irccd.ElapsedTimer/index.md
-    api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.constructor.md
-    api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.elapsed.md
-    api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.pause.md
-    api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.reset.md
-    api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.restart.md
-    api/module/Irccd.File/index.md
-    api/module/Irccd.File/Irccd.File.basename.md
-    api/module/Irccd.File/Irccd.File.dirname.md
-    api/module/Irccd.File/Irccd.File.exists.md
-    api/module/Irccd.File/Irccd.File.prototype.basename.md
-    api/module/Irccd.File/Irccd.File.prototype.close.md
-    api/module/Irccd.File/Irccd.File.prototype.constructor.md
-    api/module/Irccd.File/Irccd.File.prototype.dirname.md
-    api/module/Irccd.File/Irccd.File.prototype.lines.md
-    api/module/Irccd.File/Irccd.File.prototype.readline.md
-    api/module/Irccd.File/Irccd.File.prototype.read.md
-    api/module/Irccd.File/Irccd.File.prototype.remove.md
-    api/module/Irccd.File/Irccd.File.prototype.seek.md
-    api/module/Irccd.File/Irccd.File.prototype.stat.md
-    api/module/Irccd.File/Irccd.File.prototype.tell.md
-    api/module/Irccd.File/Irccd.File.prototype.write.md
-    api/module/Irccd.File/Irccd.File.remove.md
-    api/module/Irccd.File/Irccd.File.stat.md
-    api/module/Irccd/index.md
-    api/module/Irccd.Logger/index.md
-    api/module/Irccd.Logger/Irccd.Logger.debug.md
-    api/module/Irccd.Logger/Irccd.Logger.info.md
-    api/module/Irccd.Logger/Irccd.Logger.warning.md
-    api/module/Irccd.Plugin/index.md
-    api/module/Irccd.Plugin/Irccd.Plugin.info.md
-    api/module/Irccd.Plugin/Irccd.Plugin.list.md
-    api/module/Irccd.Plugin/Irccd.Plugin.load.md
-    api/module/Irccd.Plugin/Irccd.Plugin.reload.md
-    api/module/Irccd.Plugin/Irccd.Plugin.unload.md
-    api/module/Irccd.Server/index.md
-    api/module/Irccd.Server/Irccd.Server.add.md
-    api/module/Irccd.Server/Irccd.Server.find.md
-    api/module/Irccd.Server/Irccd.Server.list.md
-    api/module/Irccd.Server/Irccd.Server.prototype.constructor.md
-    api/module/Irccd.Server/Irccd.Server.prototype.info.md
-    api/module/Irccd.Server/Irccd.Server.prototype.invite.md
-    api/module/Irccd.Server/Irccd.Server.prototype.isSelf.md
-    api/module/Irccd.Server/Irccd.Server.prototype.join.md
-    api/module/Irccd.Server/Irccd.Server.prototype.kick.md
-    api/module/Irccd.Server/Irccd.Server.prototype.me.md
-    api/module/Irccd.Server/Irccd.Server.prototype.message.md
-    api/module/Irccd.Server/Irccd.Server.prototype.mode.md
-    api/module/Irccd.Server/Irccd.Server.prototype.names.md
-    api/module/Irccd.Server/Irccd.Server.prototype.nick.md
-    api/module/Irccd.Server/Irccd.Server.prototype.notice.md
-    api/module/Irccd.Server/Irccd.Server.prototype.part.md
-    api/module/Irccd.Server/Irccd.Server.prototype.topic.md
-    api/module/Irccd.Server/Irccd.Server.prototype.toString.md
-    api/module/Irccd.Server/Irccd.Server.prototype.whois.md
-    api/module/Irccd.Server/Irccd.Server.remove.md
-    api/module/Irccd.System/index.md
-    api/module/Irccd.System/Irccd.System.env.md
-    api/module/Irccd.System/Irccd.System.exec.md
-    api/module/Irccd.System/Irccd.System.home.md
-    api/module/Irccd.System/Irccd.System.name.md
-    api/module/Irccd.System/Irccd.System.popen.md
-    api/module/Irccd.System/Irccd.System.sleep.md
-    api/module/Irccd.System/Irccd.System.ticks.md
-    api/module/Irccd.System/Irccd.System.uptime.md
-    api/module/Irccd.System/Irccd.System.usleep.md
-    api/module/Irccd.System/Irccd.System.version.md
-    api/module/Irccd.Timer/index.md
-    api/module/Irccd.Timer/Irccd.Timer.prototype.constructor.md
-    api/module/Irccd.Timer/Irccd.Timer.prototype.start.md
-    api/module/Irccd.Timer/Irccd.Timer.prototype.stop.md
-    api/module/Irccd.Unicode/index.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isDigit.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isLetter.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isLower.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isSpace.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isTitle.md
-    api/module/Irccd.Unicode/Irccd.Unicode.isUpper.md
-    api/module/Irccd.Util/index.md
-    api/module/Irccd.Util/Irccd.Util.cut.md
-    api/module/Irccd.Util/Irccd.Util.format.md
-    api/module/Irccd.Util/Irccd.Util.splithost.md
-    api/module/Irccd.Util/Irccd.Util.splituser.md
+	HTML_API_SOURCES
+	api/event/onCommand.md
+	api/event/onConnect.md
+	api/event/onDisconnect.md
+	api/event/onInvite.md
+	api/event/onJoin.md
+	api/event/onKick.md
+	api/event/onLoad.md
+	api/event/onMe.md
+	api/event/onMessage.md
+	api/event/onMode.md
+	api/event/onNames.md
+	api/event/onNick.md
+	api/event/onNotice.md
+	api/event/onPart.md
+	api/event/onReload.md
+	api/event/onTopic.md
+	api/event/onUnload.md
+	api/event/onWhois.md
+	api/index.md
+	api/module/Irccd.Directory/index.md
+	api/module/Irccd.Directory/Irccd.Directory.find.md
+	api/module/Irccd.Directory/Irccd.Directory.mkdir.md
+	api/module/Irccd.Directory/Irccd.Directory.prototype.constructor.md
+	api/module/Irccd.Directory/Irccd.Directory.prototype.find.md
+	api/module/Irccd.Directory/Irccd.Directory.prototype.remove.md
+	api/module/Irccd.Directory/Irccd.Directory.remove.md
+	api/module/Irccd.ElapsedTimer/index.md
+	api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.constructor.md
+	api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.elapsed.md
+	api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.pause.md
+	api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.reset.md
+	api/module/Irccd.ElapsedTimer/Irccd.ElapsedTimer.prototype.restart.md
+	api/module/Irccd.File/index.md
+	api/module/Irccd.File/Irccd.File.basename.md
+	api/module/Irccd.File/Irccd.File.dirname.md
+	api/module/Irccd.File/Irccd.File.exists.md
+	api/module/Irccd.File/Irccd.File.prototype.basename.md
+	api/module/Irccd.File/Irccd.File.prototype.close.md
+	api/module/Irccd.File/Irccd.File.prototype.constructor.md
+	api/module/Irccd.File/Irccd.File.prototype.dirname.md
+	api/module/Irccd.File/Irccd.File.prototype.lines.md
+	api/module/Irccd.File/Irccd.File.prototype.readline.md
+	api/module/Irccd.File/Irccd.File.prototype.read.md
+	api/module/Irccd.File/Irccd.File.prototype.remove.md
+	api/module/Irccd.File/Irccd.File.prototype.seek.md
+	api/module/Irccd.File/Irccd.File.prototype.stat.md
+	api/module/Irccd.File/Irccd.File.prototype.tell.md
+	api/module/Irccd.File/Irccd.File.prototype.write.md
+	api/module/Irccd.File/Irccd.File.remove.md
+	api/module/Irccd.File/Irccd.File.stat.md
+	api/module/Irccd/index.md
+	api/module/Irccd.Logger/index.md
+	api/module/Irccd.Logger/Irccd.Logger.debug.md
+	api/module/Irccd.Logger/Irccd.Logger.info.md
+	api/module/Irccd.Logger/Irccd.Logger.warning.md
+	api/module/Irccd.Plugin/index.md
+	api/module/Irccd.Plugin/Irccd.Plugin.info.md
+	api/module/Irccd.Plugin/Irccd.Plugin.list.md
+	api/module/Irccd.Plugin/Irccd.Plugin.load.md
+	api/module/Irccd.Plugin/Irccd.Plugin.reload.md
+	api/module/Irccd.Plugin/Irccd.Plugin.unload.md
+	api/module/Irccd.Server/index.md
+	api/module/Irccd.Server/Irccd.Server.add.md
+	api/module/Irccd.Server/Irccd.Server.find.md
+	api/module/Irccd.Server/Irccd.Server.list.md
+	api/module/Irccd.Server/Irccd.Server.prototype.constructor.md
+	api/module/Irccd.Server/Irccd.Server.prototype.info.md
+	api/module/Irccd.Server/Irccd.Server.prototype.invite.md
+	api/module/Irccd.Server/Irccd.Server.prototype.isSelf.md
+	api/module/Irccd.Server/Irccd.Server.prototype.join.md
+	api/module/Irccd.Server/Irccd.Server.prototype.kick.md
+	api/module/Irccd.Server/Irccd.Server.prototype.me.md
+	api/module/Irccd.Server/Irccd.Server.prototype.message.md
+	api/module/Irccd.Server/Irccd.Server.prototype.mode.md
+	api/module/Irccd.Server/Irccd.Server.prototype.names.md
+	api/module/Irccd.Server/Irccd.Server.prototype.nick.md
+	api/module/Irccd.Server/Irccd.Server.prototype.notice.md
+	api/module/Irccd.Server/Irccd.Server.prototype.part.md
+	api/module/Irccd.Server/Irccd.Server.prototype.topic.md
+	api/module/Irccd.Server/Irccd.Server.prototype.toString.md
+	api/module/Irccd.Server/Irccd.Server.prototype.whois.md
+	api/module/Irccd.Server/Irccd.Server.remove.md
+	api/module/Irccd.System/index.md
+	api/module/Irccd.System/Irccd.System.env.md
+	api/module/Irccd.System/Irccd.System.exec.md
+	api/module/Irccd.System/Irccd.System.home.md
+	api/module/Irccd.System/Irccd.System.name.md
+	api/module/Irccd.System/Irccd.System.popen.md
+	api/module/Irccd.System/Irccd.System.sleep.md
+	api/module/Irccd.System/Irccd.System.ticks.md
+	api/module/Irccd.System/Irccd.System.uptime.md
+	api/module/Irccd.System/Irccd.System.usleep.md
+	api/module/Irccd.System/Irccd.System.version.md
+	api/module/Irccd.Timer/index.md
+	api/module/Irccd.Timer/Irccd.Timer.prototype.constructor.md
+	api/module/Irccd.Timer/Irccd.Timer.prototype.start.md
+	api/module/Irccd.Timer/Irccd.Timer.prototype.stop.md
+	api/module/Irccd.Unicode/index.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isDigit.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isLetter.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isLower.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isSpace.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isTitle.md
+	api/module/Irccd.Unicode/Irccd.Unicode.isUpper.md
+	api/module/Irccd.Util/index.md
+	api/module/Irccd.Util/Irccd.Util.cut.md
+	api/module/Irccd.Util/Irccd.Util.format.md
+	api/module/Irccd.Util/Irccd.Util.splithost.md
+	api/module/Irccd.Util/Irccd.Util.splituser.md
 )
 
 set(
-    HTML_SOURCES
-    build.md
-    irccd.conf.md
-    irccdctl.conf.md
-    irccdctl.md
-    irccd.md
-    irccd-test.md
+	HTML_SOURCES
+	build.md
+	irccd.conf.md
+	irccdctl.conf.md
+	irccdctl.md
+	irccd.md
+	irccd-test.md
 )
 
 set(
-    CSS
-    ${html_SOURCE_DIR}/css/bootstrap.min.css
-    ${html_SOURCE_DIR}/css/doc-guide.css
-    ${html_SOURCE_DIR}/css/doc.css
-    ${html_SOURCE_DIR}/css/tomorrow.css
+	CSS
+	${html_SOURCE_DIR}/css/bootstrap.min.css
+	${html_SOURCE_DIR}/css/doc-guide.css
+	${html_SOURCE_DIR}/css/doc.css
+	${html_SOURCE_DIR}/css/tomorrow.css
 )
 
 set(
-    JS
-    ${html_SOURCE_DIR}/js/bootstrap.min.js
-    ${html_SOURCE_DIR}/js/highlight.min.js
-    ${html_SOURCE_DIR}/js/jquery.min.js
+	JS
+	${html_SOURCE_DIR}/js/bootstrap.min.js
+	${html_SOURCE_DIR}/js/highlight.min.js
+	${html_SOURCE_DIR}/js/jquery.min.js
 )
 
 foreach (fname ${HTML_API_SOURCES} ${HTML_SOURCES})
-    # API sources require a js variable to be set.
-    if (${fname} IN_LIST HTML_API_SOURCES)
-        set(VARIABLES js:1)
-    else ()
-        set(VARIABLES guide:1)
-    endif ()
+	# API sources require a js variable to be set.
+	if (${fname} IN_LIST HTML_API_SOURCES)
+		set(VARIABLES js:1)
+	else ()
+		set(VARIABLES guide:1)
+	endif ()
 
-    irccd_build_html(
-        SOURCE ${doc_SOURCE_DIR}/src/${fname}
-        OUTPUT ${fname}
-        OUTPUT_VAR output
-        COMPONENT docs
-        VARIABLES ${VARIABLES}
-    )
+	irccd_build_html(
+		SOURCE ${doc_SOURCE_DIR}/src/${fname}
+		OUTPUT ${fname}
+		OUTPUT_VAR output
+		COMPONENT docs
+		VARIABLES ${VARIABLES}
+	)
 
-    list(APPEND SOURCES ${doc_SOURCE_DIR}/src/${fname})
-    list(APPEND OUTPUTS ${output})
+	list(APPEND SOURCES ${doc_SOURCE_DIR}/src/${fname})
+	list(APPEND OUTPUTS ${output})
 endforeach ()
 
 add_custom_target(
-    html ALL
-    SOURCES
-        ${CSS}
-        ${JS}
-        ${OUTPUTS}
-        ${SOURCES}
-        ${html_SOURCE_DIR}/template.html
-    COMMAND
-        ${CMAKE_COMMAND} -E make_directory ${html_BINARY_DIR}/css
-    COMMAND
-        ${CMAKE_COMMAND} -E make_directory ${html_BINARY_DIR}/js
-    COMMAND
-        ${CMAKE_COMMAND} -E copy ${CSS} ${html_BINARY_DIR}/css
-    COMMAND
-        ${CMAKE_COMMAND} -E copy ${JS} ${html_BINARY_DIR}/js
+	html ALL
+	SOURCES
+		${CSS}
+		${JS}
+		${OUTPUTS}
+		${SOURCES}
+		${html_SOURCE_DIR}/template.html
+	COMMAND
+		${CMAKE_COMMAND} -E make_directory ${html_BINARY_DIR}/css
+	COMMAND
+		${CMAKE_COMMAND} -E make_directory ${html_BINARY_DIR}/js
+	COMMAND
+		${CMAKE_COMMAND} -E copy ${CSS} ${html_BINARY_DIR}/css
+	COMMAND
+		${CMAKE_COMMAND} -E copy ${JS} ${html_BINARY_DIR}/js
 )
 
 # Install resources files.
 install(
-    FILES ${CSS}
-    COMPONENT docs
-    DESTINATION ${IRCCD_WITH_DOCDIR}/css
+	FILES ${CSS}
+	COMPONENT docs
+	DESTINATION ${IRCCD_WITH_DOCDIR}/css
 )
 install(
-    FILES ${JS}
-    COMPONENT docs
-    DESTINATION ${IRCCD_WITH_DOCDIR}/js
+	FILES ${JS}
+	COMPONENT docs
+	DESTINATION ${IRCCD_WITH_DOCDIR}/js
 )
 
 setg(CPACK_COMPONENT_DOCS_DISPLAY_NAME "Documentation")
--- a/irccd-test/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccd-test/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -16,15 +16,19 @@
 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #
 
+if (IRCCD_HAVE_LIBEDIT)
+	list(APPEND LIBRARIES ${Editline_LIBRARIES})
+	list(APPEND INCLUDES ${Editline_LIBRARIES})
+endif ()
+
+if (IRCCD_HAVE_JS)
+	list(APPEND LIBRARIES libirccd-js)
+endif ()
+
 irccd_define_executable(
-    TARGET irccd-test
-    LIBRARIES
-        libirccd
-        libirccd-test
-        $<$<BOOL:${IRCCD_HAVE_LIBEDIT}>:${Editline_LIBRARIES}>
-        $<$<BOOL:${IRCCD_HAVE_JS}>:libirccd-js>
-    INCLUDES
-        $<$<BOOL:${IRCCD_HAVE_LIBEDIT}>:${Editline_INCLUDE_DIRS}>
-    DESCRIPTION "Plugin tester"
-    SOURCES main.cpp
+	TARGET irccd-test
+	LIBRARIES libirccd libirccd-test ${LIBRARIES}
+	INCLUDES ${INCLUDES}
+	DESCRIPTION "Plugin tester"
+	SOURCES main.cpp
 )
--- a/irccd-test/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccd-test/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,7 +29,7 @@
 #include <boost/format.hpp>
 
 #if defined(IRCCD_HAVE_LIBEDIT)
-#   include <histedit.h>
+#	include <histedit.h>
 #endif
 
 #include <irccd/options.hpp>
@@ -43,8 +43,8 @@
 #include <irccd/test/debug_server.hpp>
 
 #if defined(IRCCD_HAVE_JS)
-#   include <irccd/js/js_api.hpp>
-#   include <irccd/js/js_plugin.hpp>
+#	include <irccd/js/js_api.hpp>
+#	include <irccd/js/js_plugin.hpp>
 #endif
 
 using boost::format;
@@ -91,23 +91,23 @@
 using functions = std::unordered_map<std::string, function>;
 
 static const functions list{
-    { "onCommand",  &(on_command)   },
-    { "onConnect",  &(on_connect)   },
-    { "onInvite",   &(on_invite)    },
-    { "onJoin",     &(on_join)      },
-    { "onKick",     &(on_kick)      },
-    { "onLoad",     &(on_load)      },
-    { "onMe",       &(on_me)        },
-    { "onMessage",  &(on_message)   },
-    { "onMode",     &(on_mode)      },
-    { "onNames",    &(on_names)     },
-    { "onNick",     &(on_nick)      },
-    { "onNotice",   &(on_notice)    },
-    { "onPart",     &(on_part)      },
-    { "onReload",   &(on_reload)    },
-    { "onTopic",    &(on_topic)     },
-    { "onUnload",   &(on_unload)    },
-    { "onWhois",    &(on_whois)     }
+	{ "onCommand",  &(on_command)   },
+	{ "onConnect",  &(on_connect)   },
+	{ "onInvite",   &(on_invite)    },
+	{ "onJoin",     &(on_join)      },
+	{ "onKick",     &(on_kick)      },
+	{ "onLoad",     &(on_load)      },
+	{ "onMe",       &(on_me)        },
+	{ "onMessage",  &(on_message)   },
+	{ "onMode",     &(on_mode)      },
+	{ "onNames",    &(on_names)     },
+	{ "onNick",     &(on_nick)      },
+	{ "onNotice",   &(on_notice)    },
+	{ "onPart",     &(on_part)      },
+	{ "onReload",   &(on_reload)    },
+	{ "onTopic",    &(on_topic)     },
+	{ "onUnload",   &(on_unload)    },
+	{ "onWhois",    &(on_whois)     }
 };
 
 // }}}
@@ -116,41 +116,41 @@
 
 void usage()
 {
-    std::cerr << "usage: irccd-test [-c config] plugin-name" << std::endl;
-    std::exit(1);
+	std::cerr << "usage: irccd-test [-c config] plugin-name" << std::endl;
+	std::exit(1);
 }
 
 // }}}
 
 // {{{ get_server
 
-std::shared_ptr<server> get_server(std::string name)
+auto get_server(std::string name) -> std::shared_ptr<server>
 {
-    name = boost::algorithm::trim_copy(name);
+	name = boost::algorithm::trim_copy(name);
 
-    if (name.empty())
-        name = "test";
+	if (name.empty())
+		name = "test";
 
-    auto s = daemon->servers().get(name);
+	auto s = daemon->servers().get(name);
 
-    if (!s) {
-        s = std::make_shared<debug_server>(io, std::move(name), "localhost");
-        daemon->servers().add(s);
-    }
+	if (!s) {
+		s = std::make_shared<debug_server>(io, std::move(name), "localhost");
+		daemon->servers().add(s);
+	}
 
-    return s;
+	return s;
 }
 
 // }}}
 
 // {{{ get_arg
 
-std::string get_arg(const std::vector<std::string>& args, unsigned index)
+auto get_arg(const std::vector<std::string>& args, unsigned index) -> std::string
 {
-    if (index >= args.size())
-        return "";
+	if (index >= args.size())
+		return "";
 
-    return args[index];
+	return args[index];
 }
 
 // }}}
@@ -162,14 +162,14 @@
  */
 void on_command(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_command(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3)
-    });
+	plugin->handle_command(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3)
+	});
 }
 
 // }}}
@@ -181,9 +181,9 @@
  */
 void on_connect(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    plugin->handle_connect(*daemon, {get_server(get_arg(args, 0))});
+	plugin->handle_connect(*daemon, {get_server(get_arg(args, 0))});
 }
 
 // }}}
@@ -195,14 +195,14 @@
  */
 void on_invite(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    plugin->handle_invite(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3),
-    });
+	plugin->handle_invite(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3),
+	});
 }
 
 // }}}
@@ -214,13 +214,13 @@
  */
 void on_join(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    plugin->handle_join(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2)
-    });
+	plugin->handle_join(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2)
+	});
 }
 
 // }}}
@@ -232,15 +232,15 @@
  */
 void on_kick(const std::string& data)
 {
-    const auto args = su::split(data, " ", 5);
+	const auto args = su::split(data, " ", 5);
 
-    plugin->handle_kick(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3),
-        get_arg(args, 4),
-    });
+	plugin->handle_kick(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3),
+		get_arg(args, 4),
+	});
 }
 
 // }}}
@@ -252,7 +252,7 @@
  */
 void on_load(const std::string&)
 {
-    plugin->handle_load(*daemon);
+	plugin->handle_load(*daemon);
 }
 
 // }}}
@@ -264,14 +264,14 @@
  */
 void on_me(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_me(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3)
-    });
+	plugin->handle_me(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3)
+	});
 }
 
 // }}}
@@ -283,14 +283,14 @@
  */
 void on_message(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_message(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3)
-    });
+	plugin->handle_message(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3)
+	});
 }
 
 // }}}
@@ -302,17 +302,17 @@
  */
 void on_mode(const std::string& data)
 {
-    const auto args = su::split(data, " ", 7);
+	const auto args = su::split(data, " ", 7);
 
-    plugin->handle_mode(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3),
-        get_arg(args, 4),
-        get_arg(args, 5),
-        get_arg(args, 6),
-    });
+	plugin->handle_mode(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3),
+		get_arg(args, 4),
+		get_arg(args, 5),
+		get_arg(args, 6),
+	});
 }
 
 // }}}
@@ -324,17 +324,17 @@
  */
 void on_names(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    names_event ev;
+	names_event ev;
 
-    ev.server = get_server(get_arg(args, 0));
-    ev.channel = get_arg(args, 1);
+	ev.server = get_server(get_arg(args, 0));
+	ev.channel = get_arg(args, 1);
 
-    if (args.size() >= 3U)
-        ev.names.insert(ev.names.begin(), args.begin() + 2, args.end());
+	if (args.size() >= 3U)
+		ev.names.insert(ev.names.begin(), args.begin() + 2, args.end());
 
-    plugin->handle_names(*daemon, ev);
+	plugin->handle_names(*daemon, ev);
 }
 
 // }}}
@@ -346,13 +346,13 @@
  */
 void on_nick(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    plugin->handle_nick(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2)
-    });
+	plugin->handle_nick(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2)
+	});
 }
 
 // }}}
@@ -364,14 +364,14 @@
  */
 void on_notice(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_notice(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3)
-    });
+	plugin->handle_notice(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3)
+	});
 }
 
 // }}}
@@ -383,14 +383,14 @@
  */
 void on_part(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_part(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3),
-    });
+	plugin->handle_part(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3),
+	});
 }
 
 // }}}
@@ -402,7 +402,7 @@
  */
 void on_reload(const std::string&)
 {
-    plugin->handle_reload(*daemon);
+	plugin->handle_reload(*daemon);
 }
 
 // }}}
@@ -414,14 +414,14 @@
  */
 void on_topic(const std::string& data)
 {
-    const auto args = su::split(data, " ", 4);
+	const auto args = su::split(data, " ", 4);
 
-    plugin->handle_topic(*daemon, {
-        get_server(get_arg(args, 0)),
-        get_arg(args, 1),
-        get_arg(args, 2),
-        get_arg(args, 3)
-    });
+	plugin->handle_topic(*daemon, {
+		get_server(get_arg(args, 0)),
+		get_arg(args, 1),
+		get_arg(args, 2),
+		get_arg(args, 3)
+	});
 }
 
 // }}}
@@ -433,7 +433,7 @@
  */
 void on_unload(const std::string&)
 {
-    plugin->handle_unload(*daemon);
+	plugin->handle_unload(*daemon);
 }
 
 // }}}
@@ -445,20 +445,20 @@
  */
 void on_whois(const std::string& data)
 {
-    const auto args = su::split(data, " ");
+	const auto args = su::split(data, " ");
 
-    whois_event ev;
+	whois_event ev;
 
-    ev.server = get_server(get_arg(args, 0));
-    ev.whois.nick = get_arg(args, 1);
-    ev.whois.user = get_arg(args, 2);
-    ev.whois.host = get_arg(args, 3);
-    ev.whois.realname = get_arg(args, 4);
+	ev.server = get_server(get_arg(args, 0));
+	ev.whois.nick = get_arg(args, 1);
+	ev.whois.user = get_arg(args, 2);
+	ev.whois.host = get_arg(args, 3);
+	ev.whois.realname = get_arg(args, 4);
 
-    if (args.size() >= 5)
-        ev.whois.channels.insert(ev.whois.channels.begin(), args.begin() + 5, args.end());
+	if (args.size() >= 5)
+		ev.whois.channels.insert(ev.whois.channels.begin(), args.begin() + 5, args.end());
 
-    plugin->handle_whois(*daemon, ev);
+	plugin->handle_whois(*daemon, ev);
 }
 
 // }}}
@@ -467,11 +467,11 @@
 
 void exec(const std::string& line)
 {
-    const auto pos = line.find(' ');
-    const auto it = list.find(line.substr(0, pos));
+	const auto pos = line.find(' ');
+	const auto it = list.find(line.substr(0, pos));
 
-    if (it != list.end())
-        it->second(pos == std::string::npos ? "" : line.substr(pos + 1));
+	if (it != list.end())
+		it->second(pos == std::string::npos ? "" : line.substr(pos + 1));
 }
 
 // }}}
@@ -480,80 +480,80 @@
 
 // {{{ prompt (libedit version)
 
-const char* prompt(EditLine*)
+auto prompt(EditLine*) -> const char*
 {
-    static const char* text = "> ";
+	static const char* text = "> ";
 
-    return text;
+	return text;
 }
 
-std::string clean(std::string input)
+auto clean(std::string input) -> std::string
 {
-    while (!input.empty() && (input.back() == '\n' || input.back() == '\r'))
-        input.pop_back();
+	while (!input.empty() && (input.back() == '\n' || input.back() == '\r'))
+		input.pop_back();
 
-    return input;
+	return input;
 }
 
-std::vector<std::string> matches(const std::string& name)
+auto matches(const std::string& name) -> std::vector<std::string>
 {
-    std::vector<std::string> result;
+	std::vector<std::string> result;
 
-    for (const auto& pair : list)
-        if (pair.first.compare(0U, name.size(), name) == 0U)
-            result.push_back(pair.first);
+	for (const auto& pair : list)
+		if (pair.first.compare(0U, name.size(), name) == 0U)
+			result.push_back(pair.first);
 
-    return result;
+	return result;
 }
 
-unsigned char complete(EditLine* el, int)
+auto complete(EditLine* el, int) -> unsigned char
 {
-    const auto* lf = el_line(el);
-    const auto args = su::split(std::string(lf->buffer, lf->cursor), " ");
+	const auto* lf = el_line(el);
+	const auto args = su::split(std::string(lf->buffer, lf->cursor), " ");
 
-    if (args.size() == 0U)
-        return CC_REFRESH;
+	if (args.size() == 0U)
+		return CC_REFRESH;
 
-    const auto found = matches(args[0]);
+	const auto found = matches(args[0]);
 
-    if (found.size() != 1U)
-        return CC_REFRESH;
+	if (found.size() != 1U)
+		return CC_REFRESH;
 
-    // Insert the missing text, e.g. onCom -> onCommand.
-    if (el_insertstr(el, &found[0].c_str()[args[0].size()]) < 0)
-        return CC_ERROR;
+	// Insert the missing text, e.g. onCom -> onCommand.
+	if (el_insertstr(el, &found[0].c_str()[args[0].size()]) < 0)
+		return CC_ERROR;
 
-    return CC_REFRESH;
+	return CC_REFRESH;
 }
 
 void run()
 {
-    std::unique_ptr<EditLine, void (*)(EditLine*)> el(
-        el_init("irccd-test", stdin, stdout, stderr),
-        el_end
-    );
-    std::unique_ptr<History, void (*)(History*)> hist(
-        history_init(),
-        history_end
-    );
-    HistEvent hev;
+	std::unique_ptr<EditLine, void (*)(EditLine*)> el(
+		el_init("irccd-test", stdin, stdout, stderr),
+		el_end
+	);
+	std::unique_ptr<History, void (*)(History*)> hist(
+		history_init(),
+		history_end
+	);
+	HistEvent hev;
 
-    history(hist.get(), &hev, H_SETSIZE, 1024);
-    el_set(el.get(), EL_EDITOR, "emacs");
-    el_set(el.get(), EL_PROMPT, prompt);
-    el_set(el.get(), EL_HIST, history, hist.get());
-    el_set(el.get(), EL_ADDFN, "ed-complete", "Complete command", complete);
-    el_set(el.get(), EL_BIND, "^I", "ed-complete", nullptr);
+	history(hist.get(), &hev, H_SETSIZE, 1024);
+	el_set(el.get(), EL_EDITOR, "emacs");
+	el_set(el.get(), EL_PROMPT, prompt);
+	el_set(el.get(), EL_HIST, history, hist.get());
+	el_set(el.get(), EL_ADDFN, "ed-complete", "Complete command", complete);
+	el_set(el.get(), EL_BIND, "^I", "ed-complete", nullptr);
 
-    const char* s;
-    int size;
+	const char* s;
+	int size;
 
-    while ((s = el_gets(el.get(), &size)) && size >= 0) {
-        if (size > 0)
-            history(hist.get(), &hev, H_ENTER, s);
+	while ((s = el_gets(el.get(), &size)) && size >= 0) {
+		if (size > 0)
+			history(hist.get(), &hev, H_ENTER, s);
 
-        exec(clean(s));
-    }
+		exec(clean(s));
+	}
 }
 
 // }}}
@@ -564,16 +564,16 @@
 
 void run()
 {
-    std::string line;
+	std::string line;
 
-    for (;;) {
-        std::cout << "> ";
+	for (;;) {
+		std::cout << "> ";
 
-        if (!std::getline(std::cin, line))
-            return;
+		if (!std::getline(std::cin, line))
+			return;
 
-        exec(line);
-    }
+		exec(line);
+	}
 }
 
 // }}}
@@ -584,11 +584,11 @@
 
 void load_plugins(int argc, char** argv)
 {
-    if (argc <= 0)
-        usage();
+	if (argc <= 0)
+		usage();
 
-    daemon->plugins().load("test", boost::filesystem::exists(argv[0]) ? argv[0] : "");
-    plugin = daemon->plugins().get("test");
+	daemon->plugins().load("test", boost::filesystem::exists(argv[0]) ? argv[0] : "");
+	plugin = daemon->plugins().get("test");
 }
 
 // }}}
@@ -597,14 +597,14 @@
 
 auto load_config(const option::result& result) -> config
 {
-    auto it = result.find("-c");
+	auto it = result.find("-c");
 
-    if (it != result.end() || (it = result.find("--config")) != result.end())
-        return config(it->second);
+	if (it != result.end() || (it = result.find("--config")) != result.end())
+		return config(it->second);
 
-    auto cfg = config::search("irccd.conf");
+	auto cfg = config::search("irccd.conf");
 
-    return *cfg;
+	return *cfg;
 }
 
 // }}}
@@ -613,16 +613,16 @@
 
 void load_options(int& argc, char**& argv)
 {
-    static const option::options def{
-        { "-c",         true    },
-        { "--config",   true    }
-    };
+	static const option::options def{
+		{ "-c",		 true	},
+		{ "--config",   true	}
+	};
 
-    try {
-        daemon->set_config(load_config(option::read(argc, argv, def)));
-    } catch (const std::exception& ex) {
-        throw std::runtime_error(str(format("%1%") % ex.what()));
-    }
+	try {
+		daemon->set_config(load_config(option::read(argc, argv, def)));
+	} catch (const std::exception& ex) {
+		throw std::runtime_error(str(format("%1%") % ex.what()));
+	}
 }
 
 // }}}
@@ -631,20 +631,20 @@
 
 void load(int argc, char** argv)
 {
-    daemon = std::make_unique<irccd>(io);
-    daemon->plugins().add_loader(std::make_unique<dynlib_plugin_loader>());
+	daemon = std::make_unique<irccd>(io);
+	daemon->plugins().add_loader(std::make_unique<dynlib_plugin_loader>());
 
 #if defined(IRCCD_HAVE_JS)
-    auto loader = std::make_unique<js::js_plugin_loader>(*daemon);
+	auto loader = std::make_unique<js::js_plugin_loader>(*daemon);
 
-    for (const auto& f : js::js_api::registry)
-        loader->get_modules().push_back(f());
+	for (const auto& f : js::js_api::registry)
+		loader->get_modules().push_back(f());
 
-    daemon->plugins().add_loader(std::move(loader));
+	daemon->plugins().add_loader(std::move(loader));
 #endif
 
-    load_options(argc, argv);
-    load_plugins(argc, argv);
+	load_options(argc, argv);
+	load_plugins(argc, argv);
 }
 
 // }}}
@@ -655,11 +655,11 @@
 
 int main(int argc, char** argv)
 {
-    try {
-        irccd::load(--argc, ++argv);
-        irccd::run();
-    } catch (const std::exception& ex) {
-        std::cerr << "abort: " << ex.what() << std::endl;
-        return 1;
-    }
+	try {
+		irccd::load(--argc, ++argv);
+		irccd::run();
+	} catch (const std::exception& ex) {
+		std::cerr << "abort: " << ex.what() << std::endl;
+		return 1;
+	}
 }
--- a/irccd/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccd/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -18,15 +18,15 @@
 
 project(irccd)
 
+if (IRCCD_HAVE_JS)
+	list(APPEND LIBRARIES libirccd-js)
+endif ()
+
 irccd_define_executable(
-    TARGET irccd
-    EXPORT
-    DESCRIPTION "The main irccd daemon."
-    SOURCES CMakeLists.txt main.cpp
-    INCLUDES ${irccd_SOURCE_DIR}
-    OPTIONS
-        $<$<BOOL:APPLE>:-Wno-deprecated-declarations>
-    LIBRARIES
-        libirccd
-        $<$<BOOL:${IRCCD_HAVE_JS}>:libirccd-js>
+	TARGET irccd
+	EXPORT
+	DESCRIPTION "The main irccd daemon."
+	SOURCES CMakeLists.txt main.cpp
+	INCLUDES ${irccd_SOURCE_DIR}
+	LIBRARIES libirccd ${LIBRARIES}
 )
--- a/irccd/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccd/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,8 +35,8 @@
 #include <irccd/daemon/transport_service.hpp>
 
 #if defined(IRCCD_HAVE_JS)
-#   include <irccd/js/js_api.hpp>
-#   include <irccd/js/js_plugin.hpp>
+#	include <irccd/js/js_api.hpp>
+#	include <irccd/js/js_plugin.hpp>
 #endif
 
 namespace irccd {
@@ -49,13 +49,13 @@
 
 void usage()
 {
-    std::cerr << "usage: irccd [options...]\n\n";
-    std::cerr << "Available options:\n";
-    std::cerr << "  -c, --config file       specify the configuration file\n";
-    std::cerr << "  -h, --help              show this help\n";
-    std::cerr << "  -v, --verbose           be verbose\n";
-    std::cerr << "      --version           show the version\n";
-    std::exit(1);
+	std::cerr << "usage: irccd [options...]\n\n";
+	std::cerr << "Available options:\n";
+	std::cerr << "  -c, --config file       specify the configuration file\n";
+	std::cerr << "  -h, --help              show this help\n";
+	std::cerr << "  -v, --verbose           be verbose\n";
+	std::cerr << "      --version           show the version\n";
+	std::exit(1);
 }
 
 // }}}
@@ -64,25 +64,25 @@
 
 void version(const option::result& options)
 {
-    std::cout << IRCCD_VERSION << std::endl;
+	std::cout << IRCCD_VERSION << std::endl;
 
-    if (options.count("-v") > 0 || options.count("--verbose") > 0) {
-        bool ssl = false;
-        bool js = false;
+	if (options.count("-v") > 0 || options.count("--verbose") > 0) {
+		bool ssl = false;
+		bool js = false;
 
 #if defined(IRCCD_HAVE_SSL)
-        ssl = true;
+		ssl = true;
 #endif
 #if defined(IRCCD_HAVE_JS)
-        js = true;
+		js = true;
 #endif
 
-        std::cout << std::boolalpha << std::endl;
-        std::cout << "ssl:          " << ssl << std::endl;
-        std::cout << "javascript:   " << js << std::endl;
-    }
+		std::cout << std::boolalpha << std::endl;
+		std::cout << "ssl:		  " << ssl << std::endl;
+		std::cout << "javascript:   " << js << std::endl;
+	}
 
-    std::exit(0);
+	std::exit(0);
 }
 
 // }}}
@@ -91,14 +91,14 @@
 
 void init(int& argc, char**& argv)
 {
-    // Needed for some components.
-    sys::set_program_name("irccd");
+	// Needed for some components.
+	sys::set_program_name("irccd");
 
-    // Default logging to console.
-    instance->get_log().set_verbose(false);
+	// Default logging to console.
+	instance->get_log().set_verbose(false);
 
-    -- argc;
-    ++ argv;
+	-- argc;
+	++ argv;
 }
 
 // }}}
@@ -107,37 +107,37 @@
 
 auto parse(int& argc, char**& argv) -> option::result
 {
-    option::result result;
+	option::result result;
 
-    try {
-        option::options options{
-            { "-c",             true    },
-            { "--config",       true    },
-            { "-h",             false   },
-            { "--help",         false   },
-            { "-v",             false   },
-            { "--verbose",      false   },
-            { "--version",      false   }
-        };
+	try {
+		option::options options{
+			{ "-c",         true    },
+			{ "--config",   true    },
+			{ "-h",         false   },
+			{ "--help",     false   },
+			{ "-v",         false   },
+			{ "--verbose",  false   },
+			{ "--version",  false   }
+		};
 
-        result = option::read(argc, argv, options);
+		result = option::read(argc, argv, options);
 
-        for (const auto& pair : result) {
-            if (pair.first == "-h" || pair.first == "--help")
-                usage();
-                // NOTREACHED
-            if (pair.first == "--version")
-                version(result);
-                // NOTREACHED
-            if (pair.first == "-v" || pair.first == "--verbose")
-                instance->get_log().set_verbose(true);
-        }
-    } catch (const std::exception& ex) {
-        instance->get_log().warning("irccd", "") << "abort: " << ex.what() << std::endl;
-        usage();
-    }
+		for (const auto& pair : result) {
+			if (pair.first == "-h" || pair.first == "--help")
+				usage();
+				// NOTREACHED
+			if (pair.first == "--version")
+				version(result);
+				// NOTREACHED
+			if (pair.first == "-v" || pair.first == "--verbose")
+				instance->get_log().set_verbose(true);
+		}
+	} catch (const std::exception& ex) {
+		instance->get_log().warning("irccd", "") << "abort: " << ex.what() << std::endl;
+		usage();
+	}
 
-    return result;
+	return result;
 }
 
 // }}}
@@ -146,17 +146,17 @@
 
 auto open(const option::result& result) -> config
 {
-    auto it = result.find("-c");
+	auto it = result.find("-c");
 
-    if (it != result.end() || (it = result.find("--config")) != result.end())
-        return config(it->second);
+	if (it != result.end() || (it = result.find("--config")) != result.end())
+		return config(it->second);
 
-    const auto cfg = config::search("irccd.conf");
+	const auto cfg = config::search("irccd.conf");
 
-    if (!cfg)
-        throw std::runtime_error("no configuration file could be found");
+	if (!cfg)
+		throw std::runtime_error("no configuration file could be found");
 
-    return *cfg;
+	return *cfg;
 }
 
 // }}}
@@ -167,56 +167,56 @@
 
 int main(int argc, char** argv)
 {
-    using namespace irccd;
+	using namespace irccd;
 
-    boost::asio::io_service service;
-    boost::asio::signal_set sigs(service, SIGINT, SIGTERM);
+	boost::asio::io_service service;
+	boost::asio::signal_set sigs(service, SIGINT, SIGTERM);
 
-    instance = std::make_unique<class irccd>(service);
+	instance = std::make_unique<class irccd>(service);
 
-    init(argc, argv);
+	init(argc, argv);
 
-    // 1. Load commands.
-    for (const auto& f : command::registry)
-        instance->transports().get_commands().push_back(f());
+	// 1. Load commands.
+	for (const auto& f : command::registry)
+		instance->transports().get_commands().push_back(f());
 
-    // 2. Load plugin loaders.
-    instance->plugins().add_loader(std::make_unique<dynlib_plugin_loader>());
+	// 2. Load plugin loaders.
+	instance->plugins().add_loader(std::make_unique<dynlib_plugin_loader>());
 
 #if defined(IRCCD_HAVE_JS)
-    auto loader = std::make_unique<js::js_plugin_loader>(*instance);
+	auto loader = std::make_unique<js::js_plugin_loader>(*instance);
 
-    for (const auto& f : js::js_api::registry)
-        loader->get_modules().push_back(f());
+	for (const auto& f : js::js_api::registry)
+		loader->get_modules().push_back(f());
 
-    instance->plugins().add_loader(std::move(loader));
+	instance->plugins().add_loader(std::move(loader));
 #endif
 
-    const auto options = parse(argc, argv);
+	const auto options = parse(argc, argv);
 
-    try {
-        instance->set_config(open(options));
-        instance->load();
-    } catch (const std::exception& ex) {
-        std::cerr << "abort: " << ex.what() << std::endl;
-        return 1;
-    }
+	try {
+		instance->set_config(open(options));
+		instance->load();
+	} catch (const std::exception& ex) {
+		std::cerr << "abort: " << ex.what() << std::endl;
+		return 1;
+	}
 
-    /*
-     * Assign instance to nullptr to force deletion of irccd and all its
-     * associated objects before any other static global values such as
-     * loggers.
-     */
-    sigs.async_wait([&] (auto, auto) {
-        service.stop();
-    });
+	/*
+	 * Assign instance to nullptr to force deletion of irccd and all its
+	 * associated objects before any other static global values such as
+	 * loggers.
+	 */
+	sigs.async_wait([&] (auto, auto) {
+		service.stop();
+	});
 
-    try {
-        service.run();
-    } catch (const std::exception& ex) {
-        std::cerr << "abort: " << ex.what() << std::endl;
-        return 1;
-    }
+	try {
+		service.run();
+	} catch (const std::exception& ex) {
+		std::cerr << "abort: " << ex.what() << std::endl;
+		return 1;
+	}
 
-    instance = nullptr;
+	instance = nullptr;
 }
--- a/irccdctl/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,19 +19,19 @@
 project(irccdctl)
 
 set(
-    SOURCES
-    ${irccdctl_SOURCE_DIR}/CMakeLists.txt
-    ${irccdctl_SOURCE_DIR}/alias.cpp
-    ${irccdctl_SOURCE_DIR}/alias.hpp
-    ${irccdctl_SOURCE_DIR}/cli.cpp
-    ${irccdctl_SOURCE_DIR}/cli.hpp
-    ${irccdctl_SOURCE_DIR}/main.cpp
+	SOURCES
+	${irccdctl_SOURCE_DIR}/CMakeLists.txt
+	${irccdctl_SOURCE_DIR}/alias.cpp
+	${irccdctl_SOURCE_DIR}/alias.hpp
+	${irccdctl_SOURCE_DIR}/cli.cpp
+	${irccdctl_SOURCE_DIR}/cli.hpp
+	${irccdctl_SOURCE_DIR}/main.cpp
 )
 
 irccd_define_executable(
-    TARGET irccdctl
-    EXPORT
-    DESCRIPTION "Irccd controller."
-    SOURCES ${SOURCES}
-    LIBRARIES libirccd-ctl
+	TARGET irccdctl
+	EXPORT
+	DESCRIPTION "Irccd controller."
+	SOURCES ${SOURCES}
+	LIBRARIES libirccd-ctl
 )
--- a/irccdctl/alias.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/alias.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,36 +27,67 @@
 
 alias_arg::alias_arg(std::string value)
 {
-    assert(!value.empty());
+	assert(!value.empty());
 
-    if ((is_placeholder_ = std::regex_match(value, std::regex("^%\\d+$"))))
-        value_ = value.substr(1);
-    else
-        value_ = std::move(value);
+	if ((is_placeholder_ = std::regex_match(value, std::regex("^%\\d+$"))))
+		value_ = value.substr(1);
+	else
+		value_ = std::move(value);
+}
+
+auto alias_arg::is_placeholder() const noexcept -> bool
+{
+	return is_placeholder_;
 }
 
-unsigned alias_arg::index() const noexcept
+unsigned alias_arg::get_index() const noexcept
 {
-    assert(is_placeholder_);
+	assert(is_placeholder_);
 
-    return std::stoi(value_);
+	return std::stoi(value_);
 }
 
-const std::string& alias_arg::value() const noexcept
+const std::string& alias_arg::get_value() const noexcept
 {
-    assert(!is_placeholder_);
+	assert(!is_placeholder_);
 
-    return value_;
+	return value_;
 }
 
 std::ostream& operator<<(std::ostream& out, const alias_arg& arg)
 {
-    if (arg.is_placeholder_)
-        out << "%" << arg.value_;
-    else
-        out << arg.value_;
+	if (arg.is_placeholder())
+		out << "%" << arg.get_value();
+	else
+		out << arg.get_value();
+
+	return out;
+}
+
+alias_command::alias_command(std::string command, std::vector<alias_arg> args) noexcept
+	: command_(std::move(command))
+	, args_(std::move(args))
+{
+}
 
-    return out;
+auto alias_command::get_command() const noexcept -> const std::string&
+{
+	return command_;
+}
+
+auto alias_command::get_args() const noexcept -> const std::vector<alias_arg>&
+{
+	return args_;
+}
+
+alias::alias(std::string name) noexcept
+	: name_(std::move(name))
+{
+}
+
+auto alias::get_name() const noexcept -> const std::string&
+{
+	return name_;
 }
 
 } // !ctl
--- a/irccdctl/alias.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/alias.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -44,52 +44,49 @@
  */
 class alias_arg {
 private:
-    std::string value_;
-    bool is_placeholder_;
+	std::string value_;
+	bool is_placeholder_;
 
 public:
-    /**
-     * Construct an argument.
-     *
-     * \pre value must not be empty
-     * \param value the value
-     */
-    alias_arg(std::string value);
+	/**
+	 * Construct an argument.
+	 *
+	 * \pre value must not be empty
+	 * \param value the value
+	 */
+	alias_arg(std::string value);
 
-    /**
-     * Check if the argument is a placeholder.
-     *
-     * \return true if the argument is a placeholder
-     */
-    inline bool is_placeholder() const noexcept
-    {
-        return is_placeholder_;
-    }
+	/**
+	 * Check if the argument is a placeholder.
+	 *
+	 * \return true if the argument is a placeholder
+	 */
+	auto is_placeholder() const noexcept -> bool;
 
-    /**
-     * Get the placeholder index (e.g %0 returns 0)
-     *
-     * \pre is_placeholder() must return true
-     * \return the position
-     */
-    unsigned index() const noexcept;
+	/**
+	 * Get the placeholder index (e.g %0 returns 0)
+	 *
+	 * \pre is_placeholder() must return true
+	 * \return the position
+	 */
+	auto get_index() const noexcept -> unsigned;
 
-    /**
-     * Get the real value.
-     *
-     * \pre is_placeholder() must return false
-     * \return the value
-     */
-    const std::string& value() const noexcept;
+	/**
+	 * Get the real value.
+	 *
+	 * \pre is_placeholder() must return false
+	 * \return the value
+	 */
+	auto get_value() const noexcept -> const std::string&;
+};
 
-    /**
-     * Output the alias to the stream.
-     *
-     * \param out the output stream
-     * \return out
-     */
-    friend std::ostream& operator<<(std::ostream& out, const alias_arg&);
-};
+/**
+ * Output the alias to the stream.
+ *
+ * \param out the output stream
+ * \return out
+ */
+auto operator<<(std::ostream& out, const alias_arg&) -> std::ostream&;
 
 /**
  * \brief Describe a user-provided alias command.
@@ -99,41 +96,31 @@
  */
 class alias_command {
 private:
-    std::string command_;
-    std::vector<alias_arg> args_;
+	std::string command_;
+	std::vector<alias_arg> args_;
 
 public:
-    /**
-     * Create an alias command.
-     *
-     * \param command the command
-     * \param args the arguments
-     */
-    inline alias_command(std::string command, std::vector<alias_arg> args = {}) noexcept
-        : command_(std::move(command))
-        , args_(std::move(args))
-    {
-    }
+	/**
+	 * Create an alias command.
+	 *
+	 * \param command the command
+	 * \param args the arguments
+	 */
+	alias_command(std::string command, std::vector<alias_arg> args = {}) noexcept;
 
-    /**
-     * Get the command to execute.
-     *
-     * \return the command name
-     */
-    inline const std::string& command() const noexcept
-    {
-        return command_;
-    }
+	/**
+	 * Get the command to execute.
+	 *
+	 * \return the command name
+	 */
+	auto get_command() const noexcept -> const std::string&;
 
-    /**
-     * Get the arguments.
-     *
-     * \return the arguments
-     */
-    inline const std::vector<alias_arg>& args() const noexcept
-    {
-        return args_;
-    }
+	/**
+	 * Get the arguments.
+	 *
+	 * \return the arguments
+	 */
+	auto get_args() const noexcept -> const std::vector<alias_arg>&;
 };
 
 /**
@@ -145,28 +132,22 @@
  */
 class alias : public std::vector<alias_command> {
 private:
-    std::string name_;
+	std::string name_;
 
 public:
-    /**
-     * Create an alias.
-     *
-     * \param name the alias name
-     */
-    inline alias(std::string name) noexcept
-        : name_(std::move(name))
-    {
-    }
+	/**
+	 * Create an alias.
+	 *
+	 * \param name the alias name
+	 */
+	alias(std::string name) noexcept;
 
-    /**
-     * Get the alias name.
-     *
-     * \return the name
-     */
-    inline const std::string& name() const noexcept
-    {
-        return name_;
-    }
+	/**
+	 * Get the alias name.
+	 *
+	 * \return the name
+	 */
+	auto get_name() const noexcept -> const std::string&;
 };
 
 } // !ctl
--- a/irccdctl/cli.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/cli.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,6 +28,8 @@
 
 #include "cli.hpp"
 
+using irccd::json_util::deserializer;
+
 namespace irccd::ctl {
 
 // {{{ helpers
@@ -37,192 +39,192 @@
 template <typename T>
 auto bind() noexcept -> cli::constructor
 {
-    return [] () noexcept {
-        return std::make_unique<T>();
-    };
+	return [] () noexcept {
+		return std::make_unique<T>();
+	};
 }
 
 auto format(std::vector<std::string> args) -> std::string
 {
-    auto result = option::read(args, {
-        { "-f",         true },
-        { "--format",   true }
-    });
+	auto result = option::read(args, {
+		{ "-f",         true },
+		{ "--format",   true }
+	});
 
-    if (result.count("-f") > 0)
-        return result.find("-f")->second;
-    if (result.count("--format") > 0)
-        return result.find("--format")->second;
+	if (result.count("-f") > 0)
+		return result.find("-f")->second;
+	if (result.count("--format") > 0)
+		return result.find("--format")->second;
 
-    return "native";
+	return "native";
 }
 
 void onConnect(const nlohmann::json &v)
 {
-    std::cout << "event:       onConnect\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "event:    onConnect\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
 }
 
 void onInvite(const nlohmann::json &v)
 {
-    std::cout << "event:       onInvite\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "event:    onInvite\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
 }
 
 void onJoin(const nlohmann::json &v)
 {
-    std::cout << "event:       onJoin\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "event:    onJoin\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
 }
 
 void onKick(const nlohmann::json &v)
 {
-    std::cout << "event:       onKick\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
-    std::cout << "target:      " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
-    std::cout << "reason:      " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
+	std::cout << "event:    onKick\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "target:   " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
+	std::cout << "reason:   " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
 }
 
 void onMessage(const nlohmann::json &v)
 {
-    std::cout << "event:       onMessage\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
-    std::cout << "message:     " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
+	std::cout << "event:    onMessage\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "message:  " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
 }
 
 void onMe(const nlohmann::json &v)
 {
-    std::cout << "event:       onMe\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "target:      " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
-    std::cout << "message:     " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
+	std::cout << "event:    onMe\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "target:   " << json_util::pretty(v.value("target", "(unknown)")) << "\n";
+	std::cout << "message:  " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
 }
 
 void onMode(const nlohmann::json &v)
 {
-    std::cout << "event:       onMode\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "mode:        " << json_util::pretty(v.value("mode", "(unknown)")) << "\n";
+	std::cout << "event:    onMode\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "mode:     " << json_util::pretty(v.value("mode", "(unknown)")) << "\n";
 }
 
 void onNames(const nlohmann::json &v)
 {
-    std::cout << "event:       onNames\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
-    std::cout << "names:       " << json_util::pretty(v.value("names", "(unknown)")) << "\n";
+	std::cout << "event:    onNames\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "names:    " << json_util::pretty(v.value("names", "(unknown)")) << "\n";
 }
 
 void onNick(const nlohmann::json &v)
 {
-    std::cout << "event:       onNick\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "nickname:    " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
+	std::cout << "event:    onNick\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
 }
 
 void onNotice(const nlohmann::json &v)
 {
-    std::cout << "event:       onNotice\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "message:     " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
+	std::cout << "event:    onNotice\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "message:  " << json_util::pretty(v.value("message", "(unknown)")) << "\n";
 }
 
 void onPart(const nlohmann::json &v)
 {
-    std::cout << "event:       onPart\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
-    std::cout << "reason:      " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
+	std::cout << "event:    onPart\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "reason:   " << json_util::pretty(v.value("reason", "(unknown)")) << "\n";
 }
 
 void onTopic(const nlohmann::json &v)
 {
-    std::cout << "event:       onTopic\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "origin:      " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
-    std::cout << "channel:     " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
-    std::cout << "topic:       " << json_util::pretty(v.value("topic", "(unknown)")) << "\n";
+	std::cout << "event:    onTopic\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "origin:   " << json_util::pretty(v.value("origin", "(unknown)")) << "\n";
+	std::cout << "channel:  " << json_util::pretty(v.value("channel", "(unknown)")) << "\n";
+	std::cout << "topic:    " << json_util::pretty(v.value("topic", "(unknown)")) << "\n";
 }
 
 void onWhois(const nlohmann::json &v)
 {
-    std::cout << "event:       onWhois\n";
-    std::cout << "server:      " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
-    std::cout << "nickname:    " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
-    std::cout << "username:    " << json_util::pretty(v.value("username", "(unknown)")) << "\n";
-    std::cout << "host:        " << json_util::pretty(v.value("host", "(unknown)")) << "\n";
-    std::cout << "realname:    " << json_util::pretty(v.value("realname", "(unknown)")) << "\n";
+	std::cout << "event:    onWhois\n";
+	std::cout << "server:   " << json_util::pretty(v.value("server", "(unknown)")) << "\n";
+	std::cout << "nickname: " << json_util::pretty(v.value("nickname", "(unknown)")) << "\n";
+	std::cout << "username: " << json_util::pretty(v.value("username", "(unknown)")) << "\n";
+	std::cout << "host:     " << json_util::pretty(v.value("host", "(unknown)")) << "\n";
+	std::cout << "realname: " << json_util::pretty(v.value("realname", "(unknown)")) << "\n";
 }
 
 const std::unordered_map<std::string_view, std::function<void (const nlohmann::json&)>> events{
-    { "onConnect",          onConnect       },
-    { "onInvite",           onInvite        },
-    { "onJoin",             onJoin          },
-    { "onKick",             onKick          },
-    { "onMessage",          onMessage       },
-    { "onMe",               onMe            },
-    { "onMode",             onMode          },
-    { "onNames",            onNames         },
-    { "onNick",             onNick          },
-    { "onNotice",           onNotice        },
-    { "onPart",             onPart          },
-    { "onTopic",            onTopic         },
-    { "onWhois",            onWhois         }
+	{ "onConnect",  onConnect       },
+	{ "onInvite",   onInvite        },
+	{ "onJoin",     onJoin          },
+	{ "onKick",     onKick          },
+	{ "onMessage",  onMessage       },
+	{ "onMe",       onMe            },
+	{ "onMode",     onMode          },
+	{ "onNames",    onNames         },
+	{ "onNick",     onNick          },
+	{ "onNotice",   onNotice        },
+	{ "onPart",     onPart          },
+	{ "onTopic",    onTopic         },
+	{ "onWhois",    onWhois         }
 };
 
 void get_event(ctl::controller& ctl, std::string fmt)
 {
-    ctl.read([&ctl, fmt] (auto code, auto message) {
-        if (code)
-            throw std::system_error(code);
+	ctl.read([&ctl, fmt] (auto code, auto message) {
+		if (code)
+			throw std::system_error(code);
 
-        const auto event = json_util::document(message).get<std::string>("event");
-        const auto it = events.find(event ? *event : "");
+		const auto event = deserializer(message).get<std::string>("event");
+		const auto it = events.find(event ? *event : "");
 
-        if (it != events.end()) {
-            if (fmt == "json")
-                std::cout << message.dump(4) << std::endl;
-            else {
-                it->second(message);
-                std::cout << std::endl;
-            }
-        }
+		if (it != events.end()) {
+			if (fmt == "json")
+				std::cout << message.dump(4) << std::endl;
+			else {
+				it->second(message);
+				std::cout << std::endl;
+			}
+		}
 
-        get_event(ctl, std::move(fmt));
-    });
+		get_event(ctl, std::move(fmt));
+	});
 }
 
 auto parse(std::vector<std::string> &args) -> option::result
 {
-    option::options options{
-        { "-c",             true    },
-        { "--command",      true    },
-        { "-n",             true    },
-        { "--nickname",     true    },
-        { "-r",             true    },
-        { "--realname",     true    },
-        { "-S",             false   },
-        { "--ssl-verify",   false   },
-        { "-s",             false   },
-        { "--ssl",          false   },
-        { "-u",             true    },
-        { "--username",     true    }
-    };
+	option::options options{
+		{ "-c",                 true    },
+		{ "--command",          true    },
+		{ "-n",                 true    },
+		{ "--nickname",         true    },
+		{ "-r",                 true    },
+		{ "--realname",         true    },
+		{ "-S",                 false   },
+		{ "--ssl-verify",       false   },
+		{ "-s",                 false   },
+		{ "--ssl",              false   },
+		{ "-u",                 true    },
+		{ "--username",         true    }
+	};
 
-    return option::read(args, options);
+	return option::read(args, options);
 }
 
 } // !namespace
@@ -232,63 +234,62 @@
 // {{{ cli
 
 const std::vector<cli::constructor> cli::registry{
-    bind<plugin_config_cli>(),
-    bind<plugin_info_cli>(),
-    bind<plugin_list_cli>(),
-    bind<plugin_load_cli>(),
-    bind<plugin_reload_cli>(),
-    bind<plugin_unload_cli>(),
-    bind<rule_add_cli>(),
-    bind<rule_edit_cli>(),
-    bind<rule_info_cli>(),
-    bind<rule_info_cli>(),
-    bind<rule_list_cli>(),
-    bind<rule_move_cli>(),
-    bind<rule_remove_cli>(),
-    bind<server_connect_cli>(),
-    bind<server_disconnect_cli>(),
-    bind<server_info_cli>(),
-    bind<server_invite_cli>(),
-    bind<server_join_cli>(),
-    bind<server_kick_cli>(),
-    bind<server_list_cli>(),
-    bind<server_me_cli>(),
-    bind<server_message_cli>(),
-    bind<server_mode_cli>(),
-    bind<server_nick_cli>(),
-    bind<server_notice_cli>(),
-    bind<server_part_cli>(),
-    bind<server_reconnect_cli>(),
-    bind<server_topic_cli>(),
-    bind<watch_cli>()
+	bind<plugin_config_cli>(),
+	bind<plugin_info_cli>(),
+	bind<plugin_list_cli>(),
+	bind<plugin_load_cli>(),
+	bind<plugin_reload_cli>(),
+	bind<plugin_unload_cli>(),
+	bind<rule_add_cli>(),
+	bind<rule_edit_cli>(),
+	bind<rule_info_cli>(),
+	bind<rule_list_cli>(),
+	bind<rule_move_cli>(),
+	bind<rule_remove_cli>(),
+	bind<server_connect_cli>(),
+	bind<server_disconnect_cli>(),
+	bind<server_info_cli>(),
+	bind<server_invite_cli>(),
+	bind<server_join_cli>(),
+	bind<server_kick_cli>(),
+	bind<server_list_cli>(),
+	bind<server_me_cli>(),
+	bind<server_message_cli>(),
+	bind<server_mode_cli>(),
+	bind<server_nick_cli>(),
+	bind<server_notice_cli>(),
+	bind<server_part_cli>(),
+	bind<server_reconnect_cli>(),
+	bind<server_topic_cli>(),
+	bind<watch_cli>()
 };
 
 void cli::recv_response(ctl::controller& ctl, nlohmann::json req, handler_t handler)
 {
-    ctl.read([&ctl, req, handler, this] (auto code, auto message) {
-        if (code)
-            throw std::system_error(code);
+	ctl.read([&ctl, req, handler, this] (auto code, auto message) {
+		if (code)
+			throw std::system_error(code);
 
-        const auto c = json_util::document(message).get<std::string>("command");
+		const auto c = deserializer(message).get<std::string>("command");
 
-        if (!c) {
-            recv_response(ctl, std::move(req), std::move(handler));
-            return;
-        }
+		if (!c) {
+			recv_response(ctl, std::move(req), std::move(handler));
+			return;
+		}
 
-        if (handler)
-            handler(std::move(message));
-    });
+		if (handler)
+			handler(std::move(message));
+	});
 }
 
 void cli::request(ctl::controller& ctl, nlohmann::json req, handler_t handler)
 {
-    ctl.write(req, [&ctl, req, handler, this] (auto code) {
-        if (code)
-            throw std::system_error(code);
+	ctl.write(req, [&ctl, req, handler, this] (auto code) {
+		if (code)
+			throw std::system_error(code);
 
-        recv_response(ctl, std::move(req), std::move(handler));
-    });
+		recv_response(ctl, std::move(req), std::move(handler));
+	});
 }
 
 // }}}
@@ -297,63 +298,63 @@
 
 void plugin_config_cli::set(ctl::controller& ctl, const std::vector<std::string>&args)
 {
-    request(ctl, {
-        { "command",    "plugin-config" },
-        { "plugin",     args[0]         },
-        { "variable",   args[1]         },
-        { "value",      args[2]         }
-    });
+	request(ctl, {
+		{ "command",    "plugin-config" },
+		{ "plugin",     args[0]         },
+		{ "variable",   args[1]         },
+		{ "value",      args[2]         }
+	});
 }
 
 void plugin_config_cli::get(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    auto json = nlohmann::json::object({
-        { "command",    "plugin-config" },
-        { "plugin",     args[0]         },
-        { "variable",   args[1]         }
-    });
+	auto json = nlohmann::json::object({
+		{ "command",    "plugin-config" },
+		{ "plugin",     args[0]         },
+		{ "variable",   args[1]         }
+	});
 
-    request(ctl, std::move(json), [args] (auto result) {
-        if (result["variables"].is_object())
-            std::cout << json_util::pretty(result["variables"][args[1]]) << std::endl;
-    });
+	request(ctl, std::move(json), [args] (auto result) {
+		if (result["variables"].is_object())
+			std::cout << json_util::pretty(result["variables"][args[1]]) << std::endl;
+	});
 }
 
 void plugin_config_cli::getall(ctl::controller& ctl, const std::vector<std::string> &args)
 {
-    const auto json = nlohmann::json::object({
-        { "command",    "plugin-config" },
-        { "plugin",     args[0]         }
-    });
+	const auto json = nlohmann::json::object({
+		{ "command",    "plugin-config" },
+		{ "plugin",     args[0]         }
+	});
 
-    request(ctl, json, [] (auto result) {
-        const auto variables = result["variables"];
+	request(ctl, json, [] (auto result) {
+		const auto variables = result["variables"];
 
-        for (auto v = variables.begin(); v != variables.end(); ++v)
-            std::cout << std::setw(16) << std::left << v.key() << " : " << json_util::pretty(v.value()) << std::endl;
-    });
+		for (auto v = variables.begin(); v != variables.end(); ++v)
+			std::cout << std::setw(16) << std::left << v.key() << " : " << json_util::pretty(v.value()) << std::endl;
+	});
 }
 
 auto plugin_config_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-config";
+	return "plugin-config";
 }
 
 void plugin_config_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args)
 {
-    switch (args.size()) {
-    case 3:
-        set(ctl, args);
-        break;
-    case 2:
-        get(ctl, args);
-        break;
-    case 1:
-        getall(ctl, args);
-        break;
-    default:
-        throw std::invalid_argument("plugin-config requires at least 1 argument");
-    }
+	switch (args.size()) {
+	case 3:
+		set(ctl, args);
+		break;
+	case 2:
+		get(ctl, args);
+		break;
+	case 1:
+		getall(ctl, args);
+		break;
+	default:
+		throw std::invalid_argument("plugin-config requires at least 1 argument");
+	}
 }
 
 // }}}
@@ -362,32 +363,32 @@
 
 auto plugin_info_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-info";
+	return "plugin-info";
 }
 
 void plugin_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("plugin-info requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("plugin-info requires 1 argument");
 
-    const auto json = nlohmann::json::object({
-        { "command",    "plugin-info"   },
-        { "plugin",     args[0]         }
-    });
+	const auto json = nlohmann::json::object({
+		{ "command",    "plugin-info"   },
+		{ "plugin",     args[0]         }
+	});
 
-    request(ctl, json, [] (auto result) {
-        const json_util::document doc(result);
+	request(ctl, json, [] (auto result) {
+		const deserializer doc(result);
 
-        std::cout << std::boolalpha;
-        std::cout << "Author         : " <<
-            doc.get<std::string>("author").value_or("(unknown)") << std::endl;
-        std::cout << "License        : " <<
-            doc.get<std::string>("license").value_or("(unknown)") << std::endl;
-        std::cout << "Summary        : " <<
-            doc.get<std::string>("summary").value_or("(unknown)") << std::endl;
-        std::cout << "Version        : " <<
-            doc.get<std::string>("version").value_or("(unknown)") << std::endl;
-    });
+		std::cout << std::boolalpha;
+		std::cout << "Author         : "
+		          << doc.get<std::string>("author").value_or("(unknown)") << std::endl;
+		std::cout << "License        : "
+		          << doc.get<std::string>("license").value_or("(unknown)") << std::endl;
+		std::cout << "Summary        : "
+		          << doc.get<std::string>("summary").value_or("(unknown)") << std::endl;
+		std::cout << "Version        : "
+		          << doc.get<std::string>("version").value_or("(unknown)") << std::endl;
+	});
 }
 
 // }}}
@@ -396,16 +397,16 @@
 
 auto plugin_list_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-list";
+	return "plugin-list";
 }
 
 void plugin_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
 {
-    request(ctl, {{ "command", "plugin-list" }}, [] (auto result) {
-        for (const auto& value : result["list"])
-            if (value.is_string())
-                std::cout << value.template get<std::string>() << std::endl;
-    });
+	request(ctl, {{ "command", "plugin-list" }}, [] (auto result) {
+		for (const auto& value : result["list"])
+			if (value.is_string())
+				std::cout << value.template get<std::string>() << std::endl;
+	});
 }
 
 // }}}
@@ -414,18 +415,18 @@
 
 auto plugin_load_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-load";
+	return "plugin-load";
 }
 
 void plugin_load_cli::exec(ctl::controller& ctl, const std::vector<std::string> &args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("plugin-load requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("plugin-load requires 1 argument");
 
-    request(ctl, {
-        { "command",    "plugin-load"   },
-        { "plugin",     args[0]         }
-    });
+	request(ctl, {
+		{ "command",    "plugin-load"   },
+		{ "plugin",     args[0]         }
+	});
 }
 
 // }}}
@@ -434,18 +435,18 @@
 
 auto plugin_reload_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-reload";
+	return "plugin-reload";
 }
 
 void plugin_reload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("plugin-reload requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("plugin-reload requires 1 argument");
 
-    request(ctl, {
-        { "command",    "plugin-reload" },
-        { "plugin",     args[0]         }
-    });
+	request(ctl, {
+		{ "command",    "plugin-reload" },
+		{ "plugin",     args[0]         }
+	});
 }
 
 // }}}
@@ -454,18 +455,18 @@
 
 auto plugin_unload_cli::get_name() const noexcept -> std::string_view
 {
-    return "plugin-unload";
+	return "plugin-unload";
 }
 
 void plugin_unload_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("plugin-unload requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("plugin-unload requires 1 argument");
 
-    request(ctl, {
-        { "command",    "plugin-unload" },
-        { "plugin",     args[0]         }
-    });
+	request(ctl, {
+		{ "command",    "plugin-unload" },
+		{ "plugin",     args[0]         }
+	});
 }
 
 // }}}
@@ -474,64 +475,64 @@
 
 auto rule_add_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-add";
+	return "rule-add";
 }
 
 void rule_add_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    static const option::options options{
-        { "-c",             true },
-        { "--add-channel",  true },
-        { "-e",             true },
-        { "--add-event",    true },
-        { "-i",             true },
-        { "--index",        true },
-        { "-p",             true },
-        { "--add-plugin",   true },
-        { "-s",             true },
-        { "--add-server",   true }
-    };
+	static const option::options options{
+		{ "-c",                 true },
+		{ "--add-channel",      true },
+		{ "-e",                 true },
+		{ "--add-event",        true },
+		{ "-i",                 true },
+		{ "--index",            true },
+		{ "-p",                 true },
+		{ "--add-plugin",       true },
+		{ "-s",                 true },
+		{ "--add-server",       true }
+	};
 
-    auto copy = args;
-    auto result = option::read(copy, options);
+	auto copy = args;
+	auto result = option::read(copy, options);
 
-    if (copy.size() < 1)
-        throw std::invalid_argument("rule-add requires at least 1 argument");
+	if (copy.size() < 1)
+		throw std::invalid_argument("rule-add requires at least 1 argument");
 
-    auto json = nlohmann::json::object({
-        { "command",    "rule-add"              },
-        { "channels",   nlohmann::json::array() },
-        { "events",     nlohmann::json::array() },
-        { "plugins",    nlohmann::json::array() },
-        { "servers",    nlohmann::json::array() }
-    });
+	auto json = nlohmann::json::object({
+		{ "command",    "rule-add"              },
+		{ "channels",   nlohmann::json::array() },
+		{ "events",     nlohmann::json::array() },
+		{ "plugins",    nlohmann::json::array() },
+		{ "servers",    nlohmann::json::array() }
+	});
 
-    // All sets.
-    for (const auto& pair : result) {
-        if (pair.first == "-c" || pair.first == "--add-channel")
-            json["channels"].push_back(pair.second);
-        if (pair.first == "-e" || pair.first == "--add-event")
-            json["events"].push_back(pair.second);
-        if (pair.first == "-p" || pair.first == "--add-plugin")
-            json["plugins"].push_back(pair.second);
-        if (pair.first == "-s" || pair.first == "--add-server")
-            json["servers"].push_back(pair.second);
-    }
+	// All sets.
+	for (const auto& pair : result) {
+		if (pair.first == "-c" || pair.first == "--add-channel")
+			json["channels"].push_back(pair.second);
+		if (pair.first == "-e" || pair.first == "--add-event")
+			json["events"].push_back(pair.second);
+		if (pair.first == "-p" || pair.first == "--add-plugin")
+			json["plugins"].push_back(pair.second);
+		if (pair.first == "-s" || pair.first == "--add-server")
+			json["servers"].push_back(pair.second);
+	}
 
-    // Index.
-    std::optional<unsigned> index;
+	// Index.
+	std::optional<unsigned> index;
 
-    if (result.count("-i") > 0 && !(index = string_util::to_uint(result.find("-i")->second)))
-        throw std::invalid_argument("invalid index argument");
-    if (result.count("--index") > 0 && !(index = string_util::to_uint(result.find("--index")->second)))
-        throw std::invalid_argument("invalid index argument");
+	if (result.count("-i") > 0 && !(index = string_util::to_uint(result.find("-i")->second)))
+		throw std::invalid_argument("invalid index argument");
+	if (result.count("--index") > 0 && !(index = string_util::to_uint(result.find("--index")->second)))
+		throw std::invalid_argument("invalid index argument");
 
-    if (index)
-        json["index"] = *index;
+	if (index)
+		json["index"] = *index;
 
-    json["action"] = copy[0];
+	json["action"] = copy[0];
 
-    request(ctl, json);
+	request(ctl, json);
 }
 
 // }}}
@@ -540,81 +541,81 @@
 
 auto rule_edit_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-edit";
+	return "rule-edit";
 }
 
 void rule_edit_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    static const option::options options{
-        { "-a",                 true },
-        { "--action",           true },
-        { "-c",                 true },
-        { "--add-channel",      true },
-        { "-C",                 true },
-        { "--remove-channel",   true },
-        { "-e",                 true },
-        { "--add-event",        true },
-        { "-E",                 true },
-        { "--remove-event",     true },
-        { "-p",                 true },
-        { "--add-plugin",       true },
-        { "-P",                 true },
-        { "--remove-plugin",    true },
-        { "-s",                 true },
-        { "--add-server",       true },
-        { "-S",                 true },
-        { "--remove-server",    true },
-    };
+	static const option::options options{
+		{ "-a",                 true },
+		{ "--action",           true },
+		{ "-c",                 true },
+		{ "--add-channel",      true },
+		{ "-C",                 true },
+		{ "--remove-channel",   true },
+		{ "-e",                 true },
+		{ "--add-event",        true },
+		{ "-E",                 true },
+		{ "--remove-event",     true },
+		{ "-p",                 true },
+		{ "--add-plugin",       true },
+		{ "-P",                 true },
+		{ "--remove-plugin",    true },
+		{ "-s",                 true },
+		{ "--add-server",       true },
+		{ "-S",                 true },
+		{ "--remove-server",    true },
+	};
 
-    auto copy = args;
-    auto result = option::read(copy, options);
+	auto copy = args;
+	auto result = option::read(copy, options);
 
-    if (copy.size() < 1)
-        throw std::invalid_argument("rule-edit requires at least 1 argument");
+	if (copy.size() < 1)
+		throw std::invalid_argument("rule-edit requires at least 1 argument");
 
-    auto json = nlohmann::json::object({
-        { "command",    "rule-edit"             },
-        { "channels",   nlohmann::json::array() },
-        { "events",     nlohmann::json::array() },
-        { "plugins",    nlohmann::json::array() },
-        { "servers",    nlohmann::json::array() }
-    });
+	auto json = nlohmann::json::object({
+		{ "command",    "rule-edit"             },
+		{ "channels",   nlohmann::json::array() },
+		{ "events",     nlohmann::json::array() },
+		{ "plugins",    nlohmann::json::array() },
+		{ "servers",    nlohmann::json::array() }
+	});
 
-    for (const auto& pair : result) {
-        // Action.
-        if (pair.first == "-a" || pair.first == "--action")
-            json["action"] = pair.second;
+	for (const auto& pair : result) {
+		// Action.
+		if (pair.first == "-a" || pair.first == "--action")
+			json["action"] = pair.second;
 
-        // Additions.
-        if (pair.first == "-c" || pair.first == "--add-channel")
-            json["add-channels"].push_back(pair.second);
-        if (pair.first == "-e" || pair.first == "--add-event")
-            json["add-events"].push_back(pair.second);
-        if (pair.first == "-p" || pair.first == "--add-plugin")
-            json["add-plugins"].push_back(pair.second);
-        if (pair.first == "-s" || pair.first == "--add-server")
-            json["add-servers"].push_back(pair.second);
+		// Additions.
+		if (pair.first == "-c" || pair.first == "--add-channel")
+			json["add-channels"].push_back(pair.second);
+		if (pair.first == "-e" || pair.first == "--add-event")
+			json["add-events"].push_back(pair.second);
+		if (pair.first == "-p" || pair.first == "--add-plugin")
+			json["add-plugins"].push_back(pair.second);
+		if (pair.first == "-s" || pair.first == "--add-server")
+			json["add-servers"].push_back(pair.second);
 
-        // Removals.
-        if (pair.first == "-C" || pair.first == "--remove-channel")
-            json["remove-channels"].push_back(pair.second);
-        if (pair.first == "-E" || pair.first == "--remove-event")
-            json["remove-events"].push_back(pair.second);
-        if (pair.first == "-P" || pair.first == "--remove-plugin")
-            json["remove-plugins"].push_back(pair.second);
-        if (pair.first == "-S" || pair.first == "--remove-server")
-            json["remove-servers"].push_back(pair.second);
-    }
+		// Removals.
+		if (pair.first == "-C" || pair.first == "--remove-channel")
+			json["remove-channels"].push_back(pair.second);
+		if (pair.first == "-E" || pair.first == "--remove-event")
+			json["remove-events"].push_back(pair.second);
+		if (pair.first == "-P" || pair.first == "--remove-plugin")
+			json["remove-plugins"].push_back(pair.second);
+		if (pair.first == "-S" || pair.first == "--remove-server")
+			json["remove-servers"].push_back(pair.second);
+	}
 
-    // Index.
-    const auto index = string_util::to_uint(copy[0]);
+	// Index.
+	const auto index = string_util::to_uint(copy[0]);
 
-    if (!index)
-        throw rule_error(rule_error::invalid_index);
+	if (!index)
+		throw rule_error(rule_error::invalid_index);
 
-    json["index"] = *index;
+	json["index"] = *index;
 
-    request(ctl, json);
+	request(ctl, json);
 }
 
 // }}}
@@ -623,59 +624,59 @@
 
 void rule_info_cli::print(const nlohmann::json& json, int index)
 {
-    assert(json.is_object());
+	assert(json.is_object());
 
-    const auto unjoin = [] (auto array) {
-        std::ostringstream oss;
+	const auto unjoin = [] (auto array) {
+		std::ostringstream oss;
 
-        for (auto it = array.begin(); it != array.end(); ++it) {
-            if (!it->is_string())
-                continue;
+		for (auto it = array.begin(); it != array.end(); ++it) {
+			if (!it->is_string())
+				continue;
 
-            oss << it->template get<std::string>() << " ";
-        }
+			oss << it->template get<std::string>() << " ";
+		}
 
-        return oss.str();
-    };
-    const auto unstr = [] (auto action) {
-        if (action.is_string() && action == "accept")
-            return "accept";
-        else
-            return "drop";
-    };
+		return oss.str();
+	};
+	const auto unstr = [] (auto action) {
+		if (action.is_string() && action == "accept")
+			return "accept";
+		else
+			return "drop";
+	};
 
-    std::cout << "rule:        " << index << std::endl;
-    std::cout << "servers:     " << unjoin(json["servers"]) << std::endl;
-    std::cout << "channels:    " << unjoin(json["channels"]) << std::endl;
-    std::cout << "plugins:     " << unjoin(json["plugins"]) << std::endl;
-    std::cout << "events:      " << unjoin(json["events"]) << std::endl;
-    std::cout << "action:      " << unstr(json["action"]) << std::endl;
-    std::cout << std::endl;
+	std::cout << "rule:        " << index << std::endl;
+	std::cout << "servers:     " << unjoin(json["servers"]) << std::endl;
+	std::cout << "channels:    " << unjoin(json["channels"]) << std::endl;
+	std::cout << "plugins:     " << unjoin(json["plugins"]) << std::endl;
+	std::cout << "events:      " << unjoin(json["events"]) << std::endl;
+	std::cout << "action:      " << unstr(json["action"]) << std::endl;
+	std::cout << std::endl;
 }
 
 auto rule_info_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-info";
+	return "rule-info";
 }
 
 void rule_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("rule-info requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("rule-info requires 1 argument");
 
-    const auto index = string_util::to_int(args[0]);
+	const auto index = string_util::to_int(args[0]);
 
-    if (!index)
-        throw rule_error(rule_error::invalid_index);
+	if (!index)
+		throw rule_error(rule_error::invalid_index);
 
-    const auto json = nlohmann::json::object({
-        { "command",    "rule-info" },
-        { "index",      *index      }
-    });
+	const auto json = nlohmann::json::object({
+		{ "command",    "rule-info"     },
+		{ "index",      *index          }
+	});
 
-    request(ctl, json, [index] (auto result) {
-        print(result, *index);
-    });
+	request(ctl, json, [index] (auto result) {
+		print(result, *index);
+	});
 }
 
 // }}}
@@ -684,19 +685,18 @@
 
 auto rule_list_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-list";
+	return "rule-list";
 }
 
 void rule_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
 {
-    request(ctl, {{ "command", "rule-list" }}, [] (auto result) {
-        auto pos = 0;
+	request(ctl, {{ "command", "rule-list" }}, [] (auto result) {
+		auto pos = 0;
 
-        for (const auto& obj : result["list"]) {
-            if (obj.is_object())
-                rule_info_cli::print(obj, pos++);
-        }
-    });
+		for (const auto& obj : result["list"])
+			if (obj.is_object())
+				rule_info_cli::print(obj, pos++);
+	});
 }
 
 // }}}
@@ -705,27 +705,27 @@
 
 auto rule_move_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-move";
+	return "rule-move";
 }
 
 void rule_move_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 2)
-        throw std::invalid_argument("rule-move requires 2 arguments");
+	if (args.size() < 2)
+		throw std::invalid_argument("rule-move requires 2 arguments");
 
-    const auto from = string_util::to_int<int>(args[0]);
-    const auto to = string_util::to_int<int>(args[1]);
+	const auto from = string_util::to_int<int>(args[0]);
+	const auto to = string_util::to_int<int>(args[1]);
 
-    if (!from)
-        throw rule_error(rule_error::invalid_index);
-    if (!to)
-        throw rule_error(rule_error::invalid_index);
+	if (!from)
+		throw rule_error(rule_error::invalid_index);
+	if (!to)
+		throw rule_error(rule_error::invalid_index);
 
-    request(ctl, {
-        { "command",    "rule-move" },
-        { "from",       *from       },
-        { "to",         *to         }
-    });
+	request(ctl, {
+		{ "command",    "rule-move"     },
+		{ "from",       *from           },
+		{ "to",         *to             }
+	});
 }
 
 // }}}
@@ -734,23 +734,23 @@
 
 auto rule_remove_cli::get_name() const noexcept -> std::string_view
 {
-    return "rule-remove";
+	return "rule-remove";
 }
 
 void rule_remove_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("rule-remove requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("rule-remove requires 1 argument");
 
-    const auto index = string_util::to_int(args[0]);
+	const auto index = string_util::to_int(args[0]);
 
-    if (!index)
-        throw rule_error(rule_error::invalid_index);
+	if (!index)
+		throw rule_error(rule_error::invalid_index);
 
-    request(ctl, {
-        { "command",    "rule-remove"   },
-        { "index",      *index          }
-    });
+	request(ctl, {
+		{ "command",    "rule-remove"   },
+		{ "index",      *index          }
+	});
 }
 
 // }}}
@@ -759,46 +759,46 @@
 
 auto server_connect_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-connect";
+	return "server-connect";
 }
 
 void server_connect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    std::vector<std::string> copy(args);
+	std::vector<std::string> copy(args);
 
-    option::result result = parse(copy);
-    option::result::const_iterator it;
+	option::result result = parse(copy);
+	option::result::const_iterator it;
 
-    if (copy.size() < 2)
-        throw std::invalid_argument("server-connect requires at least 2 arguments");
+	if (copy.size() < 2)
+		throw std::invalid_argument("server-connect requires at least 2 arguments");
 
-    auto object = nlohmann::json::object({
-        { "command",    "server-connect"    },
-        { "name",       copy[0]             },
-        { "host",       copy[1]             }
-    });
+	auto object = nlohmann::json::object({
+		{ "command",    "server-connect"        },
+		{ "name",       copy[0]                 },
+		{ "host",       copy[1]                 }
+	});
 
-    if (copy.size() == 3) {
-        const auto port = string_util::to_int(copy[2]);
+	if (copy.size() == 3) {
+		const auto port = string_util::to_int(copy[2]);
 
-        if (!port)
-            throw std::invalid_argument("invalid port given");
+		if (!port)
+			throw std::invalid_argument("invalid port given");
 
-        object["port"] = *port;
-    }
+		object["port"] = *port;
+	}
 
-    if (result.count("-S") > 0 || result.count("--ssl-verify") > 0)
-        object["sslVerify"] = true;
-    if (result.count("-s") > 0 || result.count("--ssl") > 0)
-        object["ssl"] = true;
-    if ((it = result.find("-n")) != result.end() || (it = result.find("--nickname")) != result.end())
-        object["nickname"] = it->second;
-    if ((it = result.find("-r")) != result.end() || (it = result.find("--realname")) != result.end())
-        object["realname"] = it->second;
-    if ((it = result.find("-u")) != result.end() || (it = result.find("--username")) != result.end())
-        object["username"] = it->second;
+	if (result.count("-S") > 0 || result.count("--ssl-verify") > 0)
+		object["sslVerify"] = true;
+	if (result.count("-s") > 0 || result.count("--ssl") > 0)
+		object["ssl"] = true;
+	if ((it = result.find("-n")) != result.end() || (it = result.find("--nickname")) != result.end())
+		object["nickname"] = it->second;
+	if ((it = result.find("-r")) != result.end() || (it = result.find("--realname")) != result.end())
+		object["realname"] = it->second;
+	if ((it = result.find("-u")) != result.end() || (it = result.find("--username")) != result.end())
+		object["username"] = it->second;
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -807,19 +807,19 @@
 
 auto server_disconnect_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-disconnect";
+	return "server-disconnect";
 }
 
 void server_disconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    auto object = nlohmann::json::object({
-        { "command", "server-disconnect" }
-    });
+	auto object = nlohmann::json::object({
+		{ "command", "server-disconnect" }
+	});
 
-    if (args.size() > 0)
-        object["server"] = args[0];
+	if (args.size() > 0)
+		object["server"] = args[0];
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -828,39 +828,39 @@
 
 auto server_info_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-info";
+	return "server-info";
 }
 
 void server_info_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 1)
-        throw std::invalid_argument("server-info requires 1 argument");
+	if (args.size() < 1)
+		throw std::invalid_argument("server-info requires 1 argument");
 
-    auto json = nlohmann::json::object({
-        { "command",    "server-info"   },
-        { "server",     args[0]         }
-    });
+	auto json = nlohmann::json::object({
+		{ "command",    "server-info"   },
+		{ "server",     args[0]         }
+	});
 
-    request(ctl, std::move(json), [] (auto result) {
-        std::cout << std::boolalpha;
-        std::cout << "Name           : " << json_util::pretty(result["name"]) << std::endl;
-        std::cout << "Host           : " << json_util::pretty(result["host"]) << std::endl;
-        std::cout << "Port           : " << json_util::pretty(result["port"]) << std::endl;
-        std::cout << "Ipv6           : " << json_util::pretty(result["ipv6"]) << std::endl;
-        std::cout << "SSL            : " << json_util::pretty(result["ssl"]) << std::endl;
-        std::cout << "SSL verified   : " << json_util::pretty(result["sslVerify"]) << std::endl;
-        std::cout << "Channels       : ";
+	request(ctl, std::move(json), [] (auto result) {
+		std::cout << std::boolalpha;
+		std::cout << "Name           : " << json_util::pretty(result["name"]) << std::endl;
+		std::cout << "Host           : " << json_util::pretty(result["host"]) << std::endl;
+		std::cout << "Port           : " << json_util::pretty(result["port"]) << std::endl;
+		std::cout << "Ipv6           : " << json_util::pretty(result["ipv6"]) << std::endl;
+		std::cout << "SSL            : " << json_util::pretty(result["ssl"]) << std::endl;
+		std::cout << "SSL verified   : " << json_util::pretty(result["sslVerify"]) << std::endl;
+		std::cout << "Channels       : ";
 
-        for (const auto& v : result["channels"])
-            if (v.is_string())
-                std::cout << v.template get<std::string>() << " ";
+		for (const auto& v : result["channels"])
+			if (v.is_string())
+				std::cout << v.template get<std::string>() << " ";
 
-        std::cout << std::endl;
+		std::cout << std::endl;
 
-        std::cout << "Nickname       : " << json_util::pretty(result["nickname"]) << std::endl;
-        std::cout << "User name      : " << json_util::pretty(result["username"]) << std::endl;
-        std::cout << "Real name      : " << json_util::pretty(result["realname"]) << std::endl;
-    });
+		std::cout << "Nickname       : " << json_util::pretty(result["nickname"]) << std::endl;
+		std::cout << "User name      : " << json_util::pretty(result["username"]) << std::endl;
+		std::cout << "Real name      : " << json_util::pretty(result["realname"]) << std::endl;
+	});
 }
 
 // }}}
@@ -869,20 +869,20 @@
 
 auto server_invite_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-invite";
+	return "server-invite";
 }
 
 void server_invite_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::invalid_argument("server-invite requires 3 arguments");
+	if (args.size() < 3)
+		throw std::invalid_argument("server-invite requires 3 arguments");
 
-    request(ctl, {
-        { "command",    "server-invite" },
-        { "server",     args[0]         },
-        { "target",     args[1]         },
-        { "channel",    args[2]         }
-    });
+	request(ctl, {
+		{ "command",    "server-invite" },
+		{ "server",     args[0]         },
+		{ "target",     args[1]         },
+		{ "channel",    args[2]         }
+	});
 }
 
 // }}}
@@ -891,24 +891,24 @@
 
 auto server_join_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-join";
+	return "server-join";
 }
 
 void server_join_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 2)
-        throw std::invalid_argument("server-join requires at least 2 arguments");
+	if (args.size() < 2)
+		throw std::invalid_argument("server-join requires at least 2 arguments");
 
-    auto object = nlohmann::json::object({
-        { "command",    "server-join"   },
-        { "server",     args[0]         },
-        { "channel",    args[1]         }
-    });
+	auto object = nlohmann::json::object({
+		{ "command",    "server-join"   },
+		{ "server",     args[0]         },
+		{ "channel",    args[1]         }
+	});
 
-    if (args.size() == 3)
-        object["password"] = args[2];
+	if (args.size() == 3)
+		object["password"] = args[2];
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -917,25 +917,25 @@
 
 auto server_kick_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-kick";
+	return "server-kick";
 }
 
 void server_kick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::invalid_argument("server-kick requires at least 3 arguments ");
+	if (args.size() < 3)
+		throw std::invalid_argument("server-kick requires at least 3 arguments ");
 
-    auto object = nlohmann::json::object({
-        { "command",    "server-kick"   },
-        { "server",     args[0]         },
-        { "target",     args[1]         },
-        { "channel",    args[2]         }
-    });
+	auto object = nlohmann::json::object({
+		{ "command",    "server-kick"   },
+		{ "server",     args[0]         },
+		{ "target",     args[1]         },
+		{ "channel",    args[2]         }
+	});
 
-    if (args.size() == 4)
-        object["reason"] = args[3];
+	if (args.size() == 4)
+		object["reason"] = args[3];
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -944,16 +944,16 @@
 
 auto server_list_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-list";
+	return "server-list";
 }
 
 void server_list_cli::exec(ctl::controller& ctl, const std::vector<std::string>&)
 {
-    request(ctl, {{ "command", "server-list" }}, [] (auto result) {
-        for (const auto& n : result["list"])
-            if (n.is_string())
-                std::cout << n.template get<std::string>() << std::endl;
-    });
+	request(ctl, {{ "command", "server-list" }}, [] (auto result) {
+		for (const auto& n : result["list"])
+			if (n.is_string())
+				std::cout << n.template get<std::string>() << std::endl;
+	});
 }
 
 // }}}
@@ -962,20 +962,20 @@
 
 auto server_me_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-me";
+	return "server-me";
 }
 
 void server_me_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::runtime_error("server-me requires 3 arguments");
+	if (args.size() < 3)
+		throw std::runtime_error("server-me requires 3 arguments");
 
-    request(ctl, {
-        { "command",    "server-me" },
-        { "server",     args[0]     },
-        { "target",     args[1]     },
-        { "message",    args[2]     }
-    });
+	request(ctl, {
+		{ "command",    "server-me"     },
+		{ "server",     args[0]         },
+		{ "target",     args[1]         },
+		{ "message",    args[2]         }
+	});
 }
 
 // }}}
@@ -984,20 +984,20 @@
 
 auto server_message_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-message";
+	return "server-message";
 }
 
 void server_message_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::invalid_argument("server-message requires 3 arguments");
+	if (args.size() < 3)
+		throw std::invalid_argument("server-message requires 3 arguments");
 
-    request(ctl, {
-        { "command",    "server-message"    },
-        { "server",     args[0]             },
-        { "target",     args[1]             },
-        { "message",    args[2]             }
-    });
+	request(ctl, {
+		{ "command",    "server-message"        },
+		{ "server",     args[0]                 },
+		{ "target",     args[1]                 },
+		{ "message",    args[2]                 }
+	});
 }
 
 // }}}
@@ -1006,29 +1006,29 @@
 
 auto server_mode_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-mode";
+	return "server-mode";
 }
 
 void server_mode_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 2)
-        throw std::invalid_argument("server-mode requires at least 3 arguments");
+	if (args.size() < 2)
+		throw std::invalid_argument("server-mode requires at least 3 arguments");
 
-    auto json = nlohmann::json({
-        { "command",    "server-mode"   },
-        { "server",     args[0]         },
-        { "channel",    args[1]         },
-        { "mode",       args[2]         }
-    });
+	auto json = nlohmann::json({
+		{ "command",    "server-mode"   },
+		{ "server",     args[0]         },
+		{ "channel",    args[1]         },
+		{ "mode",       args[2]         }
+	});
 
-    if (args.size() >= 4)
-        json["limit"] = args[3];
-    if (args.size() >= 5)
-        json["user"] = args[4];
-    if (args.size() >= 6)
-        json["mask"] = args[5];
+	if (args.size() >= 4)
+		json["limit"] = args[3];
+	if (args.size() >= 5)
+		json["user"] = args[4];
+	if (args.size() >= 6)
+		json["mask"] = args[5];
 
-    request(ctl, std::move(json));
+	request(ctl, std::move(json));
 }
 
 // }}}
@@ -1037,19 +1037,19 @@
 
 auto server_nick_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-nick";
+	return "server-nick";
 }
 
 void server_nick_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 2)
-        throw std::invalid_argument("server-nick requires 2 arguments");
+	if (args.size() < 2)
+		throw std::invalid_argument("server-nick requires 2 arguments");
 
-    request(ctl, {
-        { "command",    "server-nick"   },
-        { "server",     args[0]         },
-        { "nickname",   args[1]         }
-    });
+	request(ctl, {
+		{ "command",    "server-nick"   },
+		{ "server",     args[0]         },
+		{ "nickname",   args[1]         }
+	});
 }
 
 // }}}
@@ -1058,20 +1058,20 @@
 
 auto server_notice_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-notice";
+	return "server-notice";
 }
 
 void server_notice_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::invalid_argument("server-notice requires 3 arguments");
+	if (args.size() < 3)
+		throw std::invalid_argument("server-notice requires 3 arguments");
 
-    request(ctl, {
-        { "command",    "server-notice" },
-        { "server",     args[0]         },
-        { "target",     args[1]         },
-        { "message",    args[2]         }
-    });
+	request(ctl, {
+		{ "command",    "server-notice" },
+		{ "server",     args[0]         },
+		{ "target",     args[1]         },
+		{ "message",    args[2]         }
+	});
 }
 
 // }}}
@@ -1080,24 +1080,24 @@
 
 auto server_part_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-part";
+	return "server-part";
 }
 
 void server_part_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 2)
-        throw std::invalid_argument("server-part requires at least 2 arguments");
+	if (args.size() < 2)
+		throw std::invalid_argument("server-part requires at least 2 arguments");
 
-    auto object = nlohmann::json::object({
-        { "command",    "server-part"   },
-        { "server",     args[0]         },
-        { "channel",    args[1]         }
-    });
+	auto object = nlohmann::json::object({
+		{ "command",    "server-part"   },
+		{ "server",     args[0]         },
+		{ "channel",    args[1]         }
+	});
 
-    if (args.size() >= 3)
-        object["reason"] = args[2];
+	if (args.size() >= 3)
+		object["reason"] = args[2];
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -1106,19 +1106,19 @@
 
 auto server_reconnect_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-reconnect";
+	return "server-reconnect";
 }
 
 void server_reconnect_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    auto object = nlohmann::json::object({
-        { "command", "server-reconnect" }
-    });
+	auto object = nlohmann::json::object({
+		{ "command", "server-reconnect" }
+	});
 
-    if (args.size() >= 1)
-        object["server"] = args[0];
+	if (args.size() >= 1)
+		object["server"] = args[0];
 
-    request(ctl, object);
+	request(ctl, object);
 }
 
 // }}}
@@ -1127,20 +1127,20 @@
 
 auto server_topic_cli::get_name() const noexcept -> std::string_view
 {
-    return "server-topic";
+	return "server-topic";
 }
 
 void server_topic_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    if (args.size() < 3)
-        throw std::invalid_argument("server-topic requires 3 arguments");
+	if (args.size() < 3)
+		throw std::invalid_argument("server-topic requires 3 arguments");
 
-    request(ctl, {
-        { "command",    "server-topic"  },
-        { "server",     args[0]         },
-        { "channel",    args[1]         },
-        { "topic",      args[2]         }
-    });
+	request(ctl, {
+		{ "command",    "server-topic"  },
+		{ "server",     args[0]         },
+		{ "channel",    args[1]         },
+		{ "topic",      args[2]         }
+	});
 }
 
 // }}}
@@ -1149,17 +1149,17 @@
 
 auto watch_cli::get_name() const noexcept -> std::string_view
 {
-    return "watch";
+	return "watch";
 }
 
 void watch_cli::exec(ctl::controller& ctl, const std::vector<std::string>& args)
 {
-    auto fmt = format(args);
+	const auto fmt = format(args);
 
-    if (fmt != "native" && fmt != "json")
-        throw std::invalid_argument("invalid format given: " + fmt);
+	if (fmt != "native" && fmt != "json")
+		throw std::invalid_argument("invalid format given: " + fmt);
 
-    get_event(ctl, fmt);
+	get_event(ctl, fmt);
 }
 
 // }}}
--- a/irccdctl/cli.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/cli.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,69 +38,69 @@
  */
 class cli {
 public:
-    /**
-     * \brief Convenient handler for request function.
-     */
-    using handler_t = std::function<void (nlohmann::json)>;
+	/**
+	 * \brief Convenient handler for request function.
+	 */
+	using handler_t = std::function<void (nlohmann::json)>;
 
-    /**
-     * \brief Command constructor factory.
-     */
-    using constructor = std::function<auto () -> std::unique_ptr<cli>>;
+	/**
+	 * \brief Command constructor factory.
+	 */
+	using constructor = std::function<auto () -> std::unique_ptr<cli>>;
 
-    /**
-     * \brief Registry of all commands.
-     */
-    static const std::vector<constructor> registry;
+	/**
+	 * \brief Registry of all commands.
+	 */
+	static const std::vector<constructor> registry;
 
 private:
-    void recv_response(ctl::controller&, nlohmann::json, handler_t);
+	void recv_response(ctl::controller&, nlohmann::json, handler_t);
 
 protected:
-    /**
-     * Convenient request helper.
-     *
-     * This function send and receive the response for the given request. It
-     * checks for an error code or string in the command result and throws it if
-     * any.
-     *
-     * If handler is not null, it will be called once the command result has
-     * been received.
-     *
-     * This function may executes successive read calls until we get the
-     * response.
-     *
-     * \param ctl the controller
-     * \param json the json object
-     * \param handler the optional handler
-     */
-    void request(ctl::controller& ctl, nlohmann::json json, handler_t handler = nullptr);
+	/**
+	 * Convenient request helper.
+	 *
+	 * This function send and receive the response for the given request. It
+	 * checks for an error code or string in the command result and throws it if
+	 * any.
+	 *
+	 * If handler is not null, it will be called once the command result has
+	 * been received.
+	 *
+	 * This function may executes successive read calls until we get the
+	 * response.
+	 *
+	 * \param ctl the controller
+	 * \param json the json object
+	 * \param handler the optional handler
+	 */
+	void request(ctl::controller& ctl, nlohmann::json json, handler_t handler = nullptr);
 
 public:
-    /**
-     * Default constructor.
-     */
-    cli() noexcept = default;
+	/**
+	 * Default constructor.
+	 */
+	cli() noexcept = default;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~cli() noexcept = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~cli() noexcept = default;
 
-    /**
-     * Return the command name.
-     *
-     * \return the name
-     */
-    virtual auto get_name() const noexcept -> std::string_view = 0;
+	/**
+	 * Return the command name.
+	 *
+	 * \return the name
+	 */
+	virtual auto get_name() const noexcept -> std::string_view = 0;
 
-    /**
-     * Execute the command.
-     *
-     * \param ctl the controller
-     * \param args the user arguments
-     */
-    virtual void exec(ctl::controller& ctl, const std::vector<std::string>& args) = 0;
+	/**
+	 * Execute the command.
+	 *
+	 * \param ctl the controller
+	 * \param args the user arguments
+	 */
+	virtual void exec(ctl::controller& ctl, const std::vector<std::string>& args) = 0;
 };
 
 // }}}
@@ -112,20 +112,20 @@
  */
 class plugin_config_cli : public cli {
 private:
-    void set(ctl::controller&, const std::vector<std::string>&);
-    void get(ctl::controller&, const std::vector<std::string>&);
-    void getall(ctl::controller&, const std::vector<std::string>&);
+	void set(ctl::controller&, const std::vector<std::string>&);
+	void get(ctl::controller&, const std::vector<std::string>&);
+	void getall(ctl::controller&, const std::vector<std::string>&);
 
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -137,15 +137,15 @@
  */
 class plugin_info_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -157,15 +157,15 @@
  */
 class plugin_list_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -177,15 +177,15 @@
  */
 class plugin_load_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -197,15 +197,15 @@
  */
 class plugin_reload_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -217,15 +217,15 @@
  */
 class plugin_unload_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -237,15 +237,15 @@
  */
 class rule_add_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -257,15 +257,15 @@
  */
 class rule_edit_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -277,23 +277,23 @@
  */
 class rule_info_cli : public cli {
 public:
-    /**
-     * Pretty print a rule to stdout.
-     *
-     * \param json the rule information
-     * \param index the rule index
-     */
-    static void print(const nlohmann::json& json, int index = 0);
+	/**
+	 * Pretty print a rule to stdout.
+	 *
+	 * \param json the rule information
+	 * \param index the rule index
+	 */
+	static void print(const nlohmann::json& json, int index = 0);
 
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -305,15 +305,15 @@
  */
 class rule_list_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -325,15 +325,15 @@
  */
 class rule_move_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -345,15 +345,15 @@
  */
 class rule_remove_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -365,15 +365,15 @@
  */
 class server_connect_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -385,15 +385,15 @@
  */
 class server_disconnect_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -405,15 +405,15 @@
  */
 class server_info_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -425,15 +425,15 @@
  */
 class server_invite_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -445,15 +445,15 @@
  */
 class server_join_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -465,15 +465,15 @@
  */
 class server_kick_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -485,15 +485,15 @@
  */
 class server_list_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -505,15 +505,15 @@
  */
 class server_me_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -525,15 +525,15 @@
  */
 class server_message_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -545,15 +545,15 @@
  */
 class server_mode_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -565,15 +565,15 @@
  */
 class server_nick_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -585,15 +585,15 @@
  */
 class server_notice_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -605,15 +605,15 @@
  */
 class server_part_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -625,15 +625,15 @@
  */
 class server_reconnect_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -645,15 +645,15 @@
  */
 class server_topic_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
@@ -665,15 +665,15 @@
  */
 class watch_cli : public cli {
 public:
-    /**
-     * \copydoc cli::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc cli::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc cli::exec
-     */
-    void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
+	/**
+	 * \copydoc cli::exec
+	 */
+	void exec(ctl::controller& irccdctl, const std::vector<std::string>& args) override;
 };
 
 // }}}
--- a/irccdctl/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/irccdctl/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+// TODO: don't create a temporary list of endpoints.
+
 #include <irccd/sysconfig.hpp>
 
 #include <iostream>
@@ -33,7 +35,7 @@
 #include <irccd/system.hpp>
 
 #if defined(IRCCD_HAVE_SSL)
-#   include <irccd/tls_connector.hpp>
+#	include <irccd/tls_connector.hpp>
 #endif
 
 #include <irccd/daemon/transport_server.hpp>
@@ -80,7 +82,7 @@
 
 void usage()
 {
-    std::exit(1);
+	std::exit(1);
 }
 
 /*
@@ -89,17 +91,17 @@
  *
  * Block unless host/port has been resolved.
  */
-std::vector<tcp::endpoint> resolve(const std::string& host, const std::string& name)
+auto resolve(const std::string& host, const std::string& name) -> std::vector<tcp::endpoint>
 {
-    std::vector<tcp::endpoint> endpoints;
+	std::vector<tcp::endpoint> endpoints;
 
-    tcp::resolver resolver(service);
-    tcp::resolver::query query(host, name);
+	tcp::resolver resolver(service);
+	tcp::resolver::query query(host, name);
 
-    for (auto it = resolver.resolve(query); it != tcp::resolver::iterator(); ++it)
-        endpoints.push_back(*it);
+	for (auto it = resolver.resolve(query); it != tcp::resolver::iterator(); ++it)
+		endpoints.push_back(*it);
 
-    return endpoints;
+	return endpoints;
 }
 
 /*
@@ -115,30 +117,30 @@
  * domain = "ipv4 or ipv6" (Optional, default: ipv4)
  * ssl = true | false
  */
-std::unique_ptr<io::connector> read_connect_ip(const ini::section& sc)
+auto read_connect_ip(const ini::section& sc) -> std::unique_ptr<connector>
 {
-    const auto host = sc.get("host").value();
-    const auto port = sc.get("port").value();
+	const auto host = sc.get("host").get_value();
+	const auto port = sc.get("port").get_value();
 
-    if (host.empty())
-        throw transport_error(transport_error::invalid_hostname);
-    if (port.empty())
-        throw transport_error(transport_error::invalid_port);
+	if (host.empty())
+		throw transport_error(transport_error::invalid_hostname);
+	if (port.empty())
+		throw transport_error(transport_error::invalid_port);
 
-    const auto endpoints = resolve(host, port);
+	const auto endpoints = resolve(host, port);
 
-    if (string_util::is_boolean(sc.get("ssl").value())) {
+	if (string_util::is_boolean(sc.get("ssl").get_value())) {
 #if defined(IRCCD_HAVE_SSL)
-        // TODO: support more parameters.
-        boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
+		// TODO: support more parameters.
+		boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
 
-        return std::make_unique<io::tls_connector<>>(std::move(ctx), service, endpoints);
+		return std::make_unique<tls_connector<>>(std::move(ctx), service, endpoints);
 #else
-        throw std::runtime_error("SSL disabled");
+		throw std::runtime_error("SSL disabled");
 #endif
-    }
+	}
 
-    return std::make_unique<io::ip_connector>(service, endpoints);
+	return std::make_unique<ip_connector>(service, endpoints);
 }
 
 /*
@@ -151,21 +153,21 @@
  * type = "unix"
  * path = "path to socket file"
  */
-std::unique_ptr<io::connector> read_connect_local(const ini::section& sc)
+auto read_connect_local(const ini::section& sc) -> std::unique_ptr<connector>
 {
 #if !BOOST_OS_WINDOWS
-    using boost::asio::local::stream_protocol;
+	using boost::asio::local::stream_protocol;
 
-    const auto it = sc.find("path");
+	const auto it = sc.find("path");
 
-    if (it == sc.end())
-        throw std::invalid_argument("missing path parameter");
+	if (it == sc.end())
+		throw std::invalid_argument("missing path parameter");
 
-    return std::make_unique<io::local_connector>(service, it->value());
+	return std::make_unique<local_connector>(service, it->get_value());
 #else
-    (void)sc;
+	(void)sc;
 
-    throw std::invalid_argument("unix connection not supported on Windows");
+	throw std::invalid_argument("unix connection not supported on Windows");
 #endif
 }
 
@@ -177,28 +179,28 @@
  */
 void read_connect(const ini::section& sc)
 {
-    const auto it = sc.find("type");
+	const auto it = sc.find("type");
 
-    if (it == sc.end())
-        throw std::invalid_argument("missing type parameter");
+	if (it == sc.end())
+		throw std::invalid_argument("missing type parameter");
 
-    std::unique_ptr<io::connector> connector;
+	std::unique_ptr<connector> connector;
 
-    if (it->value() == "ip")
-        connector = read_connect_ip(sc);
-    else if (it->value() == "unix")
-        connector = read_connect_local(sc);
-    else
-        throw std::invalid_argument(str(format("invalid type given: %1%") % it->value()));
+	if (it->get_value() == "ip")
+		connector = read_connect_ip(sc);
+	else if (it->get_value() == "unix")
+		connector = read_connect_local(sc);
+	else
+		throw std::invalid_argument(str(format("invalid type given: %1%") % it->get_value()));
 
-    if (connector) {
-        ctl = std::make_unique<controller>(std::move(connector));
+	if (connector) {
+		ctl = std::make_unique<controller>(std::move(connector));
 
-        auto password = sc.find("password");
+		auto password = sc.find("password");
 
-        if (password != sc.end())
-            ctl->set_password(password->value());
-    }
+		if (password != sc.end())
+			ctl->set_password(password->get_value());
+	}
 }
 
 /*
@@ -212,10 +214,10 @@
  */
 void read_general(const ini::section& sc)
 {
-    const auto value = sc.find("verbose");
+	const auto value = sc.find("verbose");
 
-    if (value != sc.end())
-        verbose = string_util::is_boolean(value->value());
+	if (value != sc.end())
+		verbose = string_util::is_boolean(value->get_value());
 }
 
 /*
@@ -228,50 +230,50 @@
  * cmd1 = ( "command", "arg1, "...", "argn" )
  * cmd2 = ( "command", "arg1, "...", "argn" )
  */
-alias read_alias(const ini::section& sc, const std::string& name)
+auto read_alias(const ini::section& sc, const std::string& name) -> alias
 {
-    alias alias(name);
+	alias alias(name);
 
-    /*
-     * Each defined option is a command that the user can call. The name is
-     * unused and serves as documentation purpose.
-     */
-    for (const auto& option : sc) {
-        /*
-         * Iterate over the arguments which are usually a list and the first
-         * argument is a command name.
-         */
-        if (option.size() == 1 && option[0].empty())
-            throw std::runtime_error(str(format("alias %1%: missing command name in '%2%'")
-                % name % option.key()));
+	/*
+	 * Each defined option is a command that the user can call. The name is
+	 * unused and serves as documentation purpose.
+	 */
+	for (const auto& option : sc) {
+		/*
+		 * Iterate over the arguments which are usually a list and the first
+		 * argument is a command name.
+		 */
+		if (option.size() == 1 && option[0].empty())
+			throw std::runtime_error(str(format("alias %1%: missing command name in '%2%'")
+				% name % option.get_key()));
 
-        std::string command = option[0];
-        std::vector<alias_arg> args(option.begin() + 1, option.end());
+		std::string command = option[0];
+		std::vector<alias_arg> args(option.begin() + 1, option.end());
 
-        alias.emplace_back(std::move(command), std::move(args));
-    }
+		alias.emplace_back(std::move(command), std::move(args));
+	}
 
-    return alias;
+	return alias;
 }
 
 void read(const config& cfg)
 {
-    ini::document::const_iterator it;
+	ini::document::const_iterator it;
 
-    if (!ctl && (it = cfg.find("connect")) != cfg.end())
-        read_connect(*it);
-    if ((it = cfg.find("general")) != cfg.end())
-        read_general(*it);
+	if (!ctl && (it = cfg.find("connect")) != cfg.end())
+		read_connect(*it);
+	if ((it = cfg.find("general")) != cfg.end())
+		read_general(*it);
 
-    // [alias.*] sections.
-    for (const auto& sc : cfg) {
-        if (sc.key().compare(0, 6, "alias.") == 0) {
-            auto name = sc.key().substr(6);
-            auto alias = read_alias(sc, name);
+	// [alias.*] sections.
+	for (const auto& sc : cfg) {
+		if (sc.get_key().compare(0, 6, "alias.") == 0) {
+			auto name = sc.get_key().substr(6);
+			auto alias = read_alias(sc, name);
 
-            aliases.emplace(std::move(name), std::move(alias));
-        }
-    }
+			aliases.emplace(std::move(name), std::move(alias));
+		}
+	}
 }
 
 /*
@@ -289,23 +291,23 @@
  * -h host or ip
  * -p port
  */
-std::unique_ptr<io::connector> parse_connect_ip(const option::result& options)
+auto parse_connect_ip(const option::result& options) -> std::unique_ptr<connector>
 {
-    option::result::const_iterator it;
+	option::result::const_iterator it;
 
-    // Host (-h or --host).
-    if ((it = options.find("-h")) == options.end() && (it = options.find("--host")) == options.end())
-        throw transport_error(transport_error::invalid_hostname);
+	// Host (-h or --host).
+	if ((it = options.find("-h")) == options.end() && (it = options.find("--host")) == options.end())
+		throw transport_error(transport_error::invalid_hostname);
 
-    const auto host = it->second;
+	const auto host = it->second;
 
-    // Port (-p or --port).
-    if ((it = options.find("-p")) == options.end() && (it = options.find("--port")) == options.end())
-        throw transport_error(transport_error::invalid_port);
+	// Port (-p or --port).
+	if ((it = options.find("-p")) == options.end() && (it = options.find("--port")) == options.end())
+		throw transport_error(transport_error::invalid_port);
 
-    const auto port = it->second;
+	const auto port = it->second;
 
-    return std::make_unique<io::ip_connector>(service, resolve(host, port));
+	return std::make_unique<ip_connector>(service, resolve(host, port));
 }
 
 /*
@@ -316,19 +318,19 @@
  *
  * -P file
  */
-std::unique_ptr<io::connector> parse_connect_local(const option::result& options)
+auto parse_connect_local(const option::result& options) -> std::unique_ptr<connector>
 {
 #if !BOOST_OS_WINDOWS
-    option::result::const_iterator it;
+	option::result::const_iterator it;
 
-    if ((it = options.find("-P")) == options.end() && (it = options.find("--path")) == options.end())
-        throw std::invalid_argument("missing path parameter (-P or --path)");
+	if ((it = options.find("-P")) == options.end() && (it = options.find("--path")) == options.end())
+		throw std::invalid_argument("missing path parameter (-P or --path)");
 
-    return std::make_unique<io::local_connector>(service, it->second);
+	return std::make_unique<local_connector>(service, it->second);
 #else
-    (void)options;
+	(void)options;
 
-    throw std::invalid_argument("unix connection not supported on Windows");
+	throw std::invalid_argument("unix connection not supported on Windows");
 #endif
 }
 
@@ -340,174 +342,174 @@
  */
 void parse_connect(const option::result& options)
 {
-    assert(options.count("-t") > 0 || options.count("--type") > 0);
+	assert(options.count("-t") > 0 || options.count("--type") > 0);
 
-    auto it = options.find("-t");
+	auto it = options.find("-t");
 
-    if (it == options.end())
-        it = options.find("--type");
+	if (it == options.end())
+		it = options.find("--type");
 
-    std::unique_ptr<io::connector> connector;
+	std::unique_ptr<connector> connector;
 
-    if (it->second == "ip" || it->second == "ipv6")
-        connector = parse_connect_ip(options);
-    if (it->second == "unix")
-        connector = parse_connect_local(options);
-    else
-        throw std::invalid_argument(str(format("invalid type given: %1%") % it->second));
+	if (it->second == "ip" || it->second == "ipv6")
+		connector = parse_connect_ip(options);
+	if (it->second == "unix")
+		connector = parse_connect_local(options);
+	else
+		throw std::invalid_argument(str(format("invalid type given: %1%") % it->second));
 
-    if (connector)
-        ctl = std::make_unique<controller>(std::move(connector));
+	if (connector)
+		ctl = std::make_unique<controller>(std::move(connector));
 }
 
-option::result parse(int& argc, char**& argv)
+auto parse(int& argc, char**& argv) -> option::result
 {
-    // 1. Parse command line options.
-    option::options def{
-        { "-c",         true    },
-        { "--config",   true    },
-        { "-h",         true    },
-        { "--help",     false   },
-        { "--host",     true    },
-        { "-p",         true    },
-        { "--port",     true    },
-        { "-P",         true    },
-        { "--path",     true    },
-        { "-t",         true    },
-        { "--type",     true    },
-        { "-v",         false   },
-        { "--verbose",  false   }
-    };
+	// 1. Parse command line options.
+	option::options def{
+		{ "-c",         true    },
+		{ "--config",   true    },
+		{ "-h",         true    },
+		{ "--help",     false   },
+		{ "--host",     true    },
+		{ "-p",         true    },
+		{ "--port",     true    },
+		{ "-P",         true    },
+		{ "--path",     true    },
+		{ "-t",         true    },
+		{ "--type",     true    },
+		{ "-v",         false   },
+		{ "--verbose",  false   }
+	};
 
-    option::result result;
+	option::result result;
 
-    try {
-        result = option::read(argc, argv, def);
+	try {
+		result = option::read(argc, argv, def);
 
-        if (result.count("--help") > 0 || result.count("-h") > 0)
-            usage();
-            // NOTREACHED
+		if (result.count("--help") > 0 || result.count("-h") > 0)
+			usage();
+			// NOTREACHED
 
-        if (result.count("-v") != 0 || result.count("--verbose") != 0)
-            verbose = true;
-    } catch (const std::exception& ex) {
-        std::cerr << "irccdctl: " << ex.what() << std::endl;
-        usage();
-    }
+		if (result.count("-v") != 0 || result.count("--verbose") != 0)
+			verbose = true;
+	} catch (const std::exception& ex) {
+		std::cerr << "irccdctl: " << ex.what() << std::endl;
+		usage();
+	}
 
-    return result;
+	return result;
 }
 
 void exec(std::vector<std::string>);
 
 void exec(const alias& alias, std::vector<std::string> args_copy)
 {
-    for (const auto& cmd : alias) {
-        std::vector<std::string> args(args_copy);
-        std::vector<std::string> cmd_args;
-        std::vector<std::string>::size_type toremove = 0;
+	for (const auto& cmd : alias) {
+		std::vector<std::string> args(args_copy);
+		std::vector<std::string> cmd_args;
+		std::vector<std::string>::size_type toremove = 0;
 
-        // 1. Append command name before.
-        cmd_args.push_back(cmd.command());
+		// 1. Append command name before.
+		cmd_args.push_back(cmd.get_command());
 
-        for (const auto& arg : cmd.args()) {
-            if (arg.is_placeholder()) {
-                if (args.size() < arg.index() + 1)
-                    throw std::invalid_argument(
-                        str(format("missing argument for placeholder %1%") % arg.index()));
+		for (const auto& arg : cmd.get_args()) {
+			if (arg.is_placeholder()) {
+				if (args.size() < arg.get_index() + 1)
+					throw std::invalid_argument(
+						str(format("missing argument for placeholder %1%") % arg.get_index()));
 
-                cmd_args.push_back(args[arg.index()]);
+				cmd_args.push_back(args[arg.get_index()]);
 
-                if (arg.index() + 1 > toremove)
-                    toremove = arg.index() + 1;
-            } else
-                cmd_args.push_back(arg.value());
-        }
+				if (arg.get_index() + 1 > toremove)
+					toremove = arg.get_index() + 1;
+			} else
+				cmd_args.push_back(arg.get_value());
+		}
 
-        assert(toremove <= args.size());
+		assert(toremove <= args.size());
 
-        // 2. Remove the arguments that been placed in placeholders.
-        args.erase(args.begin(), args.begin() + toremove);
+		// 2. Remove the arguments that been placed in placeholders.
+		args.erase(args.begin(), args.begin() + toremove);
 
-        // 3. Now append the rest of arguments.
-        std::copy(args.begin(), args.end(), std::back_inserter(cmd_args));
+		// 3. Now append the rest of arguments.
+		std::copy(args.begin(), args.end(), std::back_inserter(cmd_args));
 
-        // 4. Finally try to execute.
-        exec(cmd_args);
-    }
+		// 4. Finally try to execute.
+		exec(cmd_args);
+	}
 }
 
 void exec(std::vector<std::string> args)
 {
-    assert(args.size() > 0);
+	assert(args.size() > 0);
 
-    auto name = args[0];
-    auto alias = aliases.find(name);
+	auto name = args[0];
+	auto alias = aliases.find(name);
 
-    // Remove name.
-    args.erase(args.begin());
+	// Remove name.
+	args.erase(args.begin());
 
-    if (alias != aliases.end())
-        exec(alias->second, args);
-    else {
-        auto cmd = commands.find(name);
+	if (alias != aliases.end())
+		exec(alias->second, args);
+	else {
+		auto cmd = commands.find(name);
 
-        if (cmd != commands.end())
-            cmd->second->exec(*ctl, args);
-        else
-            throw std::invalid_argument("no alias or command named " + name);
-    }
+		if (cmd != commands.end())
+			cmd->second->exec(*ctl, args);
+		else
+			throw std::invalid_argument("no alias or command named " + name);
+	}
 }
 
 void init(int &argc, char **&argv)
 {
-    sys::set_program_name("irccdctl");
+	sys::set_program_name("irccdctl");
 
-    -- argc;
-    ++ argv;
+	-- argc;
+	++ argv;
 
-    for (const auto& f : cli::registry) {
-        auto c = f();
+	for (const auto& f : cli::registry) {
+		auto c = f();
 
-        commands.emplace(c->get_name(), std::move(c));
-    }
+		commands.emplace(c->get_name(), std::move(c));
+	}
 }
 
 void do_connect()
 {
-    ctl->connect([&] (auto code, auto info) {
-        if (code)
-            throw std::system_error(code);
+	ctl->connect([&] (auto code, auto info) {
+		if (code)
+			throw std::system_error(code);
 
-        if (verbose) {
-            const json_util::document doc(info);
-            const auto major = doc.get<int>("/major");
-            const auto minor = doc.get<int>("/minor");
-            const auto patch = doc.get<int>("/patch");
+		if (verbose) {
+			const json_util::deserializer doc(info);
+			const auto major = doc.get<int>("/major");
+			const auto minor = doc.get<int>("/minor");
+			const auto patch = doc.get<int>("/patch");
 
-            if (!major || !minor || !patch)
-                std::cout << "connected to irccd (unknown version)" << std::endl;
-            else
-                std::cout << "connected to irccd "
-                          << *major << "."
-                          << *minor << "."
-                          << *patch << std::endl;
-        }
-    });
+			if (!major || !minor || !patch)
+				std::cout << "connected to irccd (unknown version)" << std::endl;
+			else
+				std::cout << "connected to irccd "
+				          << *major << "."
+				          << *minor << "."
+				          << *patch << std::endl;
+		}
+	});
 
-    service.run();
-    service.reset();
+	service.run();
+	service.reset();
 }
 
 void do_exec(int argc, char** argv)
 {
-    std::vector<std::string> args;
+	std::vector<std::string> args;
 
-    for (int i = 0; i < argc; ++i)
-        args.push_back(argv[i]);
+	for (int i = 0; i < argc; ++i)
+		args.push_back(argv[i]);
 
-    exec(args);
-    service.run();
+	exec(args);
+	service.run();
 }
 
 } // !namespace
@@ -518,54 +520,54 @@
 
 int main(int argc, char** argv)
 {
-    irccd::ctl::init(argc, argv);
+	irccd::ctl::init(argc, argv);
 
-    // 1. Read command line arguments.
-    auto result = irccd::ctl::parse(argc, argv);
+	// 1. Read command line arguments.
+	auto result = irccd::ctl::parse(argc, argv);
 
-    /*
-     * 2. Open optional config by command line or by searching it
-     *
-     * The connection to irccd is searched in the following order :
-     *
-     * 1. From the command line if specified
-     * 2. From the configuration file specified by -c
-     * 3. From the configuration file searched through directories
-     */
-    try {
-        if (result.count("-t") > 0 || result.count("--type") > 0)
-            irccd::ctl::parse_connect(result);
+	/*
+	 * 2. Open optional config by command line or by searching it
+	 *
+	 * The connection to irccd is searched in the following order :
+	 *
+	 * 1. From the command line if specified
+	 * 2. From the configuration file specified by -c
+	 * 3. From the configuration file searched through directories
+	 */
+	try {
+		if (result.count("-t") > 0 || result.count("--type") > 0)
+			irccd::ctl::parse_connect(result);
 
-        auto it = result.find("-c");
+		auto it = result.find("-c");
 
-        if (it != result.end() || (it = result.find("--config")) != result.end())
-            irccd::ctl::read(it->second);
-        else {
-            if (auto conf = irccd::config::search("irccdctl.conf"))
-                irccd::ctl::read(*conf);
-        }
-    } catch (const std::exception& ex) {
-        std::cerr << "abort: " << ex.what() << std::endl;
-        return 1;
-    }
+		if (it != result.end() || (it = result.find("--config")) != result.end())
+			irccd::ctl::read(it->second);
+		else {
+			if (auto conf = irccd::config::search("irccdctl.conf"))
+				irccd::ctl::read(*conf);
+		}
+	} catch (const std::exception& ex) {
+		std::cerr << "abort: " << ex.what() << std::endl;
+		return 1;
+	}
 
-    if (argc <= 0)
-        irccd::ctl::usage();
-        // NOTREACHED
+	if (argc <= 0)
+		irccd::ctl::usage();
+		// NOTREACHED
 
-    if (!irccd::ctl::ctl) {
-        std::cerr << "abort: no connection specified" << std::endl;
-        return 1;
-    }
+	if (!irccd::ctl::ctl) {
+		std::cerr << "abort: no connection specified" << std::endl;
+		return 1;
+	}
 
-    try {
-        irccd::ctl::do_connect();
-        irccd::ctl::do_exec(argc, argv);
-    } catch (const std::system_error& ex) {
-        std::cerr << "abort: " << ex.code().message() << std::endl;
-        return 1;
-    } catch (const std::exception& ex) {
-        std::cerr << "abort: " << ex.what() << std::endl;
-        return 1;
-    }
+	try {
+		irccd::ctl::do_connect();
+		irccd::ctl::do_exec(argc, argv);
+	} catch (const std::system_error& ex) {
+		std::cerr << "abort: " << ex.code().message() << std::endl;
+		return 1;
+	} catch (const std::exception& ex) {
+		std::cerr << "abort: " << ex.what() << std::endl;
+		return 1;
+	}
 }
--- a/libirccd-core/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -21,60 +21,67 @@
 find_package(Boost 1.60 REQUIRED QUIET COMPONENTS filesystem system)
 
 set(
-    HEADERS
-    ${libirccd-core_SOURCE_DIR}/irccd/acceptor.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/config.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/connector.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/fs_util.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/ini.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/ini_util.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/json_util.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/options.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/socket_acceptor.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/socket_connector.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/socket_stream.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/stream.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/string_util.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/system.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/tls_acceptor.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/tls_connector.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/tls_stream.hpp
-    ${libirccd-core_SOURCE_DIR}/irccd/xdg.hpp
+	HEADERS
+	${libirccd-core_SOURCE_DIR}/irccd/acceptor.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/config.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/connector.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/fs_util.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/ini.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/ini_util.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/json_util.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/options.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/socket_acceptor.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/socket_connector.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/socket_stream.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/stream.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/string_util.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/system.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/tls_acceptor.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/tls_connector.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/tls_stream.hpp
+	${libirccd-core_SOURCE_DIR}/irccd/xdg.hpp
 )
 
 set(
-    SOURCES
-    ${libirccd-core_SOURCE_DIR}/irccd/config.cpp
-    ${libirccd-core_SOURCE_DIR}/irccd/fs_util.cpp
-    ${libirccd-core_SOURCE_DIR}/irccd/ini.cpp
-    ${libirccd-core_SOURCE_DIR}/irccd/options.cpp
-    ${libirccd-core_SOURCE_DIR}/irccd/string_util.cpp
-    ${libirccd-core_SOURCE_DIR}/irccd/system.cpp
+	SOURCES
+	${libirccd-core_SOURCE_DIR}/irccd/config.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/fs_util.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/ini.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/json_util.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/options.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/string_util.cpp
+	${libirccd-core_SOURCE_DIR}/irccd/system.cpp
 )
 
+set(
+	LIBRARIES
+	${CMAKE_DL_LIBS}
+	libjson
+	Threads::Threads
+	Boost::filesystem
+	Boost::system
+)
+
+if (CMAKE_SYSTEM_NAME MATCHES Windows)
+	list(APPEND LIBRARIES mswsock shlwapi ws2_32)
+elseif (APPLE)
+	list(APPEND LIBRARIES resolv)
+endif ()
+
+if (IRCCD_HAVE_SSL)
+	list(APPEND LIBRARIES OpenSSL::Crypto OpenSSL::SSL)
+endif ()
+
 irccd_define_library(
-    TARGET libirccd-core
-    EXPORT
-    HEADERS ${HEADERS}
-    HEADERS_DIRECTORY irccd
-    SOURCES
-        ${libirccd-core_SOURCE_DIR}/CMakeLists.txt
-        ${SOURCES}
-    LIBRARIES
-        libjson
-        Threads::Threads
-        Boost::filesystem
-        Boost::system
-        $<$<BOOL:${IRCCD_HAVE_SSL}>:OpenSSL::Crypto>
-        $<$<BOOL:${IRCCD_HAVE_SSL}>:OpenSSL::SSL>
-        $<$<BOOL:${APPLE}>:resolv>
-        $<$<BOOL:${WIN32}>:mswsock>
-        $<$<BOOL:${WIN32}>:shlwapi>
-        $<$<BOOL:${WIN32}>:ws2_32>
-        $<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:dl>
-    PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
-        $<BUILD_INTERFACE:${libirccd-core_SOURCE_DIR}>
-        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
-        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/irccd/extern>
+	TARGET libirccd-core
+	EXPORT
+	HEADERS ${HEADERS}
+	HEADERS_DIRECTORY irccd
+	SOURCES ${SOURCES}
+	LIBRARIES ${LIBRARIES}
+	PUBLIC_INCLUDES
+		$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
+		$<BUILD_INTERFACE:${libirccd-core_SOURCE_DIR}>
+		$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+		$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/irccd/extern>
 )
--- a/libirccd-core/irccd/acceptor.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/acceptor.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,16 +28,11 @@
 #include <memory>
 #include <system_error>
 
-namespace irccd::io {
+namespace irccd {
 
 class stream;
 
 /**
- * \brief Accept completion handler.
- */
-using accept_handler = std::function<void (std::error_code, std::shared_ptr<stream>)>;
-
-/**
  * \brief Abstract stream acceptor interface.
  *
  * This class is used to wait a new client in an asynchronous manner. Derived
@@ -45,29 +40,35 @@
  */
 class acceptor {
 public:
-    /**
-     * Default constructor.
-     */
-    acceptor() = default;
+	/**
+	 * \brief Accept completion handler.
+	 */
+	using handler = std::function<void (std::error_code, std::shared_ptr<stream>)>;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~acceptor() = default;
+public:
+	/**
+	 * Default constructor.
+	 */
+	acceptor() = default;
 
-    /**
-     * Start asynchronous accept.
-     *
-     * Once the client is accepted, the original acceptor must be kept until it
-     * is destroyed.
-     *
-     * \pre another accept operation must not be running
-     * \pre handler != nullptr
-     * \param handler the handler
-     */
-    virtual void accept(accept_handler handler) = 0;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~acceptor() = default;
+
+	/**
+	 * Start asynchronous accept.
+	 *
+	 * Once the client is accepted, the original acceptor must be kept until it
+	 * is destroyed.
+	 *
+	 * \pre another accept operation must not be running
+	 * \pre handler != nullptr
+	 * \param handler the handler
+	 */
+	virtual void accept(handler handler) = 0;
 };
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_ACCEPTOR_HPP
--- a/libirccd-core/irccd/config.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/config.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -25,25 +25,25 @@
 
 auto config::search(std::string_view name) -> std::optional<config>
 {
-    for (const auto& path : sys::config_filenames(name)) {
-        boost::system::error_code ec;
+	for (const auto& path : sys::config_filenames(name)) {
+		boost::system::error_code ec;
 
-        if (boost::filesystem::exists(path, ec) && !ec)
-            return config(path);
-    }
+		if (boost::filesystem::exists(path, ec) && !ec)
+			return config(path);
+	}
 
-    return std::nullopt;
+	return std::nullopt;
 }
 
 config::config(std::string path)
-    : document(path.empty() ? ini::document() : ini::read_file(path))
-    , path_(std::move(path))
+	: document(path.empty() ? ini::document() : ini::read_file(path))
+	, path_(std::move(path))
 {
 }
 
 auto config::get_path() const noexcept -> const std::string&
 {
-    return path_;
+	return path_;
 }
 
 } // !irccd
--- a/libirccd-core/irccd/config.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/config.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,30 +36,30 @@
  */
 class config : public ini::document {
 private:
-    std::string path_;
+	std::string path_;
 
 public:
-    /**
-     * Search the configuration file into the standard defined paths.
-     *
-     * \param name the file name
-     * \return the config or empty if not found
-     */
-    static auto search(std::string_view name) -> std::optional<config>;
+	/**
+	 * Search the configuration file into the standard defined paths.
+	 *
+	 * \param name the file name
+	 * \return the config or empty if not found
+	 */
+	static auto search(std::string_view name) -> std::optional<config>;
 
-    /**
-     * Load the configuration from the specified path.
-     *
-     * \param path the path
-     */
-    config(std::string path = "");
+	/**
+	 * Load the configuration from the specified path.
+	 *
+	 * \param path the path
+	 */
+	config(std::string path = "");
 
-    /**
-     * Get the path to the configuration file.
-     *
-     * \return the path
-     */
-    auto get_path() const noexcept -> const std::string&;
+	/**
+	 * Get the path to the configuration file.
+	 *
+	 * \return the path
+	 */
+	auto get_path() const noexcept -> const std::string&;
 };
 
 } // !irccd
--- a/libirccd-core/irccd/connector.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/connector.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,16 +28,11 @@
 #include <memory>
 #include <system_error>
 
-namespace irccd::io {
+namespace irccd {
 
 class stream;
 
 /**
- * \brief Connect completion handler.
- */
-using connect_handler = std::function<void (std::error_code, std::shared_ptr<stream>)>;
-
-/**
  * \brief Abstract connection interface.
  *
  * This class is used to connect to a stream end point (usually sockets) in an
@@ -47,29 +42,34 @@
  */
 class connector {
 public:
-    /**
-     * Default constructor.
-     */
-    connector() = default;
+	/**
+	 * \brief Connect completion handler.
+	 */
+	using handler = std::function<void (std::error_code, std::shared_ptr<stream>)>;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~connector() = default;
+	/**
+	 * Default constructor.
+	 */
+	connector() = default;
 
-    /**
-     * Start asynchronous connect.
-     *
-     * Once the client is connected, the original acceptor must be kept until it
-     * is destroyed.
-     *
-     * \pre another connect operation must not be running
-     * \pre handler != nullptr
-     * \param handler the handler
-     */
-    virtual void connect(connect_handler handler) = 0;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~connector() = default;
+
+	/**
+	 * Start asynchronous connect.
+	 *
+	 * Once the client is connected, the original acceptor must be kept until it
+	 * is destroyed.
+	 *
+	 * \pre another connect operation must not be running
+	 * \pre handler != nullptr
+	 * \param handler the handler
+	 */
+	virtual void connect(handler handler) = 0;
 };
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_CONNECTOR_HPP
--- a/libirccd-core/irccd/fs_util.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/fs_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -24,7 +24,7 @@
 
 auto base_name(const std::string& path) -> std::string
 {
-    return boost::filesystem::path(path).filename().string();
+	return boost::filesystem::path(path).filename().string();
 }
 
 // }}}
@@ -33,7 +33,7 @@
 
 auto dir_name(const std::string& path) -> std::string
 {
-    return boost::filesystem::path(path).parent_path().string();
+	return boost::filesystem::path(path).parent_path().string();
 }
 
 // }}}
@@ -42,16 +42,16 @@
 
 auto find(const std::string& base, const std::string& name, bool recursive) -> std::string
 {
-    return find_if(base, recursive, [&] (const auto& entry) {
-        return entry.path().filename().string() == name;
-    });
+	return find_if(base, recursive, [&] (const auto& entry) {
+		return entry.path().filename().string() == name;
+	});
 }
 
 auto find(const std::string& base, const std::regex& regex, bool recursive) -> std::string
 {
-    return find_if(base, recursive, [&] (const auto& entry) {
-        return std::regex_match(entry.path().filename().string(), regex);
-    });
+	return find_if(base, recursive, [&] (const auto& entry) {
+		return std::regex_match(entry.path().filename().string(), regex);
+	});
 }
 
 // }}}
--- a/libirccd-core/irccd/fs_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/fs_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -83,17 +83,17 @@
 template <typename Predicate>
 auto find_if(const std::string& base, bool recursive, Predicate&& predicate) -> std::string
 {
-    const auto find = [&] (auto it) -> std::string {
-        for (const auto& entry : it)
-            if (predicate(entry))
-                return entry.path().string();
+	const auto find = [&] (auto it) -> std::string {
+		for (const auto& entry : it)
+			if (predicate(entry))
+				return entry.path().string();
 
-        return "";
-    };
+		return "";
+	};
 
-    return recursive
-        ? find(boost::filesystem::recursive_directory_iterator(base))
-        : find(boost::filesystem::directory_iterator(base));
+	return recursive
+		? find(boost::filesystem::recursive_directory_iterator(base))
+		: find(boost::filesystem::directory_iterator(base));
 }
 
 // }}}
--- a/libirccd-core/irccd/ini.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/ini.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -16,6 +16,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include <cassert>
 #include <cctype>
 #include <cstring>
 #include <iostream>
@@ -24,395 +25,614 @@
 #include <sstream>
 #include <stdexcept>
 
-#include <irccd/sysconfig.hpp>
-
-#include <boost/predef.h>
-
 // for PathIsRelative.
-#if BOOST_OS_WINDOWS
-#  include <shlwapi.h>
+#if defined(_WIN32)
+#  include <Shlwapi.h>
 #endif
 
 #include "ini.hpp"
 
-namespace irccd {
+using namespace std::string_literals;
 
-namespace ini {
+namespace irccd::ini {
 
 namespace {
 
 using stream_iterator = std::istreambuf_iterator<char>;
 using token_iterator = std::vector<token>::const_iterator;
 
-inline bool is_absolute(const std::string& path) noexcept
+auto is_absolute(const std::string& path) noexcept -> bool
 {
-#if BOOST_OS_WINDOWS
-    return !PathIsRelative(path.c_str());
+#if defined(_WIN32)
+	return !PathIsRelative(path.c_str());
 #else
-    return path.size() > 0 && path[0] == '/';
+	return path.size() > 0 && path[0] == '/';
 #endif
 }
 
-inline bool is_quote(char c) noexcept
+auto is_quote(char c) noexcept -> bool
 {
-    return c == '\'' || c == '"';
+	return c == '\'' || c == '"';
 }
 
-inline bool is_space(char c) noexcept
+auto is_space(char c) noexcept -> bool
 {
-    // Custom version because std::isspace includes \n as space.
-    return c == ' ' || c == '\t';
+	// Custom version because std::isspace includes \n as space.
+	return c == ' ' || c == '\t';
 }
 
-inline bool is_list(char c) noexcept
+auto is_list(char c) noexcept -> bool
 {
-    return c == '(' || c == ')' || c == ',';
+	return c == '(' || c == ')' || c == ',';
 }
 
-inline bool is_reserved(char c) noexcept
+auto is_reserved(char c) noexcept -> bool
 {
-    return is_list(c) || is_quote(c) || c == '[' || c == ']' || c == '@' || c == '#' || c == '=';
+	return is_list(c) || is_quote(c) || c == '[' || c == ']' || c == '@' || c == '#' || c == '=';
 }
 
-void analyse_line(int& line, int& column, stream_iterator& it) noexcept
+void analyse_line(unsigned& line, unsigned& column, stream_iterator& it) noexcept
 {
-    assert(*it == '\n');
+	assert(*it == '\n');
 
-    ++ line;
-    ++ it;
-    column = 0;
+	++ line;
+	++ it;
+	column = 0;
 }
 
-void analyse_comment(int& column, stream_iterator& it, stream_iterator end) noexcept
+void analyse_comment(unsigned& column, stream_iterator& it, stream_iterator end) noexcept
 {
-    assert(*it == '#');
+	assert(*it == '#');
 
-    while (it != end && *it != '\n') {
-        ++ column;
-        ++ it;
-    }
+	while (it != end && *it != '\n') {
+		++ column;
+		++ it;
+	}
 }
 
-void analyse_spaces(int& column, stream_iterator& it, stream_iterator end) noexcept
+void analyse_spaces(unsigned& column, stream_iterator& it, stream_iterator end) noexcept
 {
-    assert(is_space(*it));
+	assert(is_space(*it));
 
-    while (it != end && is_space(*it)) {
-        ++ column;
-        ++ it;
-    }
+	while (it != end && is_space(*it)) {
+		++ column;
+		++ it;
+	}
 }
 
-void analyse_list(tokens& list, int line, int& column, stream_iterator& it) noexcept
+void analyse_list(tokens& list, unsigned line, unsigned& column, stream_iterator& it) noexcept
 {
-    assert(is_list(*it));
+	assert(is_list(*it));
 
-    switch (*it++) {
-    case '(':
-        list.emplace_back(token::list_begin, line, column++);
-        break;
-    case ')':
-        list.emplace_back(token::list_end, line, column++);
-        break;
-    case ',':
-        list.emplace_back(token::comma, line, column++);
-        break;
-    default:
-        break;
-    }
+	switch (*it++) {
+	case '(':
+		list.emplace_back(token::list_begin, line, column++);
+		break;
+	case ')':
+		list.emplace_back(token::list_end, line, column++);
+		break;
+	case ',':
+		list.emplace_back(token::comma, line, column++);
+		break;
+	default:
+		break;
+	}
 }
 
-void analyse_section(tokens& list, int& line, int& column, stream_iterator& it, stream_iterator end)
+void analyse_section(tokens& list, unsigned& line, unsigned& column, stream_iterator& it, stream_iterator end)
 {
-    assert(*it == '[');
+	assert(*it == '[');
 
-    std::string value;
-    int save = column;
+	std::string value;
+	unsigned save = column;
 
-    // Read section name.
-    ++ it;
-    while (it != end && *it != ']') {
-        if (*it == '\n')
-            throw exception(line, column, "section not terminated, missing ']'");
-        if (is_reserved(*it))
-            throw exception(line, column, "section name expected after '[', got '" + std::string(1, *it) + "'");
+	// Read section name.
+	++ it;
+	while (it != end && *it != ']') {
+		if (*it == '\n')
+			throw exception(line, column, "section not terminated, missing ']'");
+		if (is_reserved(*it))
+			throw exception(line, column, "section name expected after '[', got '" + std::string(1, *it) + "'");
 
-        ++ column;
-        value += *it++;
-    }
+		++ column;
+		value += *it++;
+	}
 
-    if (it == end)
-        throw exception(line, column, "section name expected after '[', got <EOF>");
-    if (value.empty())
-        throw exception(line, column, "empty section name");
+	if (it == end)
+		throw exception(line, column, "section name expected after '[', got <EOF>");
+	if (value.empty())
+		throw exception(line, column, "empty section name");
 
-    // Remove ']'.
-    ++ it;
+	// Remove ']'.
+	++ it;
 
-    list.emplace_back(token::section, line, save, std::move(value));
+	list.emplace_back(token::section, line, save, std::move(value));
 }
 
-void analyse_assign(tokens& list, int& line, int& column, stream_iterator& it)
+void analyse_assign(tokens& list, unsigned& line, unsigned& column, stream_iterator& it)
 {
-    assert(*it == '=');
+	assert(*it == '=');
 
-    list.push_back({ token::assign, line, column++ });
-    ++ it;
+	list.push_back({ token::assign, line, column++ });
+	++ it;
 }
 
-void analyse_quoted_word(tokens& list, int& line, int& column, stream_iterator& it, stream_iterator end)
+void analyse_quoted_word(tokens& list, unsigned& line, unsigned& column, stream_iterator& it, stream_iterator end)
 {
-    std::string value;
-    int save = column;
-    char quote = *it++;
+	std::string value;
+	unsigned save = column;
+	char quote = *it++;
 
-    while (it != end && *it != quote) {
-        // TODO: escape sequence
-        ++ column;
-        value += *it++;
-    }
+	while (it != end && *it != quote) {
+		// TODO: escape sequence
+		++ column;
+		value += *it++;
+	}
 
-    if (it == end)
-        throw exception(line, column, "undisclosed '" + std::string(1, quote) + "', got <EOF>");
+	if (it == end)
+		throw exception(line, column, "undisclosed '" + std::string(1, quote) + "', got <EOF>");
 
-    // Remove quote.
-    ++ it;
+	// Remove quote.
+	++ it;
 
-    list.push_back({ token::quoted_word, line, save, std::move(value) });
+	list.push_back({ token::quoted_word, line, save, std::move(value) });
 }
 
-void analyse_word(tokens& list, int& line, int& column, stream_iterator& it, stream_iterator end)
+void analyse_word(tokens& list, unsigned& line, unsigned& column, stream_iterator& it, stream_iterator end)
 {
-    assert(!is_reserved(*it));
+	assert(!is_reserved(*it));
 
-    std::string value;
-    int save = column;
+	std::string value;
+	unsigned save = column;
 
-    while (it != end && !std::isspace(*it) && !is_reserved(*it)) {
-        ++ column;
-        value += *it++;
-    }
+	while (it != end && !std::isspace(*it) && !is_reserved(*it)) {
+		++ column;
+		value += *it++;
+	}
 
-    list.push_back({ token::word, line, save, std::move(value) });
+	list.push_back({ token::word, line, save, std::move(value) });
 }
 
-void analyse_include(tokens& list, int& line, int& column, stream_iterator& it, stream_iterator end)
+void analyse_include(tokens& list, unsigned& line, unsigned& column, stream_iterator& it, stream_iterator end)
 {
-    assert(*it == '@');
+	assert(*it == '@');
 
-    std::string include;
-    int save = column;
+	std::string include;
+	unsigned save = column;
 
-    // Read include.
-    ++ it;
-    while (it != end && !is_space(*it)) {
-        ++ column;
-        include += *it++;
-    }
+	// Read include.
+	++ it;
+	while (it != end && !is_space(*it)) {
+		++ column;
+		include += *it++;
+	}
 
-    if (include != "include")
-        throw exception(line, column, "expected include after '@' token");
-
-    list.push_back({ token::include, line, save });
+	if (include == "include")
+		list.push_back({ token::include, line, save });
+	else if (include == "tryinclude")
+		list.push_back({ token::tryinclude, line, save });
+	else
+		throw exception(line, column, "expected include or tryinclude after '@' token");
 }
 
 void parse_option_value_simple(option& option, token_iterator& it)
 {
-    assert(it->type() == token::word || it->type() == token::quoted_word);
+	assert(it->get_type() == token::word || it->get_type() == token::quoted_word);
 
-    option.push_back((it++)->value());
+	option.push_back((it++)->get_value());
 }
 
 void parse_option_value_list(option& option, token_iterator& it, token_iterator end)
 {
-    assert(it->type() == token::list_begin);
+	assert(it->get_type() == token::list_begin);
 
-    token_iterator save = it++;
+	token_iterator save = it++;
 
-    while (it != end && it->type() != token::list_end) {
-        switch (it->type()) {
-        case token::comma:
-            // Previous must be a word.
-            if (it[-1].type() != token::word && it[-1].type() != token::quoted_word)
-                throw exception(it->line(), it->column(), "unexpected comma after '" + it[-1].value() + "'");
+	while (it != end && it->get_type() != token::list_end) {
+		switch (it->get_type()) {
+		case token::comma:
+			// Previous must be a word.
+			if (it[-1].get_type() != token::word && it[-1].get_type() != token::quoted_word)
+				throw exception(it->get_line(), it->get_column(),
+				                "unexpected comma after '"s + it[-1].get_value() + "'");
 
-            ++ it;
-            break;
-        case token::word:
-        case token::quoted_word:
-            option.push_back((it++)->value());
-            break;
-        default:
-            throw exception(it->line(), it->column(), "unexpected '" + it[-1].value() + "' in list construct");
-            break;
-        }
-    }
+			++ it;
+			break;
+		case token::word:
+		case token::quoted_word:
+			option.push_back((it++)->get_value());
+			break;
+		default:
+			throw exception(it->get_line(), it->get_column(), "unexpected '"s + it[-1].get_value() + "' in list construct");
+			break;
+		}
+	}
 
-    if (it == end)
-        throw exception(save->line(), save->column(), "unterminated list construct");
+	if (it == end)
+		throw exception(save->get_line(), save->get_column(), "unterminated list construct");
 
-    // Remove ).
-    ++ it;
+	// Remove ).
+	++ it;
 }
 
 void parse_option(section& sc, token_iterator& it, token_iterator end)
 {
-    option option(it->value());
-    token_iterator save(it);
+	option option(it->get_value());
+	token_iterator save(it);
 
-    // No '=' or something else?
-    if (++it == end)
-        throw exception(save->line(), save->column(), "expected '=' assignment, got <EOF>");
-    if (it->type() != token::assign)
-        throw exception(it->line(), it->column(), "expected '=' assignment, got " + it->value());
+	// No '=' or something else?
+	if (++it == end)
+		throw exception(save->get_line(), save->get_column(), "expected '=' assignment, got <EOF>");
+	if (it->get_type() != token::assign)
+		throw exception(it->get_line(), it->get_column(), "expected '=' assignment, got " + it->get_value());
 
-    // Empty options are allowed so just test for words.
-    if (++it != end) {
-        if (it->type() == token::word || it->type() == token::quoted_word)
-            parse_option_value_simple(option, it);
-        else if (it->type() == token::list_begin)
-            parse_option_value_list(option, it, end);
-    }
+	// Empty options are allowed so just test for words.
+	if (++it != end) {
+		if (it->get_type() == token::word || it->get_type() == token::quoted_word)
+			parse_option_value_simple(option, it);
+		else if (it->get_type() == token::list_begin)
+			parse_option_value_list(option, it, end);
+	}
 
-    sc.push_back(std::move(option));
+	sc.push_back(std::move(option));
 }
 
-void parse_include(document& doc, const std::string& path, token_iterator& it, token_iterator end)
+void parse_include(document& doc, const std::string& path, token_iterator& it, token_iterator end, bool required)
 {
-    token_iterator save(it);
+	token_iterator save(it);
 
-    if (++it == end)
-        throw exception(save->line(), save->column(), "expected file name after '@include' statement, got <EOF>");
-    if (it->type() != token::word && it->type() != token::quoted_word)
-        throw exception(it->line(), it->column(), "expected file name after '@include' statement, got " + it->value());
+	if (++it == end)
+		throw exception(save->get_line(), save->get_column(), "expected file name after '@include' statement, got <EOF>");
+	if (it->get_type() != token::word && it->get_type() != token::quoted_word)
+		throw exception(it->get_line(), it->get_column(),
+		                "expected file name after '@include' statement, got "s + it->get_value());
 
-    std::string value = (it++)->value();
-    std::string file;
+	std::string value = (it++)->get_value();
+	std::string file;
 
-    if (!is_absolute(value)) {
-#if BOOST_OS_WINDOWS
-        file = path + "\\" + value;
+	if (!is_absolute(value)) {
+#if defined(_WIN32)
+		file = path + "\\" + value;
 #else
-        file = path + "/" + value;
+		file = path + "/" + value;
 #endif
-    } else
-        file = value;
+	} else
+		file = value;
 
-    for (const auto& sc : read_file(file))
-        doc.push_back(sc);
+	try {
+		/*
+		 * If required is set to true, we have @include, otherwise the non-fatal
+		 * @tryinclude keyword.
+		 */
+		for (const auto& sc : read_file(file))
+			doc.push_back(sc);
+	} catch (...) {
+		if (required)
+			throw;
+	}
 }
 
 void parse_section(document& doc, token_iterator& it, token_iterator end)
 {
-    section sc(it->value());
+	section sc(it->get_value());
 
-    // Skip [section].
-    ++ it;
+	// Skip [section].
+	++ it;
 
-    // Read until next section.
-    while (it != end && it->type() != token::section) {
-        if (it->type() != token::word)
-            throw exception(it->line(), it->column(), "unexpected token '" + it->value() + "' in section definition");
+	// Read until next section.
+	while (it != end && it->get_type() != token::section) {
+		if (it->get_type() != token::word)
+			throw exception(it->get_line(), it->get_column(),
+			                "unexpected token '"s + it->get_value() + "' in section definition");
 
-        parse_option(sc, it, end);
-    }
+		parse_option(sc, it, end);
+	}
 
-    doc.push_back(std::move(sc));
+	doc.push_back(std::move(sc));
 }
 
 } // !namespace
 
+exception::exception(unsigned line, unsigned column, std::string msg) noexcept
+	: line_(line)
+	, column_(column)
+	, message_(std::move(msg))
+{
+}
+
+auto exception::line() const noexcept -> unsigned
+{
+	return line_;
+}
+
+auto exception::column() const noexcept -> unsigned
+{
+	return column_;
+}
+
+auto exception::what() const noexcept -> const char*
+{
+	return message_.c_str();
+}
+
+token::token(type type, unsigned line, unsigned column, std::string value) noexcept
+	: type_(type)
+	, line_(line)
+	, column_(column)
+{
+	switch (type) {
+	case include:
+		value_ = "@include";
+		break;
+	case tryinclude:
+		value_ = "@tryinclude";
+		break;
+	case section:
+	case word:
+	case quoted_word:
+		value_ = value;
+		break;
+	case assign:
+		value_ = "=";
+		break;
+	case list_begin:
+		value_ = "(";
+		break;
+	case list_end:
+		value_ = ")";
+		break;
+	case comma:
+		value_ = ",";
+		break;
+	default:
+		break;
+	}
+}
+
+auto token::get_type() const noexcept -> type
+{
+	return type_;
+}
+
+auto token::get_line() const noexcept -> unsigned
+{
+	return line_;
+}
+
+auto token::get_column() const noexcept -> unsigned
+{
+	return column_;
+}
+
+auto token::get_value() const noexcept -> const std::string&
+{
+	return value_;
+}
+
+option::option(std::string key) noexcept
+	: std::vector<std::string>()
+	, key_(std::move(key))
+{
+	assert(!key_.empty());
+}
+
+option::option(std::string key, std::string value) noexcept
+	: key_(std::move(key))
+{
+	assert(!key_.empty());
+
+	push_back(std::move(value));
+}
+
+option::option(std::string key, std::vector<std::string> values) noexcept
+	: std::vector<std::string>(std::move(values))
+	, key_(std::move(key))
+{
+	assert(!key_.empty());
+}
+
+auto option::get_key() const noexcept -> const std::string&
+{
+	return key_;
+}
+
+auto option::get_value() const noexcept -> const std::string&
+{
+	static std::string dummy;
+
+	return empty() ? dummy : (*this)[0];
+}
+
+section::section(std::string key) noexcept
+	: key_(std::move(key))
+{
+	assert(!key_.empty());
+}
+
+auto section::get_key() const noexcept -> const std::string&
+{
+	return key_;
+}
+
+auto section::contains(std::string_view key) const noexcept -> bool
+{
+	return find(key) != end();
+}
+
+auto section::get(std::string_view key) const noexcept -> option
+{
+	auto it = find(key);
+
+	if (it == end())
+		return option(std::string(key));
+
+	return *it;
+}
+
+auto section::find(std::string_view key) noexcept -> iterator
+{
+	return std::find_if(begin(), end(), [&] (const auto& o) {
+		return o.get_key() == key;
+	});
+}
+
+auto section::find(std::string_view key) const noexcept -> const_iterator
+{
+	return std::find_if(cbegin(), cend(), [&] (const auto& o) {
+		return o.get_key() == key;
+	});
+}
+
+auto section::operator[](std::string_view key) -> option&
+{
+	assert(contains(key));
+
+	return *find(key);
+}
+
+auto section::operator[](std::string_view key) const -> const option&
+{
+	assert(contains(key));
+
+	return *find(key);
+}
+
+auto document::contains(std::string_view key) const noexcept -> bool
+{
+	return find(key) != end();
+}
+
+auto document::get(std::string_view key) const noexcept -> section
+{
+	auto it = find(key);
+
+	if (it == end())
+		return section(std::string(key));
+
+	return *it;
+}
+
+auto document::find(std::string_view key) noexcept -> iterator
+{
+	return std::find_if(begin(), end(), [&] (const auto& o) {
+		return o.get_key() == key;
+	});
+}
+
+auto document::find(std::string_view key) const noexcept -> const_iterator
+{
+	return std::find_if(cbegin(), cend(), [&] (const auto& o) {
+		return o.get_key() == key;
+	});
+}
+
+auto document::operator[](std::string_view key) -> section&
+{
+	assert(contains(key));
+
+	return *find(key);
+}
+
+auto document::operator[](std::string_view key) const -> const section&
+{
+	assert(contains(key));
+
+	return *find(key);
+}
+
 tokens analyse(std::istreambuf_iterator<char> it, std::istreambuf_iterator<char> end)
 {
-    tokens list;
-    int line = 1;
-    int column = 0;
+	tokens list;
+	unsigned line = 1;
+	unsigned column = 0;
 
-    while (it != end) {
-        if (*it == '\n')
-            analyse_line(line, column, it);
-        else if (*it == '#')
-            analyse_comment(column, it, end);
-        else if (*it == '[')
-            analyse_section(list, line, column, it, end);
-        else if (*it == '=')
-            analyse_assign(list, line, column, it);
-        else if (is_space(*it))
-            analyse_spaces(column, it, end);
-        else if (*it == '@')
-            analyse_include(list, line, column, it, end);
-        else if (is_quote(*it))
-            analyse_quoted_word(list, line, column, it, end);
-        else if (is_list(*it))
-            analyse_list(list, line, column, it);
-        else
-            analyse_word(list, line, column, it, end);
-    }
+	while (it != end) {
+		if (*it == '\n')
+			analyse_line(line, column, it);
+		else if (*it == '#')
+			analyse_comment(column, it, end);
+		else if (*it == '[')
+			analyse_section(list, line, column, it, end);
+		else if (*it == '=')
+			analyse_assign(list, line, column, it);
+		else if (is_space(*it))
+			analyse_spaces(column, it, end);
+		else if (*it == '@')
+			analyse_include(list, line, column, it, end);
+		else if (is_quote(*it))
+			analyse_quoted_word(list, line, column, it, end);
+		else if (is_list(*it))
+			analyse_list(list, line, column, it);
+		else
+			analyse_word(list, line, column, it, end);
+	}
 
-    return list;
+	return list;
 }
 
 tokens analyse(std::istream& stream)
 {
-    return analyse(std::istreambuf_iterator<char>(stream), {});
+	return analyse(std::istreambuf_iterator<char>(stream), {});
 }
 
 document parse(const tokens& tokens, const std::string& path)
 {
-    document doc;
-    token_iterator it = tokens.cbegin();
-    token_iterator end = tokens.cend();
+	document doc;
+	token_iterator it = tokens.cbegin();
+	token_iterator end = tokens.cend();
 
-    while (it != end) {
-        switch (it->type()) {
-        case token::include:
-            parse_include(doc, path, it, end);
-            break;
-        case token::section:
-            parse_section(doc, it, end);
-            break;
-        default:
-            throw exception(it->line(), it->column(), "unexpected '" + it->value() + "' on root document");
-        }
-    }
+	while (it != end) {
+		switch (it->get_type()) {
+		case token::include:
+			parse_include(doc, path, it, end, true);
+			break;
+		case token::tryinclude:
+			parse_include(doc, path, it, end, false);
+			break;
+		case token::section:
+			parse_section(doc, it, end);
+			break;
+		default:
+			throw exception(it->get_line(), it->get_column(),
+			                "unexpected '"s + it->get_value() + "' on root document");
+		}
+	}
 
-    return doc;
+	return doc;
 }
 
 document read_file(const std::string& filename)
 {
-    // Get parent path.
-    auto parent = filename;
-    auto pos = parent.find_last_of("/\\");
+	// Get parent path.
+	auto parent = filename;
+	auto pos = parent.find_last_of("/\\");
 
-    if (pos != std::string::npos)
-        parent.erase(pos);
-    else
-        parent = ".";
+	if (pos != std::string::npos)
+		parent.erase(pos);
+	else
+		parent = ".";
 
-    std::ifstream input(filename);
+	std::ifstream input(filename);
 
-    if (!input)
-        throw exception(0, 0, std::strerror(errno));
+	if (!input)
+		throw exception(0, 0, std::strerror(errno));
 
-    return parse(analyse(input), parent);
+	return parse(analyse(input), parent);
 }
 
 document read_string(const std::string& buffer)
 {
-    std::istringstream iss(buffer);
+	std::istringstream iss(buffer);
 
-    return parse(analyse(iss));
+	return parse(analyse(iss));
 }
 
 void dump(const tokens& tokens)
 {
-    for (const token& token: tokens) {
-        // TODO: add better description
-        std::cout << token.line() << ":" << token.column() << ": " << token.value() << std::endl;
-    }
+	for (const token& token: tokens) {
+		// TODO: add better description
+		std::cout << token.get_line() << ":" << token.get_column() << ": " << token.get_value() << std::endl;
+	}
 }
 
-} // !ini
-
-} // !irccd
+} // !irccd::ini
--- a/libirccd-core/irccd/ini.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/ini.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef IRCCD_COMMON_INI_HPP
-#define IRCCD_COMMON_INI_HPP
+#ifndef IRCCD_CORE_INI_HPP
+#define IRCCD_CORE_INI_HPP
 
 /**
  * \file ini.hpp
@@ -29,8 +29,7 @@
 /**
  * \page Ini Ini
  * \brief Extended .ini file parser.
- *
- *   - \subpage ini-syntax
+ * - \subpage ini-syntax
  */
 
 /**
@@ -39,14 +38,14 @@
  *
  * The syntax is similar to most of `.ini` implementations as:
  *
- *   - a section is delimited by `[name]` can be redefined multiple times,
- *   - an option **must** always be defined in a section,
- *   - empty options must be surrounded by quotes,
- *   - lists can not include trailing commas,
- *   - include statements must always live at the beginning of files
- *     (in no sections),
- *   - comments start with # until the end of line,
- *   - options with spaces **must** use quotes.
+ * - a section is delimited by `[name]` can be redefined multiple times,
+ * - an option **must** always be defined in a section,
+ * - empty options must be surrounded by quotes,
+ * - lists can not include trailing commas,
+ * - include statements must always live at the beginning of files
+ *   (in no sections),
+ * - comments start with # until the end of line,
+ * - options with spaces **must** use quotes.
  *
  * # Basic file
  *
@@ -54,7 +53,7 @@
  * # This is a comment.
  * [section]
  * option1 = value1
- * option2 = "value 2 with spaces"    # comment is also allowed here
+ * option2 = "value 2 with spaces"	# comment is also allowed here
  * ````
  *
  * # Redefinition
@@ -106,21 +105,17 @@
  * ````
  */
 
-#include "sysconfig.hpp"
-
 #include <algorithm>
-#include <cassert>
 #include <exception>
 #include <stdexcept>
 #include <string>
+#include <string_view>
 #include <vector>
 
-namespace irccd {
-
 /**
  * Namespace for ini related classes.
  */
-namespace ini {
+namespace irccd::ini {
 
 class document;
 
@@ -129,54 +124,40 @@
  */
 class exception : public std::exception {
 private:
-    int line_;
-    int column_;
-    std::string message_;
+	unsigned line_;
+	unsigned column_;
+	std::string message_;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param line the line
-     * \param column the column
-     * \param msg the message
-     */
-    inline exception(int line, int column, std::string msg) noexcept
-        : line_(line)
-        , column_(column)
-        , message_(std::move(msg))
-    {
-    }
+	/**
+	 * Constructor.
+	 *
+	 * \param line the line
+	 * \param column the column
+	 * \param msg the message
+	 */
+	exception(unsigned line, unsigned column, std::string msg) noexcept;
 
-    /**
-     * Get the line number.
-     *
-     * \return the line
-     */
-    inline int line() const noexcept
-    {
-        return line_;
-    }
+	/**
+	 * Get the line number.
+	 *
+	 * \return the line
+	 */
+	auto line() const noexcept -> unsigned;
 
-    /**
-     * Get the column number.
-     *
-     * \return the column
-     */
-    inline int column() const noexcept
-    {
-        return column_;
-    }
+	/**
+	 * Get the column number.
+	 *
+	 * \return the column
+	 */
+	auto column() const noexcept -> unsigned;
 
-    /**
-     * Return the raw exception message (no line and column shown).
-     *
-     * \return the exception message
-     */
-    const char* what() const noexcept override
-    {
-        return message_.c_str();
-    }
+	/**
+	 * Return the raw exception message (no line and column shown).
+	 *
+	 * \return the exception message
+	 */
+	auto what() const noexcept -> const char* override;
 };
 
 /**
@@ -188,106 +169,66 @@
  */
 class token {
 public:
-    /**
-     * \brief token type.
-     */
-    enum type {
-        include,                //!< include statement
-        section,                //!< [section]
-        word,                   //!< word without quotes
-        quoted_word,            //!< word with quotes
-        assign,                 //!< = assignment
-        list_begin,             //!< begin of list (
-        list_end,               //!< end of list )
-        comma                   //!< list separation
-    };
+	/**
+	 * \brief token type.
+	 */
+	enum type {
+		include,                //!< include statement
+		tryinclude,             //!< tryinclude statement
+		section,                //!< [section]
+		word,                   //!< word without quotes
+		quoted_word,            //!< word with quotes
+		assign,                 //!< = assignment
+		list_begin,             //!< begin of list (
+		list_end,               //!< end of list )
+		comma                   //!< list separation
+	};
 
 private:
-    type type_;
-    int line_;
-    int column_;
-    std::string value_;
+	type type_;
+	unsigned line_;
+	unsigned column_;
+	std::string value_;
 
 public:
-    /**
-     * Construct a token.
-     *
-     * \param type the type
-     * \param line the line
-     * \param column the column
-     * \param value the value
-     */
-    token(type type, int line, int column, std::string value = "") noexcept
-        : type_(type)
-        , line_(line)
-        , column_(column)
-    {
-        switch (type) {
-        case include:
-            value_ = "@include";
-            break;
-        case section:
-        case word:
-        case quoted_word:
-            value_ = value;
-            break;
-        case assign:
-            value_ = "=";
-            break;
-        case list_begin:
-            value_ = "(";
-            break;
-        case list_end:
-            value_ = ")";
-            break;
-        case comma:
-            value_ = ",";
-            break;
-        default:
-            break;
-        }
-    }
+	/**
+	 * Construct a token.
+	 *
+	 * \param type the type
+	 * \param line the line
+	 * \param column the column
+	 * \param value the value
+	 */
+	token(type type, unsigned line, unsigned column, std::string value = "") noexcept;
+
+	/**
+	 * Get the type.
+	 *
+	 * \return the type
+	 */
+	auto get_type() const noexcept -> type;
 
-    /**
-     * Get the type.
-     *
-     * \return the type
-     */
-    inline type type() const noexcept
-    {
-        return type_;
-    }
-
-    /**
-     * Get the line.
-     *
-     * \return the line
-     */
-    inline int line() const noexcept
-    {
-        return line_;
-    }
+	/**
+	 * Get the line.
+	 *
+	 * \return the line
+	 */
+	auto get_line() const noexcept -> unsigned;
 
-    /**
-     * Get the column.
-     *
-     * \return the column
-     */
-    inline int column() const noexcept
-    {
-        return column_;
-    }
+	/**
+	 * Get the column.
+	 *
+	 * \return the column
+	 */
+	auto get_column() const noexcept -> unsigned;
 
-    /**
-     * Get the value. For words, quoted words and section, the value is the
-     * content. Otherwise it's the characters parsed.
-     *
-     * \return the value
-     */
-    inline const std::string& value() const noexcept
-    {
-        return value_;
-    }
+	/**
+	 * Get the value. For words, quoted words and section, the value is the
+	 * content. Otherwise it's the characters parsed.
+	 *
+	 * \return the value
+	 */
+	auto get_value() const noexcept -> const std::string&;
 };
 
 /**
@@ -300,72 +241,48 @@
  */
 class option : public std::vector<std::string> {
 private:
-    std::string key_;
+	std::string key_;
 
 public:
-    /**
-     * Construct an empty option.
-     *
-     * \pre key must not be empty
-     * \param key the key
-     */
-    inline option(std::string key) noexcept
-        : std::vector<std::string>()
-        , key_(std::move(key))
-    {
-        assert(!key_.empty());
-    }
+	/**
+	 * Construct an empty option.
+	 *
+	 * \pre key must not be empty
+	 * \param key the key
+	 */
+	option(std::string key) noexcept;
 
-    /**
-     * Construct a single option.
-     *
-     * \pre key must not be empty
-     * \param key the key
-     * \param value the value
-     */
-    inline option(std::string key, std::string value) noexcept
-        : key_(std::move(key))
-    {
-        assert(!key_.empty());
-
-        push_back(std::move(value));
-    }
+	/**
+	 * Construct a single option.
+	 *
+	 * \pre key must not be empty
+	 * \param key the key
+	 * \param value the value
+	 */
+	option(std::string key, std::string value) noexcept;
 
-    /**
-     * Construct a list option.
-     *
-     * \pre key must not be empty
-     * \param key the key
-     * \param values the values
-     */
-    inline option(std::string key, std::vector<std::string> values) noexcept
-        : std::vector<std::string>(std::move(values))
-        , key_(std::move(key))
-    {
-        assert(!key_.empty());
-    }
+	/**
+	 * Construct a list option.
+	 *
+	 * \pre key must not be empty
+	 * \param key the key
+	 * \param values the values
+	 */
+	option(std::string key, std::vector<std::string> values) noexcept;
 
-    /**
-     * Get the option key.
-     *
-     * \return the key
-     */
-    inline const std::string& key() const noexcept
-    {
-        return key_;
-    }
+	/**
+	 * Get the option key.
+	 *
+	 * \return the key
+	 */
+	auto get_key() const noexcept -> const std::string&;
 
-    /**
-     * Get the option value.
-     *
-     * \return the value
-     */
-    inline const std::string& value() const noexcept
-    {
-        static std::string dummy;
-
-        return empty() ? dummy : (*this)[0];
-    }
+	/**
+	 * Get the option value.
+	 *
+	 * \return the value
+	 */
+	auto get_value() const noexcept -> const std::string&;
 };
 
 /**
@@ -373,116 +290,78 @@
  */
 class section : public std::vector<option> {
 private:
-    std::string key_;
+	std::string key_;
 
 public:
-    /**
-     * Construct a section with its name.
-     *
-     * \pre key must not be empty
-     * \param key the key
-     */
-    inline section(std::string key) noexcept
-        : key_(std::move(key))
-    {
-        assert(!key_.empty());
-    }
+	/**
+	 * Construct a section with its name.
+	 *
+	 * \pre key must not be empty
+	 * \param key the key
+	 */
+	section(std::string key) noexcept;
 
-    /**
-     * Get the section key.
-     *
-     * \return the key
-     */
-    inline const std::string& key() const noexcept
-    {
-        return key_;
-    }
+	/**
+	 * Get the section key.
+	 *
+	 * \return the key
+	 */
+	auto get_key() const noexcept -> const std::string&;
 
-    /**
-     * Check if the section contains a specific option.
-     *
-     * \param key the option key
-     * \return true if the option exists
-     */
-    inline bool contains(const std::string& key) const noexcept
-    {
-        return find(key) != end();
-    }
+	/**
+	 * Check if the section contains a specific option.
+	 *
+	 * \param key the option key
+	 * \return true if the option exists
+	 */
+	auto contains(std::string_view key) const noexcept -> bool;
 
-    /**
-     * Find an option or return an empty one if not found.
-     *
-     * \param key the key
-     * \return the option or empty one if not found
-     */
-    inline option get(const std::string& key) const noexcept
-    {
-        auto it = find(key);
-
-        if (it == end())
-            return option(key);
-
-        return *it;
-    }
+	/**
+	 * Find an option or return an empty one if not found.
+	 *
+	 * \param key the key
+	 * \return the option or empty one if not found
+	 */
+	auto get(std::string_view key) const noexcept -> option;
 
-    /**
-     * Find an option by key and return an iterator.
-     *
-     * \param key the key
-     * \return the iterator or end() if not found
-     */
-    inline iterator find(const std::string& key) noexcept
-    {
-        return std::find_if(begin(), end(), [&] (const auto& o) {
-            return o.key() == key;
-        });
-    }
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * \param key the key
+	 * \return the iterator or end() if not found
+	 */
+	auto find(std::string_view key) noexcept -> iterator;
 
-    /**
-     * Find an option by key and return an iterator.
-     *
-     * \param key the key
-     * \return the iterator or end() if not found
-     */
-    inline const_iterator find(const std::string& key) const noexcept
-    {
-        return std::find_if(cbegin(), cend(), [&] (const auto& o) {
-            return o.key() == key;
-        });
-    }
+	/**
+	 * Find an option by key and return an iterator.
+	 *
+	 * \param key the key
+	 * \return the iterator or end() if not found
+	 */
+	auto find(std::string_view key) const noexcept -> const_iterator;
 
-    /**
-     * Access an option at the specified key.
-     *
-     * \param key the key
-     * \return the option
-     * \pre contains(key) must return true
-     */
-    inline option& operator[](const std::string& key)
-    {
-        assert(contains(key));
-
-        return *find(key);
-    }
+	/**
+	 * Access an option at the specified key.
+	 *
+	 * \param key the key
+	 * \return the option
+	 * \pre contains(key) must return true
+	 */
+	auto operator[](std::string_view key) -> option&;
 
-    /**
-     * Overloaded function.
-     *
-     * \param key the key
-     * \return the option
-     * \pre contains(key) must return true
-     */
-    inline const option& operator[](const std::string& key) const
-    {
-        assert(contains(key));
+	/**
+	 * Overloaded function.
+	 *
+	 * \param key the key
+	 * \return the option
+	 * \pre contains(key) must return true
+	 */
+	auto operator[](std::string_view key) const -> const option&;
 
-        return *find(key);
-    }
-
-    /**
-     * Inherited operators.
-     */
-    using std::vector<option>::operator[];
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<option>::operator[];
 };
 
 /**
@@ -492,91 +371,60 @@
  */
 class document : public std::vector<section> {
 public:
-    /**
-     * Check if a document has a specific section.
-     *
-     * \param key the key
-     * \return true if the document contains the section
-     */
-    inline bool contains(const std::string& key) const noexcept
-    {
-        return find(key) != end();
-    }
+	/**
+	 * Check if a document has a specific section.
+	 *
+	 * \param key the key
+	 * \return true if the document contains the section
+	 */
+	auto contains(std::string_view key) const noexcept -> bool;
 
-    /**
-     * Find a section or return an empty one if not found.
-     *
-     * \param key the key
-     * \return the section or empty one if not found
-     */
-    inline section get(const std::string& key) const noexcept
-    {
-        auto it = find(key);
-
-        if (it == end())
-            return section(key);
+	/**
+	 * Find a section or return an empty one if not found.
+	 *
+	 * \param key the key
+	 * \return the section or empty one if not found
+	 */
+	auto get(std::string_view key) const noexcept -> section;
 
-        return *it;
-    }
-
-    /**
-     * Find a section by key and return an iterator.
-     *
-     * \param key the key
-     * \return the iterator or end() if not found
-     */
-    inline iterator find(const std::string& key) noexcept
-    {
-        return std::find_if(begin(), end(), [&] (const auto& o) {
-            return o.key() == key;
-        });
-    }
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * \param key the key
+	 * \return the iterator or end() if not found
+	 */
+	auto find(std::string_view key) noexcept -> iterator;
 
-    /**
-     * Find a section by key and return an iterator.
-     *
-     * \param key the key
-     * \return the iterator or end() if not found
-     */
-    inline const_iterator find(const std::string& key) const noexcept
-    {
-        return std::find_if(cbegin(), cend(), [&] (const auto& o) {
-            return o.key() == key;
-        });
-    }
+	/**
+	 * Find a section by key and return an iterator.
+	 *
+	 * \param key the key
+	 * \return the iterator or end() if not found
+	 */
+	auto find(std::string_view key) const noexcept -> const_iterator;
 
-    /**
-     * Access a section at the specified key.
-     *
-     * \param key the key
-     * \return the section
-     * \pre contains(key) must return true
-     */
-    inline section& operator[](const std::string& key)
-    {
-        assert(contains(key));
-
-        return *find(key);
-    }
+	/**
+	 * Access a section at the specified key.
+	 *
+	 * \param key the key
+	 * \return the section
+	 * \pre contains(key) must return true
+	 */
+	auto operator[](std::string_view key) -> section&;
 
-    /**
-     * Overloaded function.
-     *
-     * \param key the key
-     * \return the section
-     * \pre contains(key) must return true
-     */
-    inline const section& operator[](const std::string& key) const
-    {
-        assert(contains(key));
+	/**
+	 * Overloaded function.
+	 *
+	 * \param key the key
+	 * \return the section
+	 * \pre contains(key) must return true
+	 */
+	auto operator[](std::string_view key) const -> const section&;
 
-        return *find(key);
-    }
-
-    /**
-     * Inherited operators.
-     */
-    using std::vector<section>::operator[];
+	/**
+	 * Inherited operators.
+	 */
+	using std::vector<section>::operator[];
 };
 
 /**
@@ -640,8 +488,6 @@
  */
 void dump(const tokens& tokens);
 
-} // !ini
+} // !irccd::ini
 
-} // !irccd
-
-#endif // !IRCCD_COMMON_INI_HPP
+#endif // !IRCCD_INI_HPP
--- a/libirccd-core/irccd/ini_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/ini_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -44,9 +44,9 @@
  * \return the value or none if not able to convert
  */
 template <typename Int>
-inline std::optional<Int> get_uint(const ini::section& sc, const std::string& name) noexcept
+inline auto get_uint(const ini::section& sc, std::string_view name) noexcept -> std::optional<Int>
 {
-    return string_util::to_uint<Int>(sc.get(name).value());
+	return string_util::to_uint<Int>(sc.get(name).get_value());
 }
 
 /**
@@ -57,16 +57,16 @@
  * \param def the default value
  * \return the value or def if not found
  */
-inline std::string optional_string(const ini::section& sc,
-                                   const std::string& name,
-                                   const std::string& def) noexcept
+inline auto optional_string(const ini::section& sc,
+                            std::string_view name,
+                            std::string_view def) noexcept -> std::string
 {
-    const auto it = sc.find(name);
+	const auto it = sc.find(name);
 
-    if (it == sc.end())
-        return def;
+	if (it == sc.end())
+		return std::string(def);
 
-    return it->value();
+	return it->get_value();
 }
 
 /**
@@ -78,16 +78,16 @@
  * \return the value or none if not able to convert
  */
 template <typename Int>
-inline std::optional<Int> optional_uint(const ini::section& sc,
-                                          const std::string& name,
-                                          Int def) noexcept
+inline auto optional_uint(const ini::section& sc,
+                          std::string_view name,
+                          Int def) noexcept -> std::optional<Int>
 {
-    const auto it = sc.find(name);
+	const auto it = sc.find(name);
 
-    if (it == sc.end())
-        return def;
+	if (it == sc.end())
+		return def;
 
-    return string_util::to_uint<Int>(it->value());
+	return string_util::to_uint<Int>(it->get_value());
 }
 
 } // !ini_util
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libirccd-core/irccd/json_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -0,0 +1,163 @@
+/*
+ * json_util.cpp -- utilities for JSON
+ *
+ * Copyright (c) 2018 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <limits>
+#include <type_traits>
+
+#include "json_util.hpp"
+
+using nlohmann::json;
+
+namespace irccd::json_util {
+
+namespace {
+
+template <typename Int>
+auto clampi(const json& value) noexcept -> std::optional<Int>
+{
+	static_assert(std::is_signed<Int>::value, "Int must be signed");
+
+	if (!value.is_number_integer())
+		return std::nullopt;
+
+	const auto ret = value.get<std::int64_t>();
+
+	if (ret < std::numeric_limits<Int>::min() || ret > std::numeric_limits<Int>::max())
+		return std::nullopt;
+
+	return static_cast<Int>(ret);
+}
+
+template <typename Int>
+auto clampu(const json& value) noexcept -> std::optional<Int>
+{
+	static_assert(std::is_unsigned<Int>::value, "Int must be unsigned");
+
+	if (!value.is_number_unsigned())
+		return std::nullopt;
+
+	const auto ret = value.get<std::uint64_t>();
+
+	if (ret > std::numeric_limits<Int>::max())
+		return std::nullopt;
+
+	return static_cast<Int>(ret);
+}
+
+} // !namespace
+
+auto type_traits<bool>::get(const json& value) noexcept -> std::optional<bool>
+{
+	if (!value.is_boolean())
+		return std::nullopt;
+
+	return value.get<bool>();
+}
+
+auto type_traits<double>::get(const json& value) noexcept -> std::optional<double>
+{
+	if (!value.is_number_float())
+		return std::nullopt;
+
+	return value.get<double>();
+}
+
+auto type_traits<std::string>::get(const json& value) -> std::optional<std::string>
+{
+	if (!value.is_string())
+		return std::nullopt;
+
+	return value.get<std::string>();
+}
+
+auto type_traits<std::int8_t>::get(const json& value) -> std::optional<std::int8_t>
+{
+	return clampi<std::int8_t>(value);
+}
+
+auto type_traits<std::int16_t>::get(const json& value) -> std::optional<std::int16_t>
+{
+	return clampi<std::int16_t>(value);
+}
+
+auto type_traits<std::int32_t>::get(const json& value) -> std::optional<std::int32_t>
+{
+	return clampi<std::int32_t>(value);
+}
+
+auto type_traits<std::int64_t>::get(const json& value) noexcept -> std::optional<std::int64_t>
+{
+	if (!value.is_number_integer())
+		return std::nullopt;
+
+	return value.get<std::int64_t>();
+}
+
+auto type_traits<std::uint8_t>::get(const json& value) -> std::optional<std::uint8_t>
+{
+	return clampu<std::uint8_t>(value);
+}
+
+auto type_traits<std::uint16_t>::get(const json& value) -> std::optional<std::uint16_t>
+{
+	return clampu<std::uint16_t>(value);
+}
+
+auto type_traits<std::uint32_t>::get(const json& value) -> std::optional<std::uint32_t>
+{
+	return clampu<std::uint32_t>(value);
+}
+
+auto type_traits<std::uint64_t>::get(const json& value) noexcept -> std::optional<std::uint64_t>
+{
+	if (!value.is_number_unsigned())
+		return std::nullopt;
+
+	return value.get<std::uint64_t>();
+}
+
+auto pretty(const json& value, int indent) -> std::string
+{
+	switch (value.type()) {
+	case json::value_t::null:
+		return "null";
+	case json::value_t::string:
+		return value.get<std::string>();
+	case json::value_t::boolean:
+		return value.get<bool>() ? "true" : "false";
+	case json::value_t::number_integer:
+		return std::to_string(value.get<std::int64_t>());
+	case json::value_t::number_unsigned:
+		return std::to_string(value.get<std::uint64_t>());
+	case json::value_t::number_float:
+		return std::to_string(value.get<double>());
+	default:
+		return value.dump(indent);
+	}
+}
+
+auto contains(const nlohmann::json& array, const nlohmann::json& value) noexcept -> bool
+{
+	for (const auto& v : array)
+		if (v == value)
+			return true;
+
+	return false;
+}
+
+} // !irccd::json_util
--- a/libirccd-core/irccd/json_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/json_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -25,233 +25,193 @@
  */
 
 #include <cstdint>
-#include <limits>
+#include <optional>
 #include <string>
-#include <type_traits>
-
-#include <boost/optional.hpp>
 
 #include <json.hpp>
 
-namespace irccd {
-
 /**
  * \brief Utilities for JSON.
  */
-namespace json_util {
-
-/**
- * \cond JSON_UTIL_HIDDEN_SYMBOLS
- */
-
-namespace detail {
-
-template <typename Int>
-class parser_type_traits_uint : public std::true_type {
-public:
-    static boost::optional<Int> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_number_unsigned())
-            return boost::none;
-
-        const auto ret = value.get<std::uint64_t>();
-
-        if (ret > std::numeric_limits<Int>::max())
-            return boost::none;
-
-        return static_cast<Int>(ret);
-    }
-};
-
-template <typename Int>
-class parser_type_traits_int : public std::true_type {
-public:
-    static boost::optional<Int> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_number_integer())
-            return boost::none;
-
-        const auto ret = value.get<std::int64_t>();
-
-        if (ret < std::numeric_limits<Int>::min() || ret > std::numeric_limits<Int>::max())
-            return boost::none;
-
-        return static_cast<Int>(ret);
-    }
-};
-
-} // !detail
-
-/**
- * \endcond
- */
+namespace irccd::json_util {
 
 /**
  * \brief Describe how to convert a JSON value.
  *
- * This class must be specialized for every type you want to convert from JSON
+ * This traits must be specialized for every type you want to convert from JSON
  * to its native type.
  *
  * You only need to implement the get function with the following signature:
  *
  * ```cpp
- * static boost::optional<T> get(const nlohmann::json& value);
+ * static std::optional<T> get(const nlohmann::json& value);
  * ```
  *
  * The implementation should not throw an exception but return a null optional
  * instead.
  *
- * This class is already specialized for the given types:
+ * This traits is already specialized for the given types:
  *
  * - bool
  * - double
- * - std::uint(8, 16, 32, 64)
+ * - std::uint(8, 16, 32, 64)_t
  * - std::string
  */
 template <typename T>
-class parser_type_traits : public std::false_type {
-};
+struct type_traits;
 
 /**
  * \brief Specialization for `bool`.
  */
 template <>
-class parser_type_traits<bool> : public std::true_type {
-public:
-    /**
-     * Convert the JSON value to bool.
-     *
-     * \return the bool or none if not a boolean type
-     */
-    static boost::optional<bool> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_boolean())
-            return boost::none;
-
-        return value.get<bool>();
-    }
+struct type_traits<bool> {
+	/**
+	 * Convert the JSON value to bool.
+	 *
+	 * \param value the value
+	 * \return the bool or empty if not a boolean type
+	 */
+	static auto get(const nlohmann::json& value) noexcept -> std::optional<bool>;
 };
 
 /**
  * \brief Specialization for `double`.
  */
 template <>
-class parser_type_traits<double> : public std::true_type {
-public:
-    /**
-     * Convert the JSON value to bool.
-     *
-     * \return the double or none if not a double type
-     */
-    static boost::optional<double> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_number_float())
-            return boost::none;
-
-        return value.get<double>();
-    }
+struct type_traits<double> {
+	/**
+	 * Convert the JSON value to bool.
+	 *
+	 * \param value the value
+	 * \return the double or empty if not a double type
+	 */
+	static auto get(const nlohmann::json& value) noexcept -> std::optional<double>;
 };
 
 /**
  * \brief Specialization for `std::string`.
  */
 template <>
-class parser_type_traits<std::string> : public std::true_type {
-public:
-    /**
-     * Convert the JSON value to bool.
-     *
-     * \return the string or none if not a string type
-     */
-    static boost::optional<std::string> get(const nlohmann::json& value)
-    {
-        if (!value.is_string())
-            return boost::none;
-
-        return value.get<std::string>();
-    }
+struct type_traits<std::string> {
+	/**
+	 * Convert the JSON value to std::string.
+	 *
+	 * \param value the value
+	 * \return the string or empty if not a string type
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::string>;
 };
 
 /**
  * \brief Specialization for `std::int8_t`.
  */
 template <>
-class parser_type_traits<std::int8_t> : public detail::parser_type_traits_int<std::int8_t> {
+struct type_traits<std::int8_t> {
+	/**
+	 * Convert the JSON value to std::int8_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::int8_t>;
 };
 
 /**
  * \brief Specialization for `std::int16_t`.
  */
 template <>
-class parser_type_traits<std::int16_t> : public detail::parser_type_traits_int<std::int16_t> {
+struct type_traits<std::int16_t> {
+	/**
+	 * Convert the JSON value to std::int16_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::int16_t>;
 };
 
 /**
  * \brief Specialization for `std::int32_t`.
  */
 template <>
-class parser_type_traits<std::int32_t> : public detail::parser_type_traits_int<std::int32_t> {
+struct type_traits<std::int32_t> {
+	/**
+	 * Convert the JSON value to std::int32_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::int32_t>;
 };
 
 /**
  * \brief Specialization for `std::int64_t`.
  */
 template <>
-class parser_type_traits<std::int64_t> : public std::true_type {
-public:
-    /**
-     * Convert the JSON value to std::int64_t.
-     *
-     * \return the int or none if not a int type
-     */
-    static boost::optional<std::int64_t> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_number_integer())
-            return boost::none;
-
-        return value.get<std::int64_t>();
-    }
+struct type_traits<std::int64_t> {
+	/**
+	 * Convert the JSON value to std::int64_t.
+	 *
+	 * \param value the value
+	 * \return the int or empty if not a int type
+	 */
+	static auto get(const nlohmann::json& value) noexcept -> std::optional<std::int64_t>;
 };
 
 /**
- * \brief Specialization for `std::int8_t`.
+ * \brief Specialization for `std::uint8_t`.
  */
 template <>
-class parser_type_traits<std::uint8_t> : public detail::parser_type_traits_uint<std::uint8_t> {
+struct type_traits<std::uint8_t> {
+	/**
+	 * Convert the JSON value to std::uint8_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::uint8_t>;
 };
 
 /**
- * \brief Specialization for `std::int16_t`.
+ * \brief Specialization for `std::uint16_t`.
  */
 template <>
-class parser_type_traits<std::uint16_t> : public detail::parser_type_traits_uint<std::uint16_t> {
+struct type_traits<std::uint16_t> {
+	/**
+	 * Convert the JSON value to std::uint16_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::uint16_t>;
 };
 
 /**
  * \brief Specialization for `std::int32_t`.
  */
 template <>
-class parser_type_traits<std::uint32_t> : public detail::parser_type_traits_uint<std::uint32_t> {
+struct type_traits<std::uint32_t> {
+	/**
+	 * Convert the JSON value to std::uint32_t.
+	 *
+	 * \param value the value
+	 * \return the value or empty if value does not fit between the range
+	 */
+	static auto get(const nlohmann::json& value) -> std::optional<std::uint32_t>;
 };
 
 /**
- * \brief Specialization for `std::int64_t`.
+ * \brief Specialization for `std::uint64_t`.
  */
 template <>
-class parser_type_traits<std::uint64_t> : public std::true_type {
-public:
-    /**
-     * Convert the JSON value to std::uint64_t.
-     *
-     * \return the int or none if not a int type
-     */
-    static boost::optional<std::uint64_t> get(const nlohmann::json& value) noexcept
-    {
-        if (!value.is_number_unsigned())
-            return boost::none;
-
-        return value.get<std::uint64_t>();
-    }
+struct type_traits<std::uint64_t> {
+	/**
+	 * Convert the JSON value to std::uint64_t.
+	 *
+	 * \param value the value
+	 * \return the int or empty if not a int type
+	 */
+	static auto get(const nlohmann::json& value) noexcept -> std::optional<std::uint64_t>;
 };
 
 /**
@@ -260,59 +220,53 @@
  * This class helps destructuring insecure JSON input by returning optional
  * values if they are not present or invalid.
  */
-class document : public nlohmann::json {
+class deserializer : public nlohmann::json {
 public:
-    /**
-     * Constructor.
-     *
-     * \param object the object
-     */
-    inline document(nlohmann::json object)
-        : nlohmann::json(std::move(object))
-    {
-    }
+	/**
+	 * Constructor.
+	 */
+	deserializer(const nlohmann::json& obj)
+		: nlohmann::json(obj)
+	{
+	}
 
-    /**
-     * Get a value from the document object.
-     *
-     * \param key the property key
-     * \return the value or boost::none if not found or not convertible
-     */
-    template <typename Type>
-    inline boost::optional<Type> get(const std::string& key) const noexcept
-    {
-        static_assert(parser_type_traits<Type>::value, "type not supported");
+	/**
+	 * Get a value from the document object.
+	 *
+	 * \param key the property key
+	 * \return the value or std::nullopt if not found or not convertible
+	 */
+	template <typename Type>
+	auto get(const std::string& key) const noexcept -> std::optional<Type>
+	{
+		const auto it = find(key);
 
-        const auto it = find(key);
+		if (it == end())
+			return std::nullopt;
 
-        if (it == end())
-            return boost::none;
-
-        return parser_type_traits<Type>::get(*it);
-    }
+		return type_traits<Type>::get(*it);
+	}
 
-    /**
-     * Get an optional value from the document object.
-     *
-     * If the value is undefined, the default value is returned. Otherwise, if
-     * the value is not in the given type, boost::none is returned.
-     *
-     * \param key the property key
-     * \param def the default value if property is undefined
-     * \return the value, boost::none or def
-     */
-    template <typename Type, typename DefaultValue>
-    inline boost::optional<Type> optional(const std::string& key, DefaultValue&& def) const noexcept
-    {
-        static_assert(parser_type_traits<Type>::value, "type not supported");
+	/**
+	 * Get an optional value from the document object.
+	 *
+	 * If the value is undefined, the default value is returned. Otherwise, if
+	 * the value is not in the given type, std::nullopt is returned.
+	 *
+	 * \param key the property key
+	 * \param def the default value if property is undefined
+	 * \return the value, std::nullopt or def
+	 */
+	template <typename Type, typename DefaultValue>
+	auto optional(const std::string& key, DefaultValue&& def) const noexcept -> std::optional<Type>
+	{
+		const auto it = find(key);
 
-        const auto it = find(key);
+		if (it == end())
+			return std::optional<Type>(std::forward<DefaultValue>(def));
 
-        if (it == end())
-            return boost::optional<Type>(std::forward<DefaultValue>(def));
-
-        return parser_type_traits<Type>::get(*it);
-    }
+		return type_traits<Type>::get(*it);
+	}
 };
 
 /**
@@ -323,25 +277,7 @@
  * \param indent the optional indent for objects/arrays
  * \return the string
  */
-inline std::string pretty(const nlohmann::json& value, int indent = 4)
-{
-    switch (value.type()) {
-    case nlohmann::json::value_t::null:
-        return "null";
-    case nlohmann::json::value_t::string:
-        return value.get<std::string>();
-    case nlohmann::json::value_t::boolean:
-        return value.get<bool>() ? "true" : "false";
-    case nlohmann::json::value_t::number_integer:
-        return std::to_string(value.get<std::int64_t>());
-    case nlohmann::json::value_t::number_unsigned:
-        return std::to_string(value.get<std::uint64_t>());
-    case nlohmann::json::value_t::number_float:
-        return std::to_string(value.get<double>());
-    default:
-        return value.dump(indent);
-    }
-}
+auto pretty(const nlohmann::json& value, int indent = 4) -> std::string;
 
 /**
  * Check if a JSON array contains a specific value in any order.
@@ -350,17 +286,8 @@
  * \param value the JSON value
  * \return true if value is present
  */
-inline bool contains(const nlohmann::json& array, const nlohmann::json& value) noexcept
-{
-    for (const auto& v : array)
-        if (v == value)
-            return true;
+auto contains(const nlohmann::json& array, const nlohmann::json& value) noexcept -> bool;
 
-    return false;
-}
-
-} // !json_util
-
-} // !irccd
+} // !irccd::json_util
 
 #endif // !IRCCD_JSON_UTIL_HPP
--- a/libirccd-core/irccd/socket_acceptor.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/socket_acceptor.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,7 +29,7 @@
 #include "acceptor.hpp"
 #include "socket_stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief Socket stream acceptor interface.
@@ -38,75 +38,66 @@
 template <typename Protocol>
 class socket_acceptor : public acceptor {
 public:
-    /**
-     * Convenient endpoint alias.
-     */
-    using endpoint = typename Protocol::endpoint;
+	/**
+	 * Convenient endpoint alias.
+	 */
+	using endpoint = typename Protocol::endpoint;
 
-    /**
-     * Convenient acceptor alias.
-     */
-    using acceptor = typename Protocol::acceptor;
+	/**
+	 * Convenient acceptor alias.
+	 */
+	using acceptor = typename Protocol::acceptor;
 
-    /**
-     * Convenient socket alias.
-     */
-    using socket = typename Protocol::socket;
+	/**
+	 * Convenient socket alias.
+	 */
+	using socket = typename Protocol::socket;
 
 private:
-    acceptor acceptor_;
+	acceptor acceptor_;
 
 #if !defined(NDEBUG)
-    bool is_accepting_{false};
+	bool is_accepting_{false};
 #endif
 
 protected:
-    /**
-     * Helper to accept on the real underlying socket.
-     *
-     * \param socket the real socket
-     * \param handler the handler
-     */
-    template <typename Socket, typename Handler>
-    void do_accept(Socket& socket, Handler handler);
+	/**
+	 * Helper to accept on the real underlying socket.
+	 *
+	 * \param socket the real socket
+	 * \param handler the handler
+	 */
+	template <typename Socket, typename Handler>
+	void do_accept(Socket& socket, Handler handler);
 
 public:
-    /**
-     * Construct the socket_acceptor.
-     *
-     * \pre acceptor must be ready (is_open() returns true)
-     * \param acceptor the Boost.Asio acceptor
-     */
-    socket_acceptor(acceptor acceptor) noexcept
-        : acceptor_(std::move(acceptor))
-    {
-        assert(acceptor_.is_open());
-    }
+	/**
+	 * Construct the socket_acceptor.
+	 *
+	 * \pre acceptor must be ready (is_open() returns true)
+	 * \param acceptor the Boost.Asio acceptor
+	 */
+	socket_acceptor(acceptor acceptor) noexcept;
 
-    /**
-     * Get the underlying acceptor.
-     *
-     * \return the acceptor
-     */
-    auto get_acceptor() const noexcept -> const acceptor&
-    {
-        return acceptor_;
-    }
+	/**
+	 * Get the underlying acceptor.
+	 *
+	 * \return the acceptor
+	 */
+	auto get_acceptor() const noexcept -> const acceptor&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the acceptor
-     */
-    auto get_acceptor() noexcept -> acceptor&
-    {
-        return acceptor_;
-    }
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the acceptor
+	 */
+	auto get_acceptor() noexcept -> acceptor&;
 
-    /**
-     * \copydoc acceptor::accept
-     */
-    void accept(accept_handler handler) override;
+	/**
+	 * \copydoc acceptor::accept
+	 */
+
+	void accept(handler handler) override;
 };
 
 template <typename Protocol>
@@ -114,30 +105,49 @@
 void socket_acceptor<Protocol>::do_accept(Socket& socket, Handler handler)
 {
 #if !defined(NDEBUG)
-    assert(!is_accepting_);
+	assert(!is_accepting_);
 
-    is_accepting_ = true;
+	is_accepting_ = true;
 #endif
 
-    acceptor_.async_accept(socket, [this, handler] (auto code) {
+	acceptor_.async_accept(socket, [this, handler] (auto code) {
 #if !defined(NDEBUG)
-        is_accepting_ = false;
+		is_accepting_ = false;
 #endif
-        (void)this;
-        handler(code);
-    });
+		(void)this;
+		handler(code);
+	});
+}
+
+template <typename Protocol>
+socket_acceptor<Protocol>::socket_acceptor(acceptor acceptor) noexcept
+	: acceptor_(std::move(acceptor))
+{
+	assert(acceptor_.is_open());
 }
 
 template <typename Protocol>
-void socket_acceptor<Protocol>::accept(accept_handler handler)
+auto socket_acceptor<Protocol>::get_acceptor() const noexcept -> const acceptor&
 {
-    assert(handler);
+	return acceptor_;
+}
+
+template <typename Protocol>
+auto socket_acceptor<Protocol>::get_acceptor() noexcept -> acceptor&
+{
+	return acceptor_;
+}
 
-    const auto client = std::make_shared<socket_stream<socket>>(acceptor_.get_io_service());
+template <typename Protocol>
+void socket_acceptor<Protocol>::accept(handler handler)
+{
+	assert(handler);
 
-    do_accept(client->get_socket(), [client, handler] (auto code) {
-        handler(std::move(code), code ? nullptr : std::move(client));
-    });
+	const auto client = std::make_shared<socket_stream<socket>>(acceptor_.get_io_service());
+
+	do_accept(client->get_socket(), [client, handler] (auto code) {
+		handler(std::move(code), code ? nullptr : std::move(client));
+	});
 }
 
 /**
@@ -154,6 +164,6 @@
 
 #endif
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_SOCKET_ACCEPTOR_HPP
--- a/libirccd-core/irccd/socket_connector.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/socket_connector.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,7 +31,7 @@
 #include "connector.hpp"
 #include "socket_stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief Socket connection interface.
@@ -40,83 +40,69 @@
 template <typename Protocol>
 class socket_connector : public connector {
 public:
-    /**
-     * Convenient endpoint alias.
-     */
-    using endpoint = typename Protocol::endpoint;
+	/**
+	 * Convenient endpoint alias.
+	 */
+	using endpoint = typename Protocol::endpoint;
 
-    /**
-     * Convenient socket alias.
-     */
-    using socket = typename Protocol::socket;
+	/**
+	 * Convenient socket alias.
+	 */
+	using socket = typename Protocol::socket;
 
 private:
-    boost::asio::io_service& service_;
-    std::vector<endpoint> endpoints_;
+	boost::asio::io_service& service_;
+	std::vector<endpoint> endpoints_;
 
 #if !defined(NDEBUG)
-    bool is_connecting_{false};
+	bool is_connecting_{false};
 #endif
 
 protected:
-    /**
-     * Start trying to connect to all endpoints.
-     *
-     * \param socket the underlying socket
-     * \param handler handler with `void f(std::error_code)` signature
-     */
-    template <typename Socket, typename Handler>
-    void do_connect(Socket& socket, Handler handler);
+	/**
+	 * Start trying to connect to all endpoints.
+	 *
+	 * \param socket the underlying socket
+	 * \param handler handler with `void f(std::error_code)` signature
+	 */
+	template <typename Socket, typename Handler>
+	void do_connect(Socket& socket, Handler handler);
 
 public:
-    /**
-     * Construct the socket connector with only one endpoint.
-     *
-     * \param service the service
-     * \param endpoint the unique endpoint
-     */
-    socket_connector(boost::asio::io_service& service, endpoint endpoint) noexcept
-        : service_(service)
-        , endpoints_{std::move(endpoint)}
-    {
-    }
+	/**
+	 * Construct the socket connector with only one endpoint.
+	 *
+	 * \param service the service
+	 * \param endpoint the unique endpoint
+	 */
+	socket_connector(boost::asio::io_service& service, endpoint endpoint) noexcept;
 
-    /**
-     * Construct the socket connection.
-     *
-     * \param service the service
-     * \param eps the endpoints
-     */
-    socket_connector(boost::asio::io_service& service, std::vector<endpoint> eps) noexcept
-        : service_(service)
-        , endpoints_(std::move(eps))
-    {
-    }
+	/**
+	 * Construct the socket connection.
+	 *
+	 * \param service the service
+	 * \param eps the endpoints
+	 */
+	socket_connector(boost::asio::io_service& service, std::vector<endpoint> eps) noexcept;
 
-    /**
-     * Get the underlying I/O service.
-     *
-     * \return the I/O service
-     */
-    auto get_io_service() const noexcept -> const boost::asio::io_service&
-    {
-        return service_;
-    }
+	/**
+	 * Get the underlying I/O service.
+	 *
+	 * \return the I/O service
+	 */
+	auto get_io_service() const noexcept -> const boost::asio::io_service&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the I/O service
-     */
-    auto get_io_service() noexcept -> boost::asio::io_service&
-    {
-        return service_;
-    }
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the I/O service
+	 */
+	auto get_io_service() noexcept -> boost::asio::io_service&;
 
-    /**
-     * \copydoc connector::connect
-     */
-    void connect(connect_handler handler);
+	/**
+	 * \copydoc connector::connect
+	 */
+	void connect(handler handler);
 };
 
 template <typename Protocol>
@@ -124,33 +110,59 @@
 void socket_connector<Protocol>::do_connect(Socket& socket, Handler handler)
 {
 #if !defined(NDEBUG)
-    assert(!is_connecting_);
+	assert(!is_connecting_);
 
-    is_connecting_ = true;
+	is_connecting_ = true;
+#endif
+
+	boost::asio::async_connect(socket, endpoints_.begin(), endpoints_.end(), [this, handler] (auto code, auto ep) {
+#if !defined(NDEBUG)
+		is_connecting_ = false;
 #endif
 
-    boost::asio::async_connect(socket, endpoints_.begin(), endpoints_.end(), [this, handler] (auto code, auto ep) {
-#if !defined(NDEBUG)
-        is_connecting_ = false;
-#endif
+		if (ep == endpoints_.end())
+			handler(make_error_code(std::errc::host_unreachable));
+		else
+			handler(code);
+	});
+}
 
-        if (ep == endpoints_.end())
-            handler(make_error_code(std::errc::host_unreachable));
-        else
-            handler(code);
-    });
+template <typename Protocol>
+socket_connector<Protocol>::socket_connector(boost::asio::io_service& service, endpoint endpoint) noexcept
+	: service_(service)
+	, endpoints_{std::move(endpoint)}
+{
 }
 
 template <typename Protocol>
-void socket_connector<Protocol>::connect(connect_handler handler)
+socket_connector<Protocol>::socket_connector(boost::asio::io_service& service, std::vector<endpoint> eps) noexcept
+	: service_(service)
+	, endpoints_(std::move(eps))
 {
-    assert(handler);
+}
+
+template <typename Protocol>
+auto socket_connector<Protocol>::get_io_service() const noexcept -> const boost::asio::io_service&
+{
+	return service_;
+}
 
-    const auto stream = std::make_shared<socket_stream<socket>>(service_);
+template <typename Protocol>
+auto socket_connector<Protocol>::get_io_service() noexcept -> boost::asio::io_service&
+{
+	return service_;
+}
 
-    do_connect(stream->get_socket(), [handler, stream] (auto code) {
-        handler(code, code ? nullptr : std::move(stream));
-    });
+template <typename Protocol>
+void socket_connector<Protocol>::connect(handler handler)
+{
+	assert(handler);
+
+	const auto stream = std::make_shared<socket_stream<socket>>(service_);
+
+	do_connect(stream->get_socket(), [handler, stream] (auto code) {
+		handler(code, code ? nullptr : std::move(stream));
+	});
 }
 
 /**
@@ -167,6 +179,6 @@
 
 #endif
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_SOCKET_CONNECTOR_HPP
--- a/libirccd-core/irccd/socket_stream.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/socket_stream.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,7 +36,7 @@
 
 #include "stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief Socket implementation interface.
@@ -47,157 +47,167 @@
 template <typename Socket>
 class socket_stream : public stream {
 private:
-    Socket socket_;
-    boost::asio::streambuf input_;
-    std::string output_;
+	Socket socket_;
+	boost::asio::streambuf input_;
+	std::string output_;
 
 #if !defined(NDEBUG)
-    bool is_receiving_{false};
-    bool is_sending_{false};
+	bool is_receiving_{false};
+	bool is_sending_{false};
 #endif
 
-    void handle_read(std::error_code, std::size_t, read_handler);
-    void handle_write(std::error_code, std::size_t, write_handler);
+	void handle_read(std::error_code, std::size_t, stream::read_handler);
+	void handle_write(std::error_code, std::size_t, stream::write_handler);
 
 public:
-    /**
-     * Create the socket stream.
-     *
-     * \param args the Socket constructor arguments
-     */
-    template <typename... Args>
-    socket_stream(Args&&... args)
-        : socket_(std::forward<Args>(args)...)
-    {
-    }
+	/**
+	 * Create the socket stream.
+	 *
+	 * \param args the Socket constructor arguments
+	 */
+	template <typename... Args>
+	socket_stream(Args&&... args);
+
+	/**
+	 * Get the underlying socket.
+	 *
+	 * \return the socket
+	 */
+	auto get_socket() const noexcept -> const Socket&;
 
-    /**
-     * Get the underlying socket.
-     *
-     * \return the socket
-     */
-    auto get_socket() const noexcept -> const Socket&
-    {
-        return socket_;
-    }
+	/**
+	 * Overloaded function
+	 *
+	 * \return the socket
+	 */
+	auto get_socket() noexcept -> Socket&;
 
-    /**
-     * Overloaded function
-     *
-     * \return the socket
-     */
-    auto get_socket() noexcept -> Socket&
-    {
-        return socket_;
-    }
+	/**
+	 * \copydoc stream::read
+	 */
+	void read(read_handler handler) override;
 
-    /**
-     * \copydoc stream::read
-     */
-    void read(read_handler handler) override;
-
-    /**
-     * \copydoc stream::write
-     */
-    void write(const nlohmann::json& json, write_handler handler) override;
+	/**
+	 * \copydoc stream::write
+	 */
+	void write(const nlohmann::json& json, write_handler handler) override;
 };
 
 template <typename Socket>
 void socket_stream<Socket>::handle_read(std::error_code code,
                                         std::size_t xfer,
-                                        read_handler handler)
+                                        stream::read_handler handler)
 {
 #if !defined(NDEBUG)
-    is_receiving_ = false;
+	is_receiving_ = false;
 #endif
 
-    if (xfer == 0U) {
-        handler(make_error_code(std::errc::not_connected), nullptr);
-        return;
-    }
-    if (code) {
-        handler(code, nullptr);
-        return;
-    }
+	if (xfer == 0U) {
+		handler(make_error_code(std::errc::not_connected), nullptr);
+		return;
+	}
+	if (code) {
+		handler(code, nullptr);
+		return;
+	}
 
-    // 1. Convert the buffer safely.
-    std::string buffer;
+	// 1. Convert the buffer safely.
+	std::string buffer;
 
-    try {
-        buffer = std::string(
-            boost::asio::buffers_begin(input_.data()),
-            boost::asio::buffers_begin(input_.data()) + xfer - /* \r\n\r\n */ 4
-        );
+	try {
+		buffer = std::string(
+			boost::asio::buffers_begin(input_.data()),
+			boost::asio::buffers_begin(input_.data()) + xfer - /* \r\n\r\n */ 4
+		);
 
-        input_.consume(xfer);
-    } catch (const std::bad_alloc&) {
-        handler(make_error_code(std::errc::not_enough_memory), nullptr);
-        return;
-    }
+		input_.consume(xfer);
+	} catch (const std::bad_alloc&) {
+		handler(make_error_code(std::errc::not_enough_memory), nullptr);
+		return;
+	}
 
-    // 2. Convert to JSON.
-    nlohmann::json doc;
+	// 2. Convert to JSON.
+	nlohmann::json doc;
 
-    try {
-        doc = nlohmann::json::parse(buffer);
-    } catch (const std::exception&) {
-        handler(make_error_code(std::errc::invalid_argument), nullptr);
-        return;
-    }
+	try {
+		doc = nlohmann::json::parse(buffer);
+	} catch (const std::exception&) {
+		handler(make_error_code(std::errc::invalid_argument), nullptr);
+		return;
+	}
 
-    if (!doc.is_object())
-        handler(make_error_code(std::errc::invalid_argument), nullptr);
-    else
-        handler(std::error_code(), std::move(doc));
+	if (!doc.is_object())
+		handler(make_error_code(std::errc::invalid_argument), nullptr);
+	else
+		handler(std::error_code(), std::move(doc));
 }
 
 template <typename Socket>
 void socket_stream<Socket>::handle_write(std::error_code code,
                                          std::size_t xfer,
-                                         write_handler handler)
+                                         stream::write_handler handler)
 {
 #if !defined(NDEBUG)
-    is_sending_ = false;
+	is_sending_ = false;
 #endif
 
-    if (xfer == 0)
-        handler(make_error_code(std::errc::not_connected));
-    else
-        handler(code);
+	if (xfer == 0)
+		handler(make_error_code(std::errc::not_connected));
+	else
+		handler(code);
+}
+
+template <typename Socket>
+template <typename... Args>
+socket_stream<Socket>::socket_stream(Args&&... args)
+	: socket_(std::forward<Args>(args)...)
+{
+}
+
+template <typename Socket>
+auto socket_stream<Socket>::get_socket() const noexcept -> const Socket&
+{
+	return socket_;
+}
+
+template <typename Socket>
+auto socket_stream<Socket>::get_socket() noexcept -> Socket&
+{
+	return socket_;
 }
 
 template <typename Socket>
-void socket_stream<Socket>::read(read_handler handler)
+void socket_stream<Socket>::read(stream::read_handler handler)
 {
 #if !defined(NDEBUG)
-    assert(!is_receiving_);
-    assert(handler);
+	assert(!is_receiving_);
+	assert(handler);
 
-    is_receiving_ = true;
+	is_receiving_ = true;
 #endif
 
-    boost::asio::async_read_until(get_socket(), input_, "\r\n\r\n", [this, handler] (auto code, auto xfer) {
-        handle_read(code, xfer, std::move(handler));
-    });
+	boost::asio::async_read_until(get_socket(), input_, "\r\n\r\n", [this, handler] (auto code, auto xfer) {
+		handle_read(code, xfer, std::move(handler));
+	});
 }
 
 template <typename Socket>
-void socket_stream<Socket>::write(const nlohmann::json& json, write_handler handler)
+void socket_stream<Socket>::write(const nlohmann::json& json, stream::write_handler handler)
 {
 #if !defined(NDEBUG)
-    assert(!is_sending_);
-    assert(handler);
+	assert(!is_sending_);
+	assert(handler);
 
-    is_sending_ = true;
+	is_sending_ = true;
 #endif
 
-    output_ = json.dump(0) + "\r\n\r\n";
+	output_ = json.dump(0) + "\r\n\r\n";
 
-    const auto buffer = boost::asio::buffer(output_.data(), output_.size());
+	const auto buffer = boost::asio::buffer(output_.data(), output_.size());
 
-    boost::asio::async_write(get_socket(), buffer, [this, handler] (auto code, auto xfer) {
-        handle_write(code, xfer, std::move(handler));
-    });
+	boost::asio::async_write(get_socket(), buffer, [this, handler] (auto code, auto xfer) {
+		handle_write(code, xfer, std::move(handler));
+	});
 }
 
 /**
@@ -214,6 +224,6 @@
 
 #endif
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_SOCKET_STREAM_HPP
--- a/libirccd-core/irccd/stream.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/stream.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,17 +29,7 @@
 
 #include "json.hpp"
 
-namespace irccd::io {
-
-/**
- * \brief Read completion handler.
- */
-using read_handler = std::function<void (std::error_code, nlohmann::json)>;
-
-/**
- * \brief Write completion handler.
- */
-using write_handler = std::function<void (std::error_code)>;
+namespace irccd {
 
 /**
  * \brief Abstract stream interface
@@ -51,6 +41,16 @@
  */
 class stream {
 public:
+	/**
+	 * \brief Read completion handler.
+	 */
+	using read_handler = std::function<void (std::error_code, nlohmann::json)>;
+
+	/**
+	 * \brief Write completion handler.
+	 */
+	using write_handler = std::function<void (std::error_code)>;
+
     /**
      * Default constructor.
      */
@@ -82,6 +82,6 @@
     virtual void write(const nlohmann::json& json, write_handler handler) = 0;
 };
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_COMMON_STREAM_HPP
--- a/libirccd-core/irccd/string_util.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/string_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -21,11 +21,11 @@
 #include "sysconfig.hpp"
 
 #if defined(IRCCD_HAVE_POPEN)
-#   include <array>
-#   include <cerrno>
-#   include <cstring>
-#   include <functional>
-#   include <memory>
+#	include <array>
+#	include <cerrno>
+#	include <cstring>
+#	include <functional>
+#	include <memory>
 #endif
 
 #include <cassert>
@@ -36,360 +36,358 @@
 
 using namespace std::string_literals;
 
-namespace irccd {
-
-namespace string_util {
+namespace irccd::string_util {
 
 // {{{ subst
 
 namespace {
 
 const std::unordered_map<std::string_view, int> irc_colors{
-    { "white",      0   },
-    { "black",      1   },
-    { "blue",       2   },
-    { "green",      3   },
-    { "red",        4   },
-    { "brown",      5   },
-    { "purple",     6   },
-    { "orange",     7   },
-    { "yellow",     8   },
-    { "lightgreen", 9   },
-    { "cyan",       10  },
-    { "lightcyan",  11  },
-    { "lightblue",  12  },
-    { "pink",       13  },
-    { "grey",       14  },
-    { "lightgrey",  15  }
+	{ "white",      0   },
+	{ "black",      1   },
+	{ "blue",       2   },
+	{ "green",      3   },
+	{ "red",        4   },
+	{ "brown",      5   },
+	{ "purple",     6   },
+	{ "orange",     7   },
+	{ "yellow",     8   },
+	{ "lightgreen", 9   },
+	{ "cyan",       10  },
+	{ "lightcyan",  11  },
+	{ "lightblue",  12  },
+	{ "pink",       13  },
+	{ "grey",       14  },
+	{ "lightgrey",  15  }
 };
 
 const std::unordered_map<std::string_view, char> irc_attributes{
-    { "bold",       '\x02'  },
-    { "italic",     '\x09'  },
-    { "strike",     '\x13'  },
-    { "reset",      '\x0f'  },
-    { "underline",  '\x15'  },
-    { "underline2", '\x1f'  },
-    { "reverse",    '\x16'  }
+	{ "bold",       '\x02'  },
+	{ "italic",     '\x09'  },
+	{ "strike",     '\x13'  },
+	{ "reset",      '\x0f'  },
+	{ "underline",  '\x15'  },
+	{ "underline2", '\x1f'  },
+	{ "reverse",    '\x16'  }
 };
 
 const std::unordered_map<std::string_view, unsigned> shell_colors{
-    { "black",      30  },
-    { "red",        31  },
-    { "green",      32  },
-    { "orange",     33  },
-    { "blue",       34  },
-    { "purple",     35  },
-    { "cyan",       36  },
-    { "white",      37  },
-    { "default",    39  },
+	{ "black",      30  },
+	{ "red",        31  },
+	{ "green",      32  },
+	{ "orange",     33  },
+	{ "blue",       34  },
+	{ "purple",     35  },
+	{ "cyan",       36  },
+	{ "white",      37  },
+	{ "default",    39  },
 };
 
 const std::unordered_map<std::string_view, unsigned> shell_attributes{
-    { "bold",       1   },
-    { "dim",        2   },
-    { "underline",  4   },
-    { "blink",      5   },
-    { "reverse",    7   },
-    { "hidden",     8   }
+	{ "bold",       1   },
+	{ "dim",        2   },
+	{ "underline",  4   },
+	{ "blink",      5   },
+	{ "reverse",    7   },
+	{ "hidden",     8   }
 };
 
 auto is_reserved(char token) noexcept -> bool
 {
-    return token == '#' || token == '@' || token == '$' || token == '!';
+	return token == '#' || token == '@' || token == '$' || token == '!';
 }
 
 auto subst_date(const std::string& text, const subst& params) -> std::string
 {
-    std::ostringstream oss;
+	std::ostringstream oss;
 
 #if defined(IRCCD_HAVE_STD_PUT_TIME)
-    oss << std::put_time(std::localtime(&params.time), text.c_str());
+	oss << std::put_time(std::localtime(&params.time), text.c_str());
 #else
-    /*
-     * Quick and dirty hack because old version of GCC does not have this
-     * function.
-     */
-    char buffer[4096];
+	/*
+	 * Quick and dirty hack because old version of GCC does not have this
+	 * function.
+	 */
+	char buffer[4096];
 
-    std::strftime(buffer, sizeof (buffer) - 1, text.c_str(), std::localtime(&params.time));
+	std::strftime(buffer, sizeof (buffer) - 1, text.c_str(), std::localtime(&params.time));
 
-    oss << buffer;
+	oss << buffer;
 #endif
 
-    return oss.str();
+	return oss.str();
 }
 
 auto subst_keywords(const std::string& content, const subst& params) -> std::string
 {
-    auto value = params.keywords.find(std::string(content));
+	const auto value = params.keywords.find(std::string(content));
 
-    if (value != params.keywords.end())
-        return value->second;
+	if (value != params.keywords.end())
+		return value->second;
 
-    return "";
+	return "";
 }
 
-std::string subst_env(const std::string& content)
+auto subst_env(const std::string& content) -> std::string
 {
-    auto value = std::getenv(content.c_str());
+	const auto value = std::getenv(content.c_str());
 
-    if (value != nullptr)
-        return value;
+	if (value != nullptr)
+		return value;
 
-    return "";
+	return "";
 }
 
-std::string subst_irc_attrs(const std::string& content)
+auto subst_irc_attrs(const std::string& content) -> std::string
 {
-    auto list = split(content, ",");
+	auto list = split(content, ",");
 
-    // @{} means reset.
-    if (list.empty())
-        return std::string(1, irc_attributes.at("reset"));
+	// @{} means reset.
+	if (list.empty())
+		return std::string(1, irc_attributes.at("reset"));
 
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    // Remove useless spaces.
-    std::transform(list.begin(), list.end(), list.begin(), strip);
+	// Remove useless spaces.
+	std::transform(list.begin(), list.end(), list.begin(), strip);
 
-    /*
-     * 0: foreground
-     * 1: background
-     * 2-n: attributes
-     */
-    auto foreground = list[0];
-    if (!foreground.empty() || list.size() >= 2) {
-        // Color sequence.
-        oss << '\x03';
+	/*
+	 * 0: foreground
+	 * 1: background
+	 * 2-n: attributes
+	 */
+	auto foreground = list[0];
+	if (!foreground.empty() || list.size() >= 2) {
+		// Color sequence.
+		oss << '\x03';
 
-        // Foreground.
-        auto it = irc_colors.find(foreground);
-        if (it != irc_colors.end())
-            oss << it->second;
+		// Foreground.
+		auto it = irc_colors.find(foreground);
+		if (it != irc_colors.end())
+			oss << it->second;
 
-        // Background.
-        if (list.size() >= 2 && (it = irc_colors.find(list[1])) != irc_colors.end())
-            oss << "," << it->second;
+		// Background.
+		if (list.size() >= 2 && (it = irc_colors.find(list[1])) != irc_colors.end())
+			oss << "," << it->second;
 
-        // Attributes.
-        for (std::size_t i = 2; i < list.size(); ++i) {
-            auto attribute = irc_attributes.find(list[i]);
+		// Attributes.
+		for (std::size_t i = 2; i < list.size(); ++i) {
+			auto attribute = irc_attributes.find(list[i]);
 
-            if (attribute != irc_attributes.end())
-                oss << attribute->second;
-        }
-    }
+			if (attribute != irc_attributes.end())
+				oss << attribute->second;
+		}
+	}
 
-    return oss.str();
+	return oss.str();
 }
 
-std::string subst_shell_attrs(const std::string& content)
+auto subst_shell_attrs(const std::string& content) -> std::string
 {
 #if !BOOST_OS_WINDOWS
-    auto list = split(content, ",");
+	auto list = split(content, ",");
 
-    if (list.empty())
-        return "\033[0m";
-    if (list.size() > 3)
-        return "";
+	if (list.empty())
+		return "\033[0m";
+	if (list.size() > 3)
+		return "";
 
-    std::vector<std::string> seq;
+	std::vector<std::string> seq;
 
-    /*
-     * Shell sequence looks like this:
-     *
-     * ^[[attributes;foreground;backgroundm
-     */
-    if (list.size() >= 3) {
-        const auto it = shell_attributes.find(list[2]);
+	/*
+	 * Shell sequence looks like this:
+	 *
+	 * ^[[attributes;foreground;backgroundm
+	 */
+	if (list.size() >= 3) {
+		const auto it = shell_attributes.find(list[2]);
 
-        if (it != shell_attributes.end())
-            seq.push_back(std::to_string(it->second));
-        else
-            return "";
-    }
-    if (list.size() >= 1) {
-        const auto it = shell_colors.find(list[0]);
+		if (it != shell_attributes.end())
+			seq.push_back(std::to_string(it->second));
+		else
+			return "";
+	}
+	if (list.size() >= 1) {
+		const auto it = shell_colors.find(list[0]);
 
-        if (it != shell_colors.end())
-            seq.push_back(std::to_string(it->second));
-        else
-            return "";
-    }
-    if (list.size() >= 2) {
-        const auto it = shell_colors.find(list[1]);
+		if (it != shell_colors.end())
+			seq.push_back(std::to_string(it->second));
+		else
+			return "";
+	}
+	if (list.size() >= 2) {
+		const auto it = shell_colors.find(list[1]);
 
-        if (it != shell_colors.end())
-            seq.push_back(std::to_string(it->second + 10));
-        else
-            return "";
-    }
+		if (it != shell_colors.end())
+			seq.push_back(std::to_string(it->second + 10));
+		else
+			return "";
+	}
 
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    oss << "\033[";
-    oss << string_util::join(seq, ';');
-    oss << "m";
+	oss << "\033[";
+	oss << string_util::join(seq, ';');
+	oss << "m";
 
-    return oss.str();
+	return oss.str();
 #else
-    return "";
+	return "";
 #endif
 }
 
-std::string subst_shell(const std::string& command)
+auto subst_shell(const std::string& command) -> std::string
 {
 #if defined(IRCCD_HAVE_POPEN)
-    std::unique_ptr<FILE, std::function<int (FILE*)>> fp(popen(command.c_str(), "r"), pclose);
+	std::unique_ptr<FILE, std::function<int (FILE*)>> fp(popen(command.c_str(), "r"), pclose);
 
-    if (fp == nullptr)
-        throw std::runtime_error(std::strerror(errno));
+	if (fp == nullptr)
+		throw std::runtime_error(std::strerror(errno));
 
-    std::string result;
-    std::array<char, 128> buffer;
-    std::size_t n;
+	std::string result;
+	std::array<char, 128> buffer;
+	std::size_t n;
 
-    while ((n = std::fread(buffer.data(), 1, 128, fp.get())) > 0)
-        result.append(buffer.data(), n);
-    if (std::ferror(fp.get()))
-        throw std::runtime_error(std::strerror(errno));
+	while ((n = std::fread(buffer.data(), 1, 128, fp.get())) > 0)
+		result.append(buffer.data(), n);
+	if (std::ferror(fp.get()))
+		throw std::runtime_error(std::strerror(errno));
 
-    // Erase final '\n'.
-    auto it = result.find('\n');
-    if (it != std::string::npos)
-        result.erase(it);
+	// Erase final '\n'.
+	auto it = result.find('\n');
+	if (it != std::string::npos)
+		result.erase(it);
 
-    return result;
+	return result;
 #else
-    throw std::runtime_error("shell template not available");
+	throw std::runtime_error("shell template not available");
 #endif
 }
 
-std::string substitute(std::string::const_iterator& it,
-                       std::string::const_iterator& end,
-                       char token,
-                       const subst& params)
+auto substitute(std::string::const_iterator& it,
+                std::string::const_iterator& end,
+                char token,
+                const subst& params) -> std::string
 {
-    assert(is_reserved(token));
+	assert(is_reserved(token));
 
-    std::string content, value;
+	std::string content, value;
 
-    if (it == end)
-        return "";
+	if (it == end)
+		return "";
 
-    while (it != end && *it != '}')
-        content += *it++;
+	while (it != end && *it != '}')
+		content += *it++;
 
-    if (it == end || *it != '}')
-        throw std::invalid_argument("unclosed "s + token + " construct"s);
+	if (it == end || *it != '}')
+		throw std::invalid_argument("unclosed "s + token + " construct"s);
 
-    it++;
+	it++;
 
-    // Create default original value if flag is disabled.
-    value = std::string(1, token) + "{"s + content + "}"s;
+	// Create default original value if flag is disabled.
+	value = std::string(1, token) + "{"s + content + "}"s;
 
-    switch (token) {
-    case '#':
-        if ((params.flags & subst_flags::keywords) == subst_flags::keywords)
-            value = subst_keywords(content, params);
-        break;
-    case '$':
-        if ((params.flags & subst_flags::env) == subst_flags::env)
-            value = subst_env(content);
-        break;
-    case '@':
-        if ((params.flags & subst_flags::irc_attrs) == subst_flags::irc_attrs)
-            value = subst_irc_attrs(content);
-        else if ((params.flags & subst_flags::shell_attrs) == subst_flags::shell_attrs)
-            value = subst_shell_attrs(content);
-        break;
-    case '!':
-        if ((params.flags & subst_flags::shell) == subst_flags::shell)
-            value = subst_shell(content);
-        break;
-    default:
-        break;
-    }
+	switch (token) {
+	case '#':
+		if ((params.flags & subst_flags::keywords) == subst_flags::keywords)
+			value = subst_keywords(content, params);
+		break;
+	case '$':
+		if ((params.flags & subst_flags::env) == subst_flags::env)
+			value = subst_env(content);
+		break;
+	case '@':
+		if ((params.flags & subst_flags::irc_attrs) == subst_flags::irc_attrs)
+			value = subst_irc_attrs(content);
+		else if ((params.flags & subst_flags::shell_attrs) == subst_flags::shell_attrs)
+			value = subst_shell_attrs(content);
+		break;
+	case '!':
+		if ((params.flags & subst_flags::shell) == subst_flags::shell)
+			value = subst_shell(content);
+		break;
+	default:
+		break;
+	}
 
-    return value;
+	return value;
 }
 
 } // !namespace
 
-std::string format(std::string text, const subst& params)
+auto format(std::string text, const subst& params) -> std::string
 {
-    /*
-     * Change the date format before anything else to avoid interpolation with
-     * keywords and user input.
-     */
-    if ((params.flags & subst_flags::date) == subst_flags::date)
-        text = subst_date(text, params);
+	/*
+	 * Change the date format before anything else to avoid interpolation with
+	 * keywords and user input.
+	 */
+	if ((params.flags & subst_flags::date) == subst_flags::date)
+		text = subst_date(text, params);
 
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    for (auto it = text.cbegin(), end = text.cend(); it != end; ) {
-        auto token = *it;
+	for (auto it = text.cbegin(), end = text.cend(); it != end; ) {
+		auto token = *it;
 
-        // Is the current character a reserved token or not?
-        if (!is_reserved(token)) {
-            oss << *it++;
-            continue;
-        }
+		// Is the current character a reserved token or not?
+		if (!is_reserved(token)) {
+			oss << *it++;
+			continue;
+		}
 
-        // The token was at the end, just write it and return now.
-        if (++it == end) {
-            oss << token;
-            continue;
-        }
+		// The token was at the end, just write it and return now.
+		if (++it == end) {
+			oss << token;
+			continue;
+		}
 
-        // The token is declaring a template variable, substitute it.
-        if (*it == '{') {
-            oss << substitute(++it, end, token, params);
-            continue;
-        }
+		// The token is declaring a template variable, substitute it.
+		if (*it == '{') {
+			oss << substitute(++it, end, token, params);
+			continue;
+		}
 
-        /*
-         * If the next token is different from the previous one, just let the
-         * next iteration parse the string because we can have the following
-         * constructs.
-         *
-         * "@#{var}" -> "@value"
-         */
-        if (*it != token) {
-            oss << token;
-            continue;
-        }
+		/*
+		 * If the next token is different from the previous one, just let the
+		 * next iteration parse the string because we can have the following
+		 * constructs.
+		 *
+		 * "@#{var}" -> "@value"
+		 */
+		if (*it != token) {
+			oss << token;
+			continue;
+		}
 
-        /*
-         * Write the token only if it's not a variable because at this step we
-         * may have the following constructs.
-         *
-         * "##" -> "##"
-         * "##hello" -> "##hello"
-         * "##{hello}" -> "#{hello}"
-         */
-        if (++it == end)
-            oss << token << token;
-        else if (*it == '{')
-            oss << token;
-    }
+		/*
+		 * Write the token only if it's not a variable because at this step we
+		 * may have the following constructs.
+		 *
+		 * "##" -> "##"
+		 * "##hello" -> "##hello"
+		 * "##{hello}" -> "#{hello}"
+		 */
+		if (++it == end)
+			oss << token << token;
+		else if (*it == '{')
+			oss << token;
+	}
 
-    return oss.str();
+	return oss.str();
 }
 
 // }}}
 
 // {{{ strip
 
-std::string strip(std::string str) noexcept
+auto strip(std::string str) noexcept -> std::string
 {
-    const auto test = [] (auto c) noexcept { return !std::isspace(c); };
+	const auto test = [] (auto c) noexcept { return !std::isspace(c); };
 
-    str.erase(str.begin(), std::find_if(str.begin(), str.end(), test));
-    str.erase(std::find_if(str.rbegin(), str.rend(), test).base(), str.end());
+	str.erase(str.begin(), std::find_if(str.begin(), str.end(), test));
+	str.erase(std::find_if(str.rbegin(), str.rend(), test).base(), str.end());
 
-    return str;
+	return str;
 }
 
 // }}}
@@ -398,33 +396,33 @@
 
 auto split(std::string_view list, const std::string& delimiters, int max) -> std::vector<std::string>
 {
-    std::vector<std::string> result;
-    std::size_t next = -1, current;
-    int count = 1;
-    bool finished = false;
+	std::vector<std::string> result;
+	std::size_t next = -1, current;
+	int count = 1;
+	bool finished = false;
 
-    if (list.empty())
-        return result;
+	if (list.empty())
+		return result;
 
-    do {
-        std::string val;
+	do {
+		std::string val;
 
-        current = next + 1;
-        next = list.find_first_of(delimiters, current);
+		current = next + 1;
+		next = list.find_first_of(delimiters, current);
 
-        // split max, get until the end.
-        if (max >= 0 && count++ >= max) {
-            val = list.substr(current, std::string::npos);
-            finished = true;
-        } else {
-            val = list.substr(current, next - current);
-            finished = next == std::string::npos;
-        }
+		// split max, get until the end.
+		if (max >= 0 && count++ >= max) {
+			val = list.substr(current, std::string::npos);
+			finished = true;
+		} else {
+			val = list.substr(current, next - current);
+			finished = next == std::string::npos;
+		}
 
-        result.push_back(val);
-    } while (!finished);
+		result.push_back(val);
+	} while (!finished);
 
-    return result;
+	return result;
 }
 
 // }}}
@@ -433,9 +431,9 @@
 
 auto is_identifier(std::string_view name) noexcept -> bool
 {
-    static const std::regex regex("[A-Za-z0-9-_]+");
+	static const std::regex regex("[A-Za-z0-9-_]+");
 
-    return std::regex_match(std::string(name), regex);
+	return std::regex_match(std::string(name), regex);
 }
 
 // }}}
@@ -444,15 +442,13 @@
 
 auto is_boolean(std::string value) noexcept -> bool
 {
-    std::transform(value.begin(), value.end(), value.begin(), [] (auto c) noexcept {
-        return toupper(c);
-    });
+	std::transform(value.begin(), value.end(), value.begin(), [] (auto c) noexcept {
+		return toupper(c);
+	});
 
-    return value == "1" || value == "YES" || value == "TRUE" || value == "ON";
+	return value == "1" || value == "YES" || value == "TRUE" || value == "ON";
 }
 
 // }}}
 
-} // !string_util
-
-} // !util
+} // !util::string_util
--- a/libirccd-core/irccd/string_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/string_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -49,57 +49,99 @@
  * \brief Disable or enable some features.
  */
 enum class subst_flags : unsigned {
-    date        = (1 << 0),     //!< date templates
-    keywords    = (1 << 1),     //!< keywords
-    env         = (1 << 2),     //!< environment variables
-    shell       = (1 << 3),     //!< command line command
-    irc_attrs   = (1 << 4),     //!< IRC escape codes
-    shell_attrs = (1 << 5)      //!< shell attributes
+	date            = (1 << 0),      //!< date templates
+	keywords        = (1 << 1),      //!< keywords
+	env             = (1 << 2),      //!< environment variables
+	shell           = (1 << 3),      //!< command line command
+	irc_attrs       = (1 << 4),      //!< IRC escape codes
+	shell_attrs     = (1 << 5)      //!< shell attributes
 };
 
 /**
- * \cond ENUM_HIDDEN_SYMBOLS
+ * \cond IRCCD_ENUM_HIDDEN_SYMBOLS
  */
 
-inline subst_flags operator^(subst_flags v1, subst_flags v2) noexcept
+/**
+ * Apply bitwise XOR.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator^(subst_flags v1, subst_flags v2) noexcept -> subst_flags
 {
-    return static_cast<subst_flags>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+	return static_cast<subst_flags>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
 }
 
-inline subst_flags operator&(subst_flags v1, subst_flags v2) noexcept
+/**
+ * Apply bitwise AND.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator&(subst_flags v1, subst_flags v2) noexcept -> subst_flags
 {
-    return static_cast<subst_flags>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
+	return static_cast<subst_flags>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
 }
 
-inline subst_flags operator|(subst_flags v1, subst_flags v2) noexcept
+/**
+ * Apply bitwise OR.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator|(subst_flags v1, subst_flags v2) noexcept -> subst_flags
 {
-    return static_cast<subst_flags>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+	return static_cast<subst_flags>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
 }
 
-inline subst_flags operator~(subst_flags v) noexcept
+/**
+ * Apply bitwise NOT.
+ *
+ * \param v the value
+ * \return the complement
+ */
+inline auto operator~(subst_flags v) noexcept -> subst_flags
 {
-    return static_cast<subst_flags>(~static_cast<unsigned>(v));
+	return static_cast<subst_flags>(~static_cast<unsigned>(v));
 }
 
-inline subst_flags& operator|=(subst_flags& v1, subst_flags v2) noexcept
+/**
+ * Assign bitwise OR.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator|=(subst_flags& v1, subst_flags v2) noexcept -> subst_flags&
 {
-    v1 = static_cast<subst_flags>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
-
-    return v1;
+	return v1 = v1 | v2;
 }
 
-inline subst_flags& operator&=(subst_flags& v1, subst_flags v2) noexcept
+/**
+ * Assign bitwise AND.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator&=(subst_flags& v1, subst_flags v2) noexcept -> subst_flags&
 {
-    v1 = static_cast<subst_flags>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
-
-    return v1;
+	return v1 = v1 & v2;
 }
 
-inline subst_flags& operator^=(subst_flags& v1, subst_flags v2) noexcept
+/**
+ * Assign bitwise XOR.
+ *
+ * \param v1 the first value
+ * \param v2 the second value
+ * \return the new value
+ */
+inline auto operator^=(subst_flags& v1, subst_flags v2) noexcept -> subst_flags&
 {
-    v1 = static_cast<subst_flags>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
-
-    return v1;
+	return v1 = v1 ^ v2;
 }
 
 /**
@@ -111,25 +153,25 @@
  */
 class subst {
 public:
-    /**
-     * Flags for selecting templates.
-     */
-    subst_flags flags{
-        subst_flags::date |
-        subst_flags::keywords |
-        subst_flags::env |
-        subst_flags::irc_attrs
-    };
+	/**
+	 * Flags for selecting templates.
+	 */
+	subst_flags flags{
+		subst_flags::date |
+		subst_flags::keywords |
+		subst_flags::env |
+		subst_flags::irc_attrs
+	};
 
-    /**
-     * Fill that field if you want a date.
-     */
-    std::time_t time{std::time(nullptr)};
+	/**
+	 * Fill that field if you want a date.
+	 */
+	std::time_t time{std::time(nullptr)};
 
-    /**
-     * Fill that map if you want to replace keywords.
-     */
-    std::unordered_map<std::string, std::string> keywords;
+	/**
+	 * Fill that map if you want to replace keywords.
+	 */
+	std::unordered_map<std::string, std::string> keywords;
 };
 
 /**
@@ -166,25 +208,25 @@
  *
  * ### Valid constructs
  *
- *   - <strong>\#{target}, welcome</strong>: if target is set to "irccd",
- *     becomes "irccd, welcome",
- *   - <strong>\@{red}\#{target}</strong>: if target is specified, it is written
- *     in red,
+ * - <strong>\#{target}, welcome</strong>: if target is set to "irccd",
+ *   becomes "irccd, welcome",
+ * - <strong>\@{red}\#{target}</strong>: if target is specified, it is written
+ *   in red,
  *
  * ### Invalid or literals constructs
  *
- *   - <strong>\#\#{target}</strong>: will output "\#{target}",
- *   - <strong>\#\#</strong>: will output "\#\#",
- *   - <strong>\#target</strong>: will output "\#target",
- *   - <strong>\#{target</strong>: will throw std::invalid_argument.
+ * - <strong>\#\#{target}</strong>: will output "\#{target}",
+ * - <strong>\#\#</strong>: will output "\#\#",
+ * - <strong>\#target</strong>: will output "\#target",
+ * - <strong>\#{target</strong>: will throw std::invalid_argument.
  *
  * ### Colors & attributes
  *
- *   - <strong>\@{red,blue}</strong>: will write text red on blue background,
- *   - <strong>\@{default,yellow}</strong>: will write default color text on
- *     yellow background,
- *   - <strong>\@{white,black,bold,underline}</strong>: will write white text on
- *     black in both bold and underline.
+ * - <strong>\@{red,blue}</strong>: will write text red on blue background,
+ * - <strong>\@{default,yellow}</strong>: will write default color text on
+ *   yellow background,
+ * - <strong>\@{white,black,bold,underline}</strong>: will write white text on
+ *   black in both bold and underline.
  */
 auto format(std::string text, const subst& params = {}) -> std::string;
 
@@ -229,16 +271,16 @@
 template <typename InputIt, typename DelimType = char>
 auto join(InputIt first, InputIt last, DelimType delim = ':') -> std::string
 {
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    if (first != last) {
-        oss << *first;
+	if (first != last) {
+		oss << *first;
 
-        while (++first != last)
-            oss << delim << *first;
-    }
+		while (++first != last)
+			oss << delim << *first;
+	}
 
-    return oss.str();
+	return oss.str();
 }
 
 /**
@@ -251,7 +293,7 @@
 template <typename Container, typename DelimType = char>
 auto join(const Container& c, DelimType delim = ':') -> std::string
 {
-    return join(c.begin(), c.end(), delim);
+	return join(c.begin(), c.end(), delim);
 }
 
 /**
@@ -264,7 +306,7 @@
 template <typename T, typename DelimType = char>
 auto join(std::initializer_list<T> list, DelimType delim = ':') -> std::string
 {
-    return join(list.begin(), list.end(), delim);
+	return join(list.begin(), list.end(), delim);
 }
 
 // }}}
@@ -309,15 +351,15 @@
             T min = std::numeric_limits<T>::min(),
             T max = std::numeric_limits<T>::max()) noexcept -> std::optional<T>
 {
-    static_assert(std::is_signed<T>::value, "must be signed");
+	static_assert(std::is_signed<T>::value, "must be signed");
 
-    char* end;
-    auto v = std::strtoll(str.c_str(), &end, 10);
+	char* end;
+	auto v = std::strtoll(str.c_str(), &end, 10);
 
-    if (*end != '\0' || v < min || v > max)
-        return std::nullopt;
+	if (*end != '\0' || v < min || v > max)
+		return std::nullopt;
 
-    return static_cast<T>(v);
+	return static_cast<T>(v);
 }
 
 // }}}
@@ -338,15 +380,15 @@
              T min = std::numeric_limits<T>::min(),
              T max = std::numeric_limits<T>::max()) noexcept -> std::optional<T>
 {
-    static_assert(std::is_unsigned<T>::value, "must be unsigned");
+	static_assert(std::is_unsigned<T>::value, "must be unsigned");
 
-    char* end;
-    auto v = std::strtoull(str.c_str(), &end, 10);
+	char* end;
+	auto v = std::strtoull(str.c_str(), &end, 10);
 
-    if (*end != '\0' || v < min || v > max)
-        return std::nullopt;
+	if (*end != '\0' || v < min || v > max)
+		return std::nullopt;
 
-    return static_cast<T>(v);
+	return static_cast<T>(v);
 }
 
 // }}}
--- a/libirccd-core/irccd/system.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/system.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,27 +31,27 @@
 #include "sysconfig.hpp"
 
 #if BOOST_OS_WINDOWS
-#   include <sys/timeb.h>
-#   include <shlobj.h>
+#	include <sys/timeb.h>
+#	include <shlobj.h>
 #else
-#   include <sys/utsname.h>
-#   include <sys/types.h>
-#   include <sys/param.h>
-#   include <sys/time.h>
-#   include <unistd.h>
+#	include <sys/utsname.h>
+#	include <sys/types.h>
+#	include <sys/param.h>
+#	include <sys/time.h>
+#	include <unistd.h>
 #endif
 
 #if BOOST_OS_LINUX
-#   include <sys/sysinfo.h>
+#	include <sys/sysinfo.h>
 #endif
 
 #if BOOST_OS_MACOS
-#   include <sys/sysctl.h>
-#   include <libproc.h>
+#	include <sys/sysctl.h>
+#	include <libproc.h>
 #endif
 
 #if defined(IRCCD_HAVE_GETLOGIN)
-#   include <unistd.h>
+#	include <unistd.h>
 #endif
 
 #include "system.hpp"
@@ -77,28 +77,28 @@
  */
 auto base_directory() -> boost::filesystem::path
 {
-    static const boost::filesystem::path bindir(IRCCD_INSTALL_BINDIR);
-    static const boost::filesystem::path prefix(IRCCD_INSTALL_PREFIX);
+	static const boost::filesystem::path bindir(IRCCD_INSTALL_BINDIR);
+	static const boost::filesystem::path prefix(IRCCD_INSTALL_PREFIX);
 
-    boost::filesystem::path path(".");
+	boost::filesystem::path path(".");
 
-    if (bindir.is_relative()) {
-        try {
-            path = boost::dll::program_location();
-            path = path.parent_path();
-        } catch (...) {
-            path = ".";
-        }
+	if (bindir.is_relative()) {
+		try {
+			path = boost::dll::program_location();
+			path = path.parent_path();
+		} catch (...) {
+			path = ".";
+		}
 
-        // Compute relative base directory.
-        for (auto len = std::distance(bindir.begin(), bindir.end()); len > 0; len--)
-            path = path.parent_path();
-        if (path.empty())
-            path = ".";
-    } else
-        path = prefix;
+		// Compute relative base directory.
+		for (auto len = std::distance(bindir.begin(), bindir.end()); len > 0; len--)
+			path = path.parent_path();
+		if (path.empty())
+			path = ".";
+	} else
+		path = prefix;
 
-    return path;
+	return path;
 }
 
 // }}}
@@ -119,12 +119,12 @@
  */
 auto system_directory(const std::string& component) -> boost::filesystem::path
 {
-    boost::filesystem::path path(component);
+	boost::filesystem::path path(component);
 
-    if (path.is_relative())
-        path = base_directory() / component;
+	if (path.is_relative())
+		path = base_directory() / component;
 
-    return path.string();
+	return path.string();
 }
 
 // }}}
@@ -140,32 +140,32 @@
  * Referenced by:   config_filenames.
  * Requires:
  *   - Windows:
- *     - <shlobj.h>
+ *	 - <shlobj.h>
  */
 auto user_config_directory() -> boost::filesystem::path
 {
-    boost::filesystem::path path;
+	boost::filesystem::path path;
 
 #if BOOST_OS_WINDOWS
-    char folder[MAX_PATH] = {0};
+	char folder[MAX_PATH] = {0};
 
-    if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, folder) == S_OK) {
-        path /= folder;
-        path /= "\\irccd\\config";
-    } else
-        path = ".";
+	if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, folder) == S_OK) {
+		path /= folder;
+		path /= "\\irccd\\config";
+	} else
+		path = ".";
 #else
-    try {
-        path = xdg().config_home();
-    } catch (...) {
-        path = sys::env("HOME");
-        path /= ".config";
-    }
+	try {
+		path = xdg().get_config_home();
+	} catch (...) {
+		path = sys::env("HOME");
+		path /= ".config";
+	}
 
-    path /= "irccd";
+	path /= "irccd";
 #endif
 
-    return path;
+	return path;
 }
 
 // }}}
@@ -179,33 +179,33 @@
  * Referenced by:   plugin_filenames.
  * Requires:
  *   - Windows:
- *     - <shlobj.h>
+ *	 - <shlobj.h>
  *
  * Like add user_config_directory but for plugins.
  */
 auto user_plugin_directory() -> boost::filesystem::path
 {
-    boost::filesystem::path path;
+	boost::filesystem::path path;
 
 #if BOOST_OS_WINDOWS
-    char folder[MAX_PATH] = {0};
+	char folder[MAX_PATH] = {0};
 
-    if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, folder) == S_OK) {
-        path /= folder;
-        path /= "\\irccd\\share";
-    }
+	if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, folder) == S_OK) {
+		path /= folder;
+		path /= "\\irccd\\share";
+	}
 #else
-    try {
-        path = xdg().data_home();
-    } catch (...) {
-        path = sys::env("HOME");
-        path /= ".local/share";
-    }
+	try {
+		path = xdg().get_data_home();
+	} catch (...) {
+		path = sys::env("HOME");
+		path /= ".local/share";
+	}
 
-    path /= "irccd";
+	path /= "irccd";
 #endif
 
-    return path / "plugins";
+	return path / "plugins";
 }
 
 // }}}
@@ -217,11 +217,11 @@
 void set_program_name(std::string name) noexcept
 {
 #if defined(IRCCD_HAVE_SETPROGNAME)
-    static std::string save = name;
+	static std::string save = name;
 
-    setprogname(save.c_str());
+	setprogname(save.c_str());
 #else
-    (void)name;
+	(void)name;
 #endif
 }
 
@@ -232,31 +232,31 @@
 auto name() -> std::string
 {
 #if BOOST_OS_LINUX
-    return "Linux";
+	return "Linux";
 #elif BOOST_OS_WINDOWS
-    return "Windows";
+	return "Windows";
 #elif BOOST_OS_BSD_FREE
-    return "FreeBSD";
+	return "FreeBSD";
 #elif BOOST_OS_BSD_DRAGONFLY
-    return "DragonFlyBSD";
+	return "DragonFlyBSD";
 #elif BOOST_OS_BSD_OPEN
-    return "OpenBSD";
+	return "OpenBSD";
 #elif BOOST_OS_BSD_NET
-    return "NetBSD";
+	return "NetBSD";
 #elif BOOST_OS_MACOS
-    return "macOS";
+	return "macOS";
 #elif BOOST_OS_ANDROID
-    return "Android";
+	return "Android";
 #elif BOOST_OS_AIX
-    return "Aix";
+	return "Aix";
 #elif BOOST_OS_HAIKU
-    return "Haiku";
+	return "Haiku";
 #elif BOOST_OS_IOS
-    return "iOS";
+	return "iOS";
 #elif BOOST_OS_SOLARIS
-    return "Solaris";
+	return "Solaris";
 #else
-    return "Unknown";
+	return "Unknown";
 #endif
 }
 
@@ -267,25 +267,25 @@
 /*
  * Requires:
  *   - Windows:
- *     - <windows.h>
+ *	 - <windows.h>
  *   - Others:
- *     - <sys/utsname.h>
+ *	 - <sys/utsname.h>
  */
 auto version() -> std::string
 {
 #if BOOST_OS_WINDOWS
-    const auto version = GetVersion();
-    const auto major = (DWORD)(LOBYTE(LOWORD(version)));
-    const auto minor = (DWORD)(HIBYTE(LOWORD(version)));
+	const auto version = GetVersion();
+	const auto major = (DWORD)(LOBYTE(LOWORD(version)));
+	const auto minor = (DWORD)(HIBYTE(LOWORD(version)));
 
-    return std::to_string(major) + "." + std::to_string(minor);
+	return std::to_string(major) + "." + std::to_string(minor);
 #else
-    struct utsname uts;
+	struct utsname uts;
 
-    if (::uname(&uts) < 0)
-        throw std::runtime_error(std::strerror(errno));
+	if (::uname(&uts) < 0)
+		throw std::runtime_error(std::strerror(errno));
 
-    return std::string(uts.release);
+	return std::string(uts.release);
 #endif
 }
 
@@ -296,44 +296,44 @@
 /*
  * Requires:
  *   - Windows:
- *     - <windows.h>
+ *	 - <windows.h>
  *   - Linux:
- *     - <sys/sysinfo.h>
+ *	 - <sys/sysinfo.h>
  *   - Mac:
- *     - <sys/types.h>
- *     - <sys/sysctl.h>
+ *	 - <sys/types.h>
+ *	 - <sys/sysctl.h>
  *   - Others:
- *     - <ctime>
+ *	 - <ctime>
  */
 auto uptime() -> std::uint64_t
 {
 #if BOOST_OS_WINDOWS
-    return ::GetTickCount64() / 1000;
+	return ::GetTickCount64() / 1000;
 #elif BOOST_OS_LINUX
-    struct sysinfo info;
+	struct sysinfo info;
 
-    if (sysinfo(&info) < 0)
-        throw std::runtime_error(std::strerror(errno));
+	if (sysinfo(&info) < 0)
+		throw std::runtime_error(std::strerror(errno));
 
-    return info.uptime;
+	return info.uptime;
 #elif BOOST_OS_MACOS
-    struct timeval boottime;
-    size_t length = sizeof (boottime);
-    int mib[2] = { CTL_KERN, KERN_BOOTTIME };
+	struct timeval boottime;
+	size_t length = sizeof (boottime);
+	int mib[2] = { CTL_KERN, KERN_BOOTTIME };
 
-    if (sysctl(mib, 2, &boottime, &length, nullptr, 0) < 0)
-        throw std::runtime_error(std::strerror(errno));
+	if (sysctl(mib, 2, &boottime, &length, nullptr, 0) < 0)
+		throw std::runtime_error(std::strerror(errno));
 
-    time_t bsec = boottime.tv_sec, csec = time(nullptr);
+	time_t bsec = boottime.tv_sec, csec = time(nullptr);
 
-    return difftime(csec, bsec);
+	return difftime(csec, bsec);
 #else
-    struct timespec ts;
+	struct timespec ts;
 
-    if (clock_gettime(CLOCK_UPTIME, &ts) < 0)
-        throw std::runtime_error(std::strerror(errno));
+	if (clock_gettime(CLOCK_UPTIME, &ts) < 0)
+		throw std::runtime_error(std::strerror(errno));
 
-    return ts.tv_sec;
+	return ts.tv_sec;
 #endif
 }
 
@@ -344,24 +344,24 @@
 /*
  * Requires:
  *   - Windows:
- *     - <sys/timeb.h>
+ *	 - <sys/timeb.h>
  *   - Others:
- *     - <sys/times.h>
+ *	 - <sys/times.h>
  */
 auto ticks() -> std::uint64_t
 {
 #if BOOST_OS_WINDOWS
-    _timeb tp;
+	_timeb tp;
 
-    _ftime(&tp);
+	_ftime(&tp);
 
-    return tp.time * 1000LL + tp.millitm;
+	return tp.time * 1000LL + tp.millitm;
 #else
-    struct timeval tp;
+	struct timeval tp;
 
-    gettimeofday(&tp, NULL);
+	gettimeofday(&tp, NULL);
 
-    return tp.tv_sec * 1000LL + tp.tv_usec / 1000;
+	return tp.tv_sec * 1000LL + tp.tv_usec / 1000;
 #endif
 }
 
@@ -372,19 +372,19 @@
 /*
  * Requires:
  *   - Windows:
- *     - <shlobj.h>
+ *	 - <shlobj.h>
  */
 auto home() -> std::string
 {
 #if BOOST_OS_WINDOWS
-    char path[MAX_PATH];
+	char path[MAX_PATH];
 
-    if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, path) != S_OK)
-        return "";
+	if (SHGetFolderPathA(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, path) != S_OK)
+		return "";
 
-    return std::string(path);
+	return std::string(path);
 #else
-    return env("HOME");
+	return env("HOME");
 #endif
 }
 
@@ -398,12 +398,12 @@
  */
 auto env(const std::string& var) -> std::string
 {
-    const auto value = std::getenv(var.c_str());
+	const auto value = std::getenv(var.c_str());
 
-    if (value == nullptr)
-        return "";
+	if (value == nullptr)
+		return "";
 
-    return value;
+	return value;
 }
 
 // }}}
@@ -412,7 +412,7 @@
 
 auto cachedir() -> boost::filesystem::path
 {
-    return system_directory(IRCCD_INSTALL_LOCALSTATEDIR) / "cache/irccd";
+	return system_directory(IRCCD_INSTALL_LOCALSTATEDIR) / "cache/irccd";
 }
 
 // }}}
@@ -421,7 +421,7 @@
 
 auto datadir() -> boost::filesystem::path
 {
-    return system_directory(IRCCD_INSTALL_DATADIR);
+	return system_directory(IRCCD_INSTALL_DATADIR);
 }
 
 // }}}
@@ -430,7 +430,7 @@
 
 auto sysconfdir() -> boost::filesystem::path
 {
-    return system_directory(IRCCD_INSTALL_SYSCONFDIR) / "irccd";
+	return system_directory(IRCCD_INSTALL_SYSCONFDIR) / "irccd";
 }
 
 // }}}
@@ -439,7 +439,7 @@
 
 auto plugindir() -> boost::filesystem::path
 {
-    return system_directory(IRCCD_INSTALL_LIBDIR) / "irccd";
+	return system_directory(IRCCD_INSTALL_LIBDIR) / "irccd";
 }
 
 // }}}
@@ -453,13 +453,13 @@
 auto username() -> std::string
 {
 #if defined(IRCCD_HAVE_GETLOGIN)
-    auto v = getlogin();
+	auto v = getlogin();
 
-    if (v)
-        return v;
+	if (v)
+		return v;
 #endif
 
-    return "";
+	return "";
 }
 
 // }}}
@@ -468,13 +468,13 @@
 
 auto config_filenames(std::string_view file) -> std::vector<std::string>
 {
-    // TODO: remove this once we can use std::filesystem.
-    const std::string filename(file);
+	// TODO: remove this once we can use std::filesystem.
+	const std::string filename(file);
 
-    return {
-        (user_config_directory() / filename).string(),
-        (sysconfdir() / filename).string()
-    };
+	return {
+		(user_config_directory() / filename).string(),
+		(sysconfdir() / filename).string()
+	};
 }
 
 // }}}
@@ -484,16 +484,16 @@
 auto plugin_filenames(const std::string& name,
                       const std::vector<std::string>& extensions) -> std::vector<std::string>
 {
-    assert(!extensions.empty());
+	assert(!extensions.empty());
 
-    std::vector<std::string> result;
+	std::vector<std::string> result;
 
-    for (const auto& ext : extensions)
-        result.push_back((user_plugin_directory() / (name + ext)).string());
-    for (const auto& ext : extensions)
-        result.push_back((plugindir() / (name + ext)).string());
+	for (const auto& ext : extensions)
+		result.push_back((user_plugin_directory() / (name + ext)).string());
+	for (const auto& ext : extensions)
+		result.push_back((plugindir() / (name + ext)).string());
 
-    return result;
+	return result;
 }
 
 // }}}
--- a/libirccd-core/irccd/tls_acceptor.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/tls_acceptor.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,7 +31,7 @@
 #include "socket_acceptor.hpp"
 #include "tls_stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief TLS/SSL acceptors.
@@ -40,52 +40,56 @@
 template <typename Protocol = boost::asio::ip::tcp>
 class tls_acceptor : public socket_acceptor<Protocol> {
 private:
-    using socket = typename Protocol::socket;
+	using socket = typename Protocol::socket;
 
-    boost::asio::ssl::context context_;
+	boost::asio::ssl::context context_;
 
 public:
-    /**
-     * Construct a secure layer transport server.
-     *
-     * \param context the SSL context
-     * \param args the socket_acceptor arguments
-     */
-    template <typename... Args>
-    tls_acceptor(boost::asio::ssl::context context, Args&&... args)
-        : socket_acceptor<Protocol>(std::forward<Args>(args)...)
-        , context_(std::move(context))
-    {
-    }
+	/**
+	 * Construct a secure layer transport server.
+	 *
+	 * \param context the SSL context
+	 * \param args the socket_acceptor arguments
+	 */
+	template <typename... Args>
+	tls_acceptor(boost::asio::ssl::context context, Args&&... args);
 
-    /**
-     * \copydoc acceptor::accept
-     */
-    void accept(accept_handler handler) override;
+	/**
+	 * \copydoc acceptor::accept
+	 */
+	void accept(acceptor::handler handler) override;
 };
 
 template <typename Protocol>
-void tls_acceptor<Protocol>::accept(accept_handler handler)
+void tls_acceptor<Protocol>::accept(acceptor::handler handler)
 {
-    assert(handler);
+	assert(handler);
 
-    auto client = std::make_shared<tls_stream<socket>>(this->get_acceptor().get_io_service(), this->context_);
+	auto client = std::make_shared<tls_stream<socket>>(this->get_acceptor().get_io_service(), this->context_);
 
-    socket_acceptor<Protocol>::do_accept(client->get_socket().lowest_layer(), [handler, client] (auto code) {
-        using boost::asio::ssl::stream_base;
+	socket_acceptor<Protocol>::do_accept(client->get_socket().lowest_layer(), [handler, client] (auto code) {
+		using boost::asio::ssl::stream_base;
 
-        if (code) {
-            handler(code, nullptr);
-            return;
-        }
+		if (code) {
+			handler(code, nullptr);
+			return;
+		}
 
-        client->get_socket().async_handshake(stream_base::server, [handler, client] (auto code) {
-            handler(code, code ? nullptr : std::move(client));
-        });
-    });
+		client->get_socket().async_handshake(stream_base::server, [handler, client] (auto code) {
+			handler(code, code ? nullptr : std::move(client));
+		});
+	});
 }
 
-} // !irccd::io
+template <typename Protocol>
+template <typename... Args>
+tls_acceptor<Protocol>::tls_acceptor(boost::asio::ssl::context context, Args&&... args)
+	: socket_acceptor<Protocol>(std::forward<Args>(args)...)
+	, context_(std::move(context))
+{
+}
+
+} // !irccd
 
 #endif // !IRCCD_HAVE_SSL
 
--- a/libirccd-core/irccd/tls_connector.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/tls_connector.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,7 +31,7 @@
 #include "socket_connector.hpp"
 #include "tls_stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief TLS/SSL connectors.
@@ -40,51 +40,55 @@
 template <typename Protocol = boost::asio::ip::tcp>
 class tls_connector : public socket_connector<Protocol> {
 private:
-    boost::asio::ssl::context context_;
+	boost::asio::ssl::context context_;
 
 public:
-    /**
-     * Construct a secure layer transport server.
-     *
-     * \param context the SSL context
-     * \param args the arguments to socket_connector<Socket> constructor
-     */
-    template <typename... Args>
-    tls_connector(boost::asio::ssl::context context, Args&&... args)
-        : socket_connector<Protocol>(std::forward<Args>(args)...)
-        , context_(std::move(context))
-    {
-    }
+	/**
+	 * Construct a secure layer transport server.
+	 *
+	 * \param context the SSL context
+	 * \param args the arguments to socket_connector<Socket> constructor
+	 */
+	template <typename... Args>
+	tls_connector(boost::asio::ssl::context context, Args&&... args);
 
-    /**
-     * \copydoc socket_connector::connect
-     */
-    void connect(connect_handler handler) override;
+	/**
+	 * \copydoc socket_connector::connect
+	 */
+	void connect(connector::handler handler) override;
 };
 
 template <typename Protocol>
-void tls_connector<Protocol>::connect(connect_handler handler)
+template <typename... Args>
+tls_connector<Protocol>::tls_connector(boost::asio::ssl::context context, Args&&... args)
+	: socket_connector<Protocol>(std::forward<Args>(args)...)
+	, context_(std::move(context))
 {
-    using boost::asio::ssl::stream_base;
-    using socket = typename Protocol::socket;
-
-    assert(handler);
-
-    const auto stream = std::make_shared<tls_stream<socket>>(this->get_io_service(), context_);
-
-    socket_connector<Protocol>::do_connect(stream->get_socket().lowest_layer(), [handler, stream] (auto code) {
-        if (code) {
-            handler(code, nullptr);
-            return;
-        }
-
-        stream->get_socket().async_handshake(stream_base::client, [handler, stream] (auto code) {
-            handler(code, code ? nullptr : std::move(stream));
-        });
-    });
 }
 
-} // !irccd::io
+template <typename Protocol>
+void tls_connector<Protocol>::connect(connector::handler handler)
+{
+	using boost::asio::ssl::stream_base;
+	using socket = typename Protocol::socket;
+
+	assert(handler);
+
+	const auto stream = std::make_shared<tls_stream<socket>>(this->get_io_service(), context_);
+
+	socket_connector<Protocol>::do_connect(stream->get_socket().lowest_layer(), [handler, stream] (auto code) {
+		if (code) {
+			handler(code, nullptr);
+			return;
+		}
+
+		stream->get_socket().async_handshake(stream_base::client, [handler, stream] (auto code) {
+			handler(code, code ? nullptr : std::move(stream));
+		});
+	});
+}
+
+} // !irccd
 
 #endif // !IRCCD_HAVE_SSL
 
--- a/libirccd-core/irccd/tls_stream.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/tls_stream.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,7 +32,7 @@
 
 #include "socket_stream.hpp"
 
-namespace irccd::io {
+namespace irccd {
 
 /**
  * \brief TLS/SSL streams.
@@ -41,19 +41,19 @@
 template <typename Socket = boost::asio::ip::tcp::socket>
 class tls_stream : public socket_stream<boost::asio::ssl::stream<Socket>> {
 public:
-    /**
-     * Constructor.
-     *
-     * \param args the arguments to boost::asio::ssl::stream<Socket>
-     */
-    template <typename... Args>
-    tls_stream(Args&&... args)
-        : socket_stream<boost::asio::ssl::stream<Socket>>(std::forward<Args>(args)...)
-    {
-    }
+	/**
+	 * Constructor.
+	 *
+	 * \param args the arguments to boost::asio::ssl::stream<Socket>
+	 */
+	template <typename... Args>
+	tls_stream(Args&&... args)
+		: socket_stream<boost::asio::ssl::stream<Socket>>(std::forward<Args>(args)...)
+	{
+	}
 };
 
-} // !irccd::io
+} // !irccd
 
 #endif // !IRCCD_HAVE_SSL
 
--- a/libirccd-core/irccd/xdg.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-core/irccd/xdg.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef IRCCD_XDG_HPP
-#define IRCCD_XDG_HPP
+#ifndef IRCCD_CORE_XDG_HPP
+#define IRCCD_CORE_XDG_HPP
 
 /**
  * \file xdg.hpp
@@ -43,152 +43,150 @@
  */
 class xdg {
 private:
-    std::string config_home_;
-    std::string data_home_;
-    std::string cache_home_;
-    std::string runtime_dir_;
-    std::vector<std::string> config_dirs_;
-    std::vector<std::string> data_dirs_;
+	std::string config_home_;
+	std::string data_home_;
+	std::string cache_home_;
+	std::string runtime_dir_;
+	std::vector<std::string> config_dirs_;
+	std::vector<std::string> data_dirs_;
 
-    inline bool is_absolute(const std::string& path) const noexcept
-    {
-        return path.length() > 0 && path[0] == '/';
-    }
+	auto is_absolute(const std::string& path) const noexcept -> bool
+	{
+		return path.length() > 0 && path[0] == '/';
+	}
 
-    std::vector<std::string> split(const std::string& arg) const
-    {
-        std::stringstream iss(arg);
-        std::string item;
-        std::vector<std::string> elems;
+	auto split(const std::string& arg) const -> std::vector<std::string>
+	{
+		std::stringstream iss(arg);
+		std::string item;
+		std::vector<std::string> elems;
 
-        while (std::getline(iss, item, ':')) {
-            if (is_absolute(item))
-                elems.push_back(item);
-        }
+		while (std::getline(iss, item, ':')) {
+			if (is_absolute(item))
+				elems.push_back(item);
+		}
 
-        return elems;
-    }
+		return elems;
+	}
 
-    std::string env_or_home(const std::string& var, const std::string& repl) const
-    {
-        auto value = std::getenv(var.c_str());
+	auto env_or_home(const std::string& var, const std::string& repl) const -> std::string
+	{
+		auto value = std::getenv(var.c_str());
 
-        if (value == nullptr || !is_absolute(value)) {
-            auto home = std::getenv("HOME");
+		if (value == nullptr || !is_absolute(value)) {
+			auto home = std::getenv("HOME");
 
-            if (home == nullptr)
-                throw std::runtime_error("could not get home directory");
+			if (home == nullptr)
+				throw std::runtime_error("could not get home directory");
 
-            return std::string(home) + "/" + repl;
-        }
+			return std::string(home) + "/" + repl;
+		}
 
-        return value;
-    }
+		return value;
+	}
 
-    std::vector<std::string> list_or_defaults(const std::string& var,
-                                              const std::vector<std::string>& list) const
-    {
-        auto value = std::getenv(var.c_str());
+	auto list_or_defaults(const std::string& var,
+	                      const std::vector<std::string>& list) const -> std::vector<std::string>
+	{
+		const auto value = std::getenv(var.c_str());
 
-        if (!value)
-            return list;
+		if (!value)
+			return list;
 
-        // No valid item at all? Use defaults.
-        auto result = split(value);
+		// No valid item at all? Use defaults.
+		if (const auto result = split(value); !result.empty())
+			return result;
 
-        return (result.size() == 0) ? list : result;
-    }
+		return list;
+	}
 
 public:
-    /**
-     * Open an xdg instance and load directories.
-     *
-     * \throw std::runtime_error on failures
-     */
-    xdg()
-    {
-        config_home_    = env_or_home("XDG_CONFIG_HOME", ".config");
-        data_home_      = env_or_home("XDG_DATA_HOME", ".local/share");
-        cache_home_     = env_or_home("XDG_CACHE_HOME", ".cache");
-
-        config_dirs_    = list_or_defaults("XDG_CONFIG_DIRS", { "/etc/xdg" });
-        data_dirs_      = list_or_defaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" });
-
-        /*
-         * Runtime directory is a special case and does not have a replacement,
-         * the application should manage this by itself.
-         */
-        auto runtime = std::getenv("XDG_RUNTIME_DIR");
+	/**
+	 * Open an xdg instance and load directories.
+	 *
+	 * \throw std::runtime_error on failures
+	 */
+	xdg()
+		: config_home_(env_or_home("XDG_CONFIG_HOME", ".config"))
+		, data_home_(env_or_home("XDG_DATA_HOME", ".local/share"))
+		, cache_home_(env_or_home("XDG_CACHE_HOME", ".cache"))
+		, config_dirs_(list_or_defaults("XDG_CONFIG_DIRS", { "/etc/xdg" }))
+		, data_dirs_(list_or_defaults("XDG_DATA_DIRS", { "/usr/local/share", "/usr/share" }))
+	{
 
-        if (runtime && is_absolute(runtime))
-            runtime_dir_ = runtime;
-    }
+		/*
+		 * Runtime directory is a special case and does not have a replacement,
+		 * the application should manage this by itself.
+		 */
+		if (const auto runtime = std::getenv("XDG_RUNTIME_DIR"); runtime && is_absolute(runtime))
+			runtime_dir_ = runtime;
+	}
 
-    /**
-     * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
-     *
-     * \return the config directory
-     */
-    inline const std::string& config_home() const noexcept
-    {
-        return config_home_;
-    }
+	/**
+	 * Get the config directory. ${XDG_CONFIG_HOME} or ${HOME}/.config
+	 *
+	 * \return the config directory
+	 */
+	auto get_config_home() const noexcept -> const std::string&
+	{
+		return config_home_;
+	}
 
-    /**
-     * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
-     *
-     * \return the data directory
-     */
-    inline const std::string& data_home() const noexcept
-    {
-        return data_home_;
-    }
+	/**
+	 * Get the data directory. ${XDG_DATA_HOME} or ${HOME}/.local/share
+	 *
+	 * \return the data directory
+	 */
+	auto get_data_home() const noexcept -> const std::string&
+	{
+		return data_home_;
+	}
 
-    /**
-     * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
-     *
-     * \return the cache directory
-     */
-    inline const std::string& cache_home() const noexcept
-    {
-        return cache_home_;
-    }
+	/**
+	 * Get the cache directory. ${XDG_CACHE_HOME} or ${HOME}/.cache
+	 *
+	 * \return the cache directory
+	 */
+	auto get_cache_home() const noexcept -> const std::string&
+	{
+		return cache_home_;
+	}
 
-    /**
-     * Get the runtime directory.
-     *
-     * There is no replacement for XDG_RUNTIME_DIR, if it is not set, an empty
-     * value is returned and the user is responsible of using something else.
-     *
-     * \return the runtime directory
-     */
-    inline const std::string& runtime_dir() const noexcept
-    {
-        return runtime_dir_;
-    }
+	/**
+	 * Get the runtime directory.
+	 *
+	 * There is no replacement for XDG_RUNTIME_DIR, if it is not set, an empty
+	 * value is returned and the user is responsible of using something else.
+	 *
+	 * \return the runtime directory
+	 */
+	auto get_runtime_dir() const noexcept -> const std::string&
+	{
+		return runtime_dir_;
+	}
 
-    /**
-     * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
-     *
-     * \return the list of config directories
-     */
-    inline const std::vector<std::string>& config_dirs() const noexcept
-    {
-        return config_dirs_;
-    }
+	/**
+	 * Get the standard config directories. ${XDG_CONFIG_DIRS} or { "/etc/xdg" }
+	 *
+	 * \return the list of config directories
+	 */
+	auto get_config_dirs() const noexcept -> const std::vector<std::string>&
+	{
+		return config_dirs_;
+	}
 
-    /**
-     * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share",
-     * "/usr/share" }
-     *
-     * \return the list of data directories
-     */
-    inline const std::vector<std::string>& data_dirs() const noexcept
-    {
-        return data_dirs_;
-    }
+	/**
+	 * Get the data directories. ${XDG_DATA_DIRS} or { "/usr/local/share",
+	 * "/usr/share" }
+	 *
+	 * \return the list of data directories
+	 */
+	auto get_data_dirs() const noexcept -> const std::vector<std::string>&
+	{
+		return data_dirs_;
+	}
 };
 
 } // !irccd
 
-#endif // !IRCCD_XDG_HPP
+#endif // !IRCCD_CORE_XDG_HPP
--- a/libirccd-ctl/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-ctl/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,25 +19,23 @@
 project(libirccd-ctl)
 
 set(
-    HEADERS
-    ${libirccd-ctl_SOURCE_DIR}/irccd/ctl/controller.hpp
+	HEADERS
+	${libirccd-ctl_SOURCE_DIR}/irccd/ctl/controller.hpp
 )
 
 set(
-    SOURCES
-    ${libirccd-ctl_SOURCE_DIR}/irccd/ctl/controller.cpp
+	SOURCES
+	${libirccd-ctl_SOURCE_DIR}/irccd/ctl/controller.cpp
 )
 
 irccd_define_library(
-    TARGET libirccd-ctl
-    EXPORT
-    HEADERS ${HEADERS}
-    HEADERS_DIRECTORY irccd/ctl
-    SOURCES
-        ${libirccd-ctl_SOURCE_DIR}/CMakeLists.txt
-        ${SOURCES}
-    LIBRARIES
-        libirccd
-    PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libirccd-ctl_SOURCE_DIR}>
+	TARGET libirccd-ctl
+	EXPORT
+	HEADERS ${HEADERS}
+	HEADERS_DIRECTORY irccd/ctl
+	SOURCES ${SOURCES}
+	LIBRARIES
+		libirccd
+	PUBLIC_INCLUDES
+		$<BUILD_INTERFACE:${libirccd-ctl_SOURCE_DIR}>
 )
--- a/libirccd-ctl/irccd/ctl/controller.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-ctl/irccd/ctl/controller.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,112 +30,130 @@
 
 namespace irccd {
 
+using json_util::deserializer;
+
 namespace ctl {
 
 void controller::authenticate(connect_handler handler, nlohmann::json info)
 {
-    const auto cmd = nlohmann::json::object({
-        { "command",    "auth"      },
-        { "password",   password_   }
-    });
+	const auto cmd = nlohmann::json::object({
+		{ "command",    "auth"          },
+		{ "password",   password_       }
+	});
 
-    write(cmd, [handler, info, this] (auto code) {
-        if (code) {
-            handler(std::move(code), nullptr);
-            return;
-        }
+	write(cmd, [handler, info, this] (auto code) {
+		if (code) {
+			handler(std::move(code), nullptr);
+			return;
+		}
 
-        read([handler, info] (auto code, auto) {
-            handler(std::move(code), std::move(info));
-        });
-    });
+		read([handler, info] (auto code, auto) {
+			handler(std::move(code), std::move(info));
+		});
+	});
 }
 
 void controller::verify(connect_handler handler)
 {
-    read([handler, this] (auto code, auto message) {
-        if (code) {
-            handler(std::move(code), std::move(message));
-            return;
-        }
+	read([handler, this] (auto code, auto message) {
+		if (code) {
+			handler(std::move(code), std::move(message));
+			return;
+		}
 
-        const json_util::document doc(message);
-        const auto program = doc.get<std::string>("program");
-        const auto major = doc.get<int>("major");
+		const deserializer doc(message);
+		const auto program = doc.get<std::string>("program");
+		const auto major = doc.get<int>("major");
 
-        if (!program && *program != "irccd")
-            handler(irccd_error::not_irccd, std::move(message));
-        else if (major && *major != IRCCD_VERSION_MAJOR)
-            handler(irccd_error::incompatible_version, std::move(message));
-        else {
-            if (!password_.empty())
-                authenticate(std::move(handler), message);
-            else
-                handler(code, std::move(message));
-        }
-    });
+		if (!program && *program != "irccd")
+			handler(irccd_error::not_irccd, std::move(message));
+		else if (major && *major != IRCCD_VERSION_MAJOR)
+			handler(irccd_error::incompatible_version, std::move(message));
+		else {
+			if (!password_.empty())
+				authenticate(std::move(handler), message);
+			else
+				handler(code, std::move(message));
+		}
+	});
+}
+
+controller::controller(std::unique_ptr<connector> connector) noexcept
+	: connector_(std::move(connector))
+{
+	assert(connector_);
+}
+
+auto controller::get_password() const noexcept -> const std::string&
+{
+	return password_;
+}
+
+void controller::set_password(std::string password) noexcept
+{
+	password_ = std::move(password);
 }
 
 void controller::connect(connect_handler handler)
 {
-    assert(handler);
+	assert(handler);
 
-    connector_->connect([handler, this] (auto code, auto stream) {
-        if (code)
-            handler(std::move(code), nullptr);
-        else {
-            stream_ = std::move(stream);
-            verify(std::move(handler));
-        }
-    });
+	connector_->connect([handler, this] (auto code, auto stream) {
+		if (code)
+			handler(std::move(code), nullptr);
+		else {
+			stream_ = std::move(stream);
+			verify(std::move(handler));
+		}
+	});
 }
 
-void controller::read(io::read_handler handler)
+void controller::read(stream::read_handler handler)
 {
-    assert(handler);
-    assert(stream_);
+	assert(handler);
+	assert(stream_);
 
-    auto stream = stream_;
+	auto stream = stream_;
 
-    stream_->read([this, handler, stream] (auto code, auto msg) {
-        if (code) {
-            stream_ = nullptr;
-            handler(std::move(code), std::move(msg));
-            return;
-        }
+	stream_->read([this, handler, stream] (auto code, auto msg) {
+		if (code) {
+			stream_ = nullptr;
+			handler(std::move(code), std::move(msg));
+			return;
+		}
 
-        const json_util::document doc(msg);
-        const auto e = doc.get<int>("error");
-        const auto c = doc.get<std::string>("errorCategory");
+		const deserializer doc(msg);
+		const auto e = doc.get<int>("error");
+		const auto c = doc.get<std::string>("errorCategory");
 
-        if (e && c) {
-            if (*c == "irccd")
-                code = make_error_code(static_cast<irccd_error::error>(*e));
-            else if (*c == "server")
-                code = make_error_code(static_cast<server_error::error>(*e));
-            else if (*c == "plugin")
-                code = make_error_code(static_cast<plugin_error::error>(*e));
-            else if (*c == "rule")
-                code = make_error_code(static_cast<rule_error::error>(*e));
-        }
+		if (e && c) {
+			if (*c == "irccd")
+				code = make_error_code(static_cast<irccd_error::error>(*e));
+			else if (*c == "server")
+				code = make_error_code(static_cast<server_error::error>(*e));
+			else if (*c == "plugin")
+				code = make_error_code(static_cast<plugin_error::error>(*e));
+			else if (*c == "rule")
+				code = make_error_code(static_cast<rule_error::error>(*e));
+		}
 
-        handler(std::move(code), std::move(msg));
-    });
+		handler(std::move(code), std::move(msg));
+	});
 }
 
-void controller::write(nlohmann::json message, io::write_handler handler)
+void controller::write(nlohmann::json message, stream::write_handler handler)
 {
-    assert(message.is_object());
-    assert(stream_);
+	assert(message.is_object());
+	assert(stream_);
 
-    auto stream = stream_;
+	auto stream = stream_;
 
-    stream_->write(std::move(message), [this, stream, handler] (auto code) {
-        if (code)
-            stream_ = nullptr;
-        if (handler)
-            handler(std::move(code));
-    });
+	stream_->write(std::move(message), [this, stream, handler] (auto code) {
+		if (code)
+			stream_ = nullptr;
+		if (handler)
+			handler(std::move(code));
+	});
 }
 
 } // !ctl
--- a/libirccd-ctl/irccd/ctl/controller.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-ctl/irccd/ctl/controller.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -47,86 +47,76 @@
  */
 class controller {
 public:
-    /**
-     * Connection completion handler.
-     *
-     * This callback is called when connection has been completed or failed. In
-     * both case, the error code is set and the JSON object may contain the
-     * irccd program information.
-     */
-    using connect_handler = std::function<void (std::error_code, nlohmann::json)>;
+	/**
+	 * Connection completion handler.
+	 *
+	 * This callback is called when connection has been completed or failed. In
+	 * both case, the error code is set and the JSON object may contain the
+	 * irccd program information.
+	 */
+	using connect_handler = std::function<void (std::error_code, nlohmann::json)>;
 
 private:
-    std::unique_ptr<io::connector> connector_;
-    std::shared_ptr<io::stream> stream_;
-    std::string password_;
+	std::unique_ptr<connector> connector_;
+	std::shared_ptr<stream> stream_;
+	std::string password_;
 
-    void authenticate(connect_handler, nlohmann::json);
-    void verify(connect_handler);
+	void authenticate(connect_handler, nlohmann::json);
+	void verify(connect_handler);
 
 public:
-    /**
-     * Construct the controller with its connection.
-     *
-     * \pre connector != nullptr
-     * \
-     * \note no connect attempt is done
-     */
-    inline controller(std::unique_ptr<io::connector> connector) noexcept
-        : connector_(std::move(connector))
-    {
-        assert(connector_);
-    }
+	/**
+	 * Construct the controller with its connection.
+	 *
+	 * \pre connector != nullptr
+	 * \
+	 * \note no connect attempt is done
+	 */
+	controller(std::unique_ptr<connector> connector) noexcept;
 
-    /**
-     * Get the optional password set.
-     *
-     * \return the password
-     */
-    inline const std::string& get_password() const noexcept
-    {
-        return password_;
-    }
+	/**
+	 * Get the optional password set.
+	 *
+	 * \return the password
+	 */
+	auto get_password() const noexcept -> const std::string&;
+
+	/**
+	 * Set an optional password.
+	 *
+	 * An empty password means no authentication (default).
+	 *
+	 * \param password the password
+	 * \note this must be called before connect
+	 */
+	void set_password(std::string password) noexcept;
 
-    /**
-     * Set an optional password.
-     *
-     * An empty password means no authentication (default).
-     *
-     * \param password the password
-     * \note this must be called before connect
-     */
-    inline void set_password(std::string password) noexcept
-    {
-        password_ = std::move(password);
-    }
+	/**
+	 * Attempt to connect to the irccd daemon.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the handler
+	 */
+	void connect(connect_handler handler);
 
-    /**
-     * Attempt to connect to the irccd daemon.
-     *
-     * \pre handler != nullptr
-     * \param handler the handler
-     */
-    void connect(connect_handler handler);
+	/**
+	 * Queue a receive operation, if receive operations are already running,
+	 * it is queued and ran once ready.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the recv handler
+	 */
+	void read(stream::read_handler handler);
 
-    /**
-     * Queue a receive operation, if receive operations are already running, it
-     * is queued and ran once ready.
-     *
-     * \pre handler != nullptr
-     * \param handler the recv handler
-     */
-    void read(io::read_handler handler);
-
-    /**
-     * Queue a send operation, if receive operations are already running, it is
-     * queued and ran once ready.
-     *
-     * \pre message.is_object()
-     * \param message the JSON message
-     * \param handler the optional completion handler
-     */
-    void write(nlohmann::json message, io::write_handler handler = nullptr);
+	/**
+	 * Queue a send operation, if receive operations are already running, it
+	 * is queued and ran once ready.
+	 *
+	 * \pre message.is_object()
+	 * \param message the JSON message
+	 * \param handler the optional completion handler
+	 */
+	void write(nlohmann::json message, stream::write_handler handler = nullptr);
 };
 
 } // !ctl
--- a/libirccd-js/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -21,58 +21,58 @@
 find_package(Boost REQUIRED QUIET COMPONENTS timer)
 
 set(
-    HEADERS
-    ${libirccd-js_SOURCE_DIR}/irccd/js/directory_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/duk.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/elapsed_timer_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/file_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/irccd_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/js_plugin.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/logger_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/plugin_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/server_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/system_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/timer_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/unicode.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/unicode_js_api.hpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/util_js_api.hpp
+	HEADERS
+	${libirccd-js_SOURCE_DIR}/irccd/js/directory_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/duk.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/elapsed_timer_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/file_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/irccd_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/js_plugin.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/logger_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/plugin_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/server_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/system_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/timer_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/unicode.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/unicode_js_api.hpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/util_js_api.hpp
 )
 
 set(
-    SOURCES
-    ${libirccd-js_SOURCE_DIR}/irccd/js/duk.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/directory_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/elapsed_timer_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/file_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/irccd_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/js_plugin.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/logger_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/plugin_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/server_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/system_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/timer_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/unicode.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/unicode_js_api.cpp
-    ${libirccd-js_SOURCE_DIR}/irccd/js/util_js_api.cpp
+	SOURCES
+	${libirccd-js_SOURCE_DIR}/irccd/js/duk.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/directory_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/elapsed_timer_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/file_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/irccd_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/js_plugin.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/logger_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/plugin_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/server_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/system_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/timer_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/unicode.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/unicode_js_api.cpp
+	${libirccd-js_SOURCE_DIR}/irccd/js/util_js_api.cpp
 )
 
 irccd_define_library(
-    TARGET libirccd-js
-    EXPORT
-    HEADERS ${HEADERS}
-    HEADERS_DIRECTORY irccd/js
-    SOURCES
-        ${libirccd-js_SOURCE_DIR}/CMakeLists.txt
-        ${SOURCES}
-        $<TARGET_OBJECTS:libduktape>
-    FLAGS
-        DUK_OPT_CPP_EXCEPTIONS
-    LIBRARIES
-        Boost::timer
-        libirccd
-    PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${duktape_SOURCE_DIR}>
-        $<BUILD_INTERFACE:${libirccd-js_SOURCE_DIR}>
+	TARGET libirccd-js
+	EXPORT
+	HEADERS ${HEADERS}
+	HEADERS_DIRECTORY irccd/js
+	SOURCES
+		${libirccd-js_SOURCE_DIR}/CMakeLists.txt
+		${SOURCES}
+		$<TARGET_OBJECTS:libduktape>
+	FLAGS
+		DUK_OPT_CPP_EXCEPTIONS
+	LIBRARIES
+		Boost::timer
+		libirccd
+	PUBLIC_INCLUDES
+		$<BUILD_INTERFACE:${duktape_SOURCE_DIR}>
+		$<BUILD_INTERFACE:${libirccd-js_SOURCE_DIR}>
 )
--- a/libirccd-js/irccd/js/directory_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/directory_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -48,17 +48,17 @@
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_ret_t
 {
-    try {
-        return handler();
-    } catch (const boost::system::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler();
+	} catch (const boost::system::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -70,20 +70,20 @@
  */
 auto path(duk_context* ctx) -> std::string
 {
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, "path");
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, "path");
 
-    if (duk_get_type(ctx, -1) != DUK_TYPE_STRING)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Directory object");
+	if (duk_get_type(ctx, -1) != DUK_TYPE_STRING)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Directory object");
 
-    const auto ret = duk::get<std::string>(ctx, -1);
+	const auto ret = duk::get<std::string>(ctx, -1);
 
-    if (ret.empty())
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "directory object has empty path");
+	if (ret.empty())
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "directory object has empty path");
 
-    duk_pop_n(ctx, 2);
+	duk_pop_n(ctx, 2);
 
-    return ret;
+	return ret;
 }
 
 // }}}
@@ -101,41 +101,41 @@
  */
 auto find(duk_context* ctx, std::string base, bool recursive, int pattern_index) -> duk_ret_t
 {
-    /*
-     * Helper for checking if it's a valid RegExp object.
-     */
-    const auto is_regex = [&] {
-        duk_get_global_string(ctx, "RegExp");
-        const auto result = duk_instanceof(ctx, pattern_index, -1);
-        duk_pop(ctx);
+	/*
+	 * Helper for checking if it's a valid RegExp object.
+	 */
+	const auto is_regex = [&] {
+		duk_get_global_string(ctx, "RegExp");
+		const auto result = duk_instanceof(ctx, pattern_index, -1);
+		duk_pop(ctx);
 
-        return result;
-    };
+		return result;
+	};
 
-    /*
-     * Helper for getting regex source.
-     */
-    const auto pattern = [&] {
-        duk_get_prop_string(ctx, pattern_index, "source");
-        const auto pattern = duk_to_string(ctx, -1);
-        duk_pop(ctx);
+	/*
+	 * Helper for getting regex source.
+	 */
+	const auto pattern = [&] {
+		duk_get_prop_string(ctx, pattern_index, "source");
+		const auto pattern = duk_to_string(ctx, -1);
+		duk_pop(ctx);
 
-        return pattern;
-    };
+		return pattern;
+	};
 
-    std::string path;
+	std::string path;
 
-    if (duk_is_string(ctx, pattern_index))
-        path = fs_util::find(base, duk::get<std::string>(ctx, pattern_index), recursive);
-    else if (is_regex())
-        path = fs_util::find(base, pattern(), recursive);
-    else
-        throw duk::type_error("pattern must be a string or a regex expression");
+	if (duk_is_string(ctx, pattern_index))
+		path = fs_util::find(base, duk::get<std::string>(ctx, pattern_index), recursive);
+	else if (is_regex())
+		path = fs_util::find(base, pattern(), recursive);
+	else
+		throw duk::type_error("pattern must be a string or a regex expression");
 
-    if (path.empty())
-        return 0;
+	if (path.empty())
+		return 0;
 
-    return duk::push(ctx, path);
+	return duk::push(ctx, path);
 }
 
 // }}}
@@ -150,15 +150,15 @@
  */
 auto remove(const std::string& path, bool recursive) -> duk_ret_t
 {
-    if (!boost::filesystem::is_directory(path))
-        throw std::system_error(make_error_code(std::errc::invalid_argument));
+	if (!boost::filesystem::is_directory(path))
+		throw std::system_error(make_error_code(std::errc::invalid_argument));
 
-    if (!recursive)
-        boost::filesystem::remove(path);
-    else
-        boost::filesystem::remove_all(path);
+	if (!recursive)
+		boost::filesystem::remove(path);
+	else
+		boost::filesystem::remove_all(path);
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -182,9 +182,9 @@
  */
 auto Directory_prototype_find(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return find(ctx, path(ctx), duk::get<bool>(ctx, 1), 0);
-    });
+	return wrap(ctx, [&] {
+		return find(ctx, path(ctx), duk::get<bool>(ctx, 1), 0);
+	});
 }
 
 // }}}
@@ -205,9 +205,9 @@
  */
 auto Directory_prototype_remove(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return remove(path(ctx), duk::get<bool>(ctx, 0));
-    });
+	return wrap(ctx, [&] {
+		return remove(path(ctx), duk::get<bool>(ctx, 0));
+	});
 }
 
 // }}}
@@ -227,40 +227,40 @@
  */
 auto Directory_constructor(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        if (!duk_is_constructor_call(ctx))
-            return 0;
+	return wrap(ctx, [&] {
+		if (!duk_is_constructor_call(ctx))
+			return 0;
 
-        const auto path = duk::require<std::string>(ctx, 0);
+		const auto path = duk::require<std::string>(ctx, 0);
 
-        if (!boost::filesystem::is_directory(path))
-            throw std::system_error(make_error_code(std::errc::invalid_argument));
+		if (!boost::filesystem::is_directory(path))
+			throw std::system_error(make_error_code(std::errc::invalid_argument));
 
-        duk_push_this(ctx);
+		duk_push_this(ctx);
 
-        // 'entries' property.
-        duk_push_string(ctx, "entries");
-        duk_push_array(ctx);
+		// 'entries' property.
+		duk_push_string(ctx, "entries");
+		duk_push_array(ctx);
 
-        unsigned i = 0;
-        for (const auto& entry : boost::filesystem::directory_iterator(path)) {
-            duk_push_object(ctx);
-            duk::push(ctx, entry.path().filename().string());
-            duk_put_prop_string(ctx, -2, "name");
-            duk_push_int(ctx, entry.status().type());
-            duk_put_prop_string(ctx, -2, "type");
-            duk_put_prop_index(ctx, -2, i++);
-        }
+		unsigned i = 0;
+		for (const auto& entry : boost::filesystem::directory_iterator(path)) {
+			duk_push_object(ctx);
+			duk::push(ctx, entry.path().filename().string());
+			duk_put_prop_string(ctx, -2, "name");
+			duk_push_int(ctx, entry.status().type());
+			duk_put_prop_string(ctx, -2, "type");
+			duk_put_prop_index(ctx, -2, i++);
+		}
 
-        duk_def_prop(ctx, -3, DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_VALUE);
+		duk_def_prop(ctx, -3, DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_VALUE);
 
-        // 'path' property.
-        duk::push(ctx, "path");
-        duk::push(ctx, path);
-        duk_def_prop(ctx, -3, DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_VALUE);
+		// 'path' property.
+		duk::push(ctx, "path");
+		duk::push(ctx, path);
+		duk_def_prop(ctx, -3, DUK_DEFPROP_ENUMERABLE | DUK_DEFPROP_HAVE_VALUE);
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -284,9 +284,9 @@
  */
 auto Directory_find(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return find(ctx, duk::require<std::string>(ctx, 0), duk::get<bool>(ctx, 2), 1);
-    });
+	return wrap(ctx, [&] {
+		return find(ctx, duk::require<std::string>(ctx, 0), duk::get<bool>(ctx, 2), 1);
+	});
 }
 
 // }}}
@@ -307,9 +307,9 @@
  */
 auto Directory_remove(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return remove(duk::require<std::string>(ctx, 0), duk::get<bool>(ctx, 1));
-    });
+	return wrap(ctx, [&] {
+		return remove(duk::require<std::string>(ctx, 0), duk::get<bool>(ctx, 1));
+	});
 }
 
 // }}}
@@ -330,11 +330,11 @@
  */
 auto Directory_mkdir(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        boost::filesystem::create_directories(duk::require<std::string>(ctx, 0));
+	return wrap(ctx, [&] {
+		boost::filesystem::create_directories(duk::require<std::string>(ctx, 0));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -342,28 +342,28 @@
 // {{{ definitions
 
 const duk_function_list_entry methods[] = {
-    { "find",           Directory_prototype_find,   DUK_VARARGS },
-    { "remove",         Directory_prototype_remove, 1           },
-    { nullptr,          nullptr,                    0           }
+	{ "find",               Directory_prototype_find,       DUK_VARARGS     },
+	{ "remove",             Directory_prototype_remove,     1               },
+	{ nullptr,              nullptr,                        0               }
 };
 
 const duk_function_list_entry functions[] = {
-    { "find",           Directory_find,             DUK_VARARGS },
-    { "mkdir",          Directory_mkdir,            DUK_VARARGS },
-    { "remove",         Directory_remove,           DUK_VARARGS },
-    { nullptr,          nullptr,                    0           }
+	{ "find",               Directory_find,                 DUK_VARARGS     },
+	{ "mkdir",              Directory_mkdir,                DUK_VARARGS     },
+	{ "remove",             Directory_remove,               DUK_VARARGS     },
+	{ nullptr,              nullptr,                        0               }
 };
 
 const duk_number_list_entry constants[] = {
-    { "TypeFile",       static_cast<int>(fs::regular_file)      },
-    { "TypeDir",        static_cast<int>(fs::directory_file)    },
-    { "TypeLink",       static_cast<int>(fs::symlink_file)      },
-    { "TypeBlock",      static_cast<int>(fs::block_file)        },
-    { "TypeCharacter",  static_cast<int>(fs::character_file)    },
-    { "TypeFifo",       static_cast<int>(fs::fifo_file)         },
-    { "TypeSocket",     static_cast<int>(fs::socket_file)       },
-    { "TypeUnknown",    static_cast<int>(fs::type_unknown)      },
-    { nullptr,          0                                       }
+	{ "TypeFile",           static_cast<int>(fs::regular_file)              },
+	{ "TypeDir",            static_cast<int>(fs::directory_file)            },
+	{ "TypeLink",           static_cast<int>(fs::symlink_file)              },
+	{ "TypeBlock",          static_cast<int>(fs::block_file)                },
+	{ "TypeCharacter",      static_cast<int>(fs::character_file)            },
+	{ "TypeFifo",           static_cast<int>(fs::fifo_file)	                },
+	{ "TypeSocket",         static_cast<int>(fs::socket_file)               },
+	{ "TypeUnknown",	static_cast<int>(fs::type_unknown)              },
+	{ nullptr,              0                                               }
 };
 
 // }}}
@@ -374,31 +374,31 @@
 
 auto directory_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Directory";
+	return "Irccd.Directory";
 }
 
 void directory_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_c_function(plugin->get_context(), Directory_constructor, 2);
-    duk_put_number_list(plugin->get_context(), -1, constants);
-    duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_c_function(plugin->get_context(), Directory_constructor, 2);
+	duk_put_number_list(plugin->get_context(), -1, constants);
+	duk_put_function_list(plugin->get_context(), -1, functions);
 
 #if BOOST_OS_WINDOWS
-    duk_push_string(plugin->get_context(), "\\");
+	duk_push_string(plugin->get_context(), "\\");
 #else
-    duk_push_string(plugin->get_context(), "/");
+	duk_push_string(plugin->get_context(), "/");
 #endif
 
-    duk_put_prop_string(plugin->get_context(), -2, "separator");
+	duk_put_prop_string(plugin->get_context(), -2, "separator");
 
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, methods);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "Directory");
-    duk_pop(plugin->get_context());
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, methods);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "Directory");
+	duk_pop(plugin->get_context());
 }
 
 // }}}
--- a/libirccd-js/irccd/js/directory_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/directory_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class directory_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/duk.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/duk.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,31 +27,31 @@
 
 stack_guard::stack_guard(duk_context* ctx, unsigned expected) noexcept
 #if !defined(NDEBUG)
-    : context_(ctx)
-    , expected_(expected)
-    , at_start_(duk_get_top(ctx))
+	: context_(ctx)
+	, expected_(expected)
+	, at_start_(duk_get_top(ctx))
 #endif
 {
 #if defined(NDEBUG)
-    (void)ctx;
-    (void)expected;
+	(void)ctx;
+	(void)expected;
 #endif
 }
 
 stack_guard::~stack_guard() noexcept
 {
 #if !defined(NDEBUG)
-    auto result = duk_get_top(context_) - at_start_;
+	auto result = duk_get_top(context_) - at_start_;
 
-    if (result != static_cast<int>(expected_)) {
-        std::fprintf(stderr, "Corrupt stack detection in stack_guard:\n");
-        std::fprintf(stderr, "  Size at start:           %d\n", at_start_);
-        std::fprintf(stderr, "  Size at end:             %d\n", duk_get_top(context_));
-        std::fprintf(stderr, "  Expected (user):         %u\n", expected_);
-        std::fprintf(stderr, "  Expected (adjusted):     %u\n", expected_ + at_start_);
-        std::fprintf(stderr, "  Difference count:       %+d\n", result - expected_);
-        std::abort();
-    }
+	if (result != static_cast<int>(expected_)) {
+		std::fprintf(stderr, "Corrupt stack detection in stack_guard:\n");
+		std::fprintf(stderr, "  Size at start:          %d\n", at_start_);
+		std::fprintf(stderr, "  Size at end:            %d\n", duk_get_top(context_));
+		std::fprintf(stderr, "  Expected (user):        %u\n", expected_);
+		std::fprintf(stderr, "  Expected (adjusted):    %u\n", expected_ + at_start_);
+		std::fprintf(stderr, "  Difference count:       %+d\n", result - expected_);
+		std::abort();
+	}
 #endif
 }
 
@@ -60,18 +60,18 @@
 // {{{ context
 
 context::context() noexcept
-    : handle_(duk_create_heap_default(), duk_destroy_heap)
+	: handle_(duk_create_heap_default(), duk_destroy_heap)
 {
 }
 
 context::operator duk_context*() noexcept
 {
-    return handle_.get();
+	return handle_.get();
 }
 
 context::operator duk_context*() const noexcept
 {
-    return handle_.get();
+	return handle_.get();
 }
 
 // }}}
@@ -83,42 +83,42 @@
                        std::string stack,
                        std::string file_name,
                        unsigned line_number) noexcept
-    : name_(std::move(name))
-    , message_(std::move(message))
-    , stack_(std::move(stack))
-    , file_name_(std::move(file_name))
-    , line_number_(line_number)
+	: name_(std::move(name))
+	, message_(std::move(message))
+	, stack_(std::move(stack))
+	, file_name_(std::move(file_name))
+	, line_number_(line_number)
 {
 }
 
 auto stack_info::get_name() const noexcept -> const std::string&
 {
-    return name_;
+	return name_;
 }
 
 auto stack_info::get_message() const noexcept -> const std::string&
 {
-    return message_;
+	return message_;
 }
 
 auto stack_info::get_stack() const noexcept -> const std::string&
 {
-    return stack_;
+	return stack_;
 }
 
 auto stack_info::get_file_name() const noexcept -> const std::string&
 {
-    return file_name_;
+	return file_name_;
 }
 
 auto stack_info::get_line_number() const noexcept -> unsigned
 {
-    return line_number_;
+	return line_number_;
 }
 
 auto stack_info::what() const noexcept -> const char*
 {
-    return message_.c_str();
+	return message_.c_str();
 }
 
 // }}}
@@ -126,19 +126,19 @@
 // {{{ error
 
 error::error(int type, std::string message) noexcept
-    : type_(type)
-    , message_(std::move(message))
+	: type_(type)
+	, message_(std::move(message))
 {
 }
 
 error::error(std::string message) noexcept
-    : message_(std::move(message))
+	: message_(std::move(message))
 {
 }
 
 void error::create(duk_context* ctx) const
 {
-    duk_push_error_object(ctx, type_, "%s", message_.c_str());
+	duk_push_error_object(ctx, type_, "%s", message_.c_str());
 }
 
 // }}}
@@ -146,7 +146,7 @@
 // {{{ eval_error
 
 eval_error::eval_error(std::string message) noexcept
-    : error(DUK_ERR_EVAL_ERROR, std::move(message))
+	: error(DUK_ERR_EVAL_ERROR, std::move(message))
 {
 }
 
@@ -155,7 +155,7 @@
 // {{{ range_error
 
 range_error::range_error(std::string message) noexcept
-    : error(DUK_ERR_RANGE_ERROR, std::move(message))
+	: error(DUK_ERR_RANGE_ERROR, std::move(message))
 {
 }
 
@@ -164,7 +164,7 @@
 // {{{ reference_error
 
 reference_error::reference_error(std::string message) noexcept
-    : error(DUK_ERR_REFERENCE_ERROR, std::move(message))
+	: error(DUK_ERR_REFERENCE_ERROR, std::move(message))
 {
 }
 
@@ -173,7 +173,7 @@
 // {{{ syntax_error
 
 syntax_error::syntax_error(std::string message) noexcept
-    : error(DUK_ERR_SYNTAX_ERROR, std::move(message))
+	: error(DUK_ERR_SYNTAX_ERROR, std::move(message))
 {
 }
 
@@ -182,7 +182,7 @@
 // {{{ type_error
 
 type_error::type_error(std::string message) noexcept
-    : error(DUK_ERR_TYPE_ERROR, std::move(message))
+	: error(DUK_ERR_TYPE_ERROR, std::move(message))
 {
 }
 
@@ -191,7 +191,7 @@
 // {{{ uri_error
 
 uri_error::uri_error(std::string message) noexcept
-    : error(DUK_ERR_URI_ERROR, std::move(message))
+	: error(DUK_ERR_URI_ERROR, std::move(message))
 {
 }
 
@@ -201,30 +201,30 @@
 
 auto get_stack(duk_context* ctx, int index, bool pop) -> stack_info
 {
-    index = duk_normalize_index(ctx, index);
+	index = duk_normalize_index(ctx, index);
 
-    duk_get_prop_string(ctx, index, "name");
-    auto name = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "message");
-    auto message = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "fileName");
-    auto file_name = duk_to_string(ctx, -1);
-    duk_get_prop_string(ctx, index, "lineNumber");
-    auto line_number = duk_to_uint(ctx, -1);
-    duk_get_prop_string(ctx, index, "stack");
-    auto stack = duk_to_string(ctx, -1);
-    duk_pop_n(ctx, 5);
+	duk_get_prop_string(ctx, index, "name");
+	auto name = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "message");
+	auto message = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "fileName");
+	auto file_name = duk_to_string(ctx, -1);
+	duk_get_prop_string(ctx, index, "lineNumber");
+	auto line_number = duk_to_uint(ctx, -1);
+	duk_get_prop_string(ctx, index, "stack");
+	auto stack = duk_to_string(ctx, -1);
+	duk_pop_n(ctx, 5);
 
-    if (pop)
-        duk_remove(ctx, index);
+	if (pop)
+		duk_remove(ctx, index);
 
-    return {
-        std::move(name),
-        std::move(message),
-        std::move(stack),
-        std::move(file_name),
-        line_number
-    };
+	return {
+		std::move(name),
+		std::move(message),
+		std::move(stack),
+		std::move(file_name),
+		line_number
+	};
 }
 
 // }}}
@@ -233,7 +233,7 @@
 
 void type_traits<std::exception>::raise(duk_context* ctx, const std::exception& ex)
 {
-    duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
+	duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
 }
 
 // }}}
@@ -242,8 +242,8 @@
 
 void type_traits<error>::raise(duk_context* ctx, const error& ex)
 {
-    ex.create(ctx);
-    duk_throw(ctx);
+	ex.create(ctx);
+	duk_throw(ctx);
 }
 
 // }}}
@@ -252,17 +252,17 @@
 
 void type_traits<bool>::push(duk_context* ctx, bool value)
 {
-    duk_push_boolean(ctx, value);
+	duk_push_boolean(ctx, value);
 }
 
 auto type_traits<bool>::get(duk_context* ctx, duk_idx_t index) -> bool
 {
-    return duk_get_boolean(ctx, index);
+	return duk_get_boolean(ctx, index);
 }
 
 auto type_traits<bool>::require(duk_context* ctx, duk_idx_t index) -> bool
 {
-    return duk_require_boolean(ctx, index);
+	return duk_require_boolean(ctx, index);
 }
 
 // }}}
@@ -271,17 +271,17 @@
 
 void type_traits<duk_double_t>::push(duk_context* ctx, duk_double_t value)
 {
-    duk_push_number(ctx, value);
+	duk_push_number(ctx, value);
 }
 
 auto type_traits<duk_double_t>::get(duk_context* ctx, duk_idx_t index) -> duk_double_t
 {
-    return duk_get_number(ctx, index);
+	return duk_get_number(ctx, index);
 }
 
 auto type_traits<duk_double_t>::require(duk_context* ctx, duk_idx_t index) -> duk_double_t
 {
-    return duk_require_number(ctx, index);
+	return duk_require_number(ctx, index);
 }
 
 // }}}
@@ -290,17 +290,17 @@
 
 void type_traits<duk_int_t>::push(duk_context* ctx, duk_int_t value)
 {
-    duk_push_int(ctx, value);
+	duk_push_int(ctx, value);
 }
 
 auto type_traits<duk_int_t>::get(duk_context* ctx, duk_idx_t index) -> duk_int_t
 {
-    return duk_get_int(ctx, index);
+	return duk_get_int(ctx, index);
 }
 
 auto type_traits<duk_int_t>::require(duk_context* ctx, duk_idx_t index) -> duk_int_t
 {
-    return duk_require_int(ctx, index);
+	return duk_require_int(ctx, index);
 }
 
 // }}}
@@ -309,17 +309,17 @@
 
 void type_traits<duk_uint_t>::push(duk_context* ctx, duk_uint_t value)
 {
-    duk_push_uint(ctx, value);
+	duk_push_uint(ctx, value);
 }
 
 auto type_traits<duk_uint_t>::get(duk_context* ctx, duk_idx_t index) -> duk_uint_t
 {
-    return duk_get_uint(ctx, index);
+	return duk_get_uint(ctx, index);
 }
 
 auto type_traits<duk_uint_t>::require(duk_context* ctx, duk_idx_t index) -> duk_uint_t
 {
-    return duk_require_uint(ctx, index);
+	return duk_require_uint(ctx, index);
 }
 
 // }}}
@@ -328,17 +328,17 @@
 
 void type_traits<const char*>::push(duk_context* ctx, const char* value)
 {
-    duk_push_string(ctx, value);
+	duk_push_string(ctx, value);
 }
 
 auto type_traits<const char*>::get(duk_context* ctx, duk_idx_t index) -> const char*
 {
-    return duk_get_string(ctx, index);
+	return duk_get_string(ctx, index);
 }
 
 auto type_traits<const char*>::require(duk_context* ctx, duk_idx_t index) -> const char*
 {
-    return duk_require_string(ctx, index);
+	return duk_require_string(ctx, index);
 }
 
 // }}}
@@ -347,23 +347,23 @@
 
 void type_traits<std::string>::push(duk_context* ctx, const std::string& value)
 {
-    duk_push_lstring(ctx, value.data(), value.size());
+	duk_push_lstring(ctx, value.data(), value.size());
 }
 
 auto type_traits<std::string>::get(duk_context* ctx, duk_idx_t index) -> std::string
 {
-    duk_size_t length;
-    const char* str = duk_get_lstring(ctx, index, &length);
+	duk_size_t length;
+	const char* str = duk_get_lstring(ctx, index, &length);
 
-    return { str, length };
+	return { str, length };
 }
 
 auto type_traits<std::string>::require(duk_context* ctx, duk_idx_t index) -> std::string
 {
-    duk_size_t length;
-    const char* str = duk_require_lstring(ctx, index, &length);
+	duk_size_t length;
+	const char* str = duk_require_lstring(ctx, index, &length);
 
-    return { str, length };
+	return { str, length };
 }
 
 // }}}
@@ -372,23 +372,23 @@
 
 void type_traits<std::string_view>::push(duk_context* ctx, std::string_view value)
 {
-    duk_push_lstring(ctx, value.data(), value.size());
+	duk_push_lstring(ctx, value.data(), value.size());
 }
 
 auto type_traits<std::string_view>::get(duk_context* ctx, duk_idx_t index) -> std::string_view
 {
-    duk_size_t length;
-    const char* str = duk_get_lstring(ctx, index, &length);
+	duk_size_t length;
+	const char* str = duk_get_lstring(ctx, index, &length);
 
-    return { str, length };
+	return { str, length };
 }
 
 auto type_traits<std::string_view>::require(duk_context* ctx, duk_idx_t index) -> std::string_view
 {
-    duk_size_t length;
-    const char* str = duk_require_lstring(ctx, index, &length);
+	duk_size_t length;
+	const char* str = duk_require_lstring(ctx, index, &length);
 
-    return { str, length };
+	return { str, length };
 }
 
 // }}}
--- a/libirccd-js/irccd/js/duk.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/duk.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -16,8 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef DUKTAPE_HPP
-#define DUKTAPE_HPP
+#ifndef IRCCD_JS_DUK_HPP
+#define IRCCD_JS_DUK_HPP
 
 /**
  * \file duk.hpp
@@ -55,28 +55,28 @@
 class stack_guard {
 #if !defined(NDEBUG)
 private:
-    duk_context* context_;
-    unsigned expected_;
-    int at_start_;
+	duk_context* context_;
+	unsigned expected_;
+	int at_start_;
 #endif
 
 public:
-    /**
-     * Create the stack checker.
-     *
-     * No-op if NDEBUG is set.
-     *
-     * \param ctx the context
-     * \param expected the size expected relative to the already existing values
-     */
-    stack_guard(duk_context* ctx, unsigned expected = 0) noexcept;
+	/**
+	 * Create the stack checker.
+	 *
+	 * No-op if NDEBUG is set.
+	 *
+	 * \param ctx the context
+	 * \param expected the size expected relative to the already existing values
+	 */
+	stack_guard(duk_context* ctx, unsigned expected = 0) noexcept;
 
-    /**
-     * Verify the expected size.
-     *
-     * No-op if NDEBUG is set.
-     */
-    ~stack_guard() noexcept;
+	/**
+	 * Verify the expected size.
+	 *
+	 * No-op if NDEBUG is set.
+	 */
+	~stack_guard() noexcept;
 };
 
 // }}}
@@ -90,42 +90,42 @@
  */
 class context {
 private:
-    std::unique_ptr<duk_context, void (*)(duk_context*)> handle_;
+	std::unique_ptr<duk_context, void (*)(duk_context*)> handle_;
 
-    context(const context&) = delete;
-    void operator=(const context&) = delete;
+	context(const context&) = delete;
+	void operator=(const context&) = delete;
 
 public:
-    /**
-     * Create default context.
-     */
-    context() noexcept;
+	/**
+	 * Create default context.
+	 */
+	context() noexcept;
 
-    /**
-     * Default move constructor.
-     */
-    context(context&&) noexcept = default;
+	/**
+	 * Default move constructor.
+	 */
+	context(context&&) noexcept = default;
 
-    /**
-     * Convert the context to the native Duktape/C type.
-     *
-     * \return the duk_context
-     */
-    operator duk_context*() noexcept;
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * \return the duk_context
+	 */
+	operator duk_context*() noexcept;
 
-    /**
-     * Convert the context to the native Duktape/C type.
-     *
-     * \return the duk_context
-     */
-    operator duk_context*() const noexcept;
+	/**
+	 * Convert the context to the native Duktape/C type.
+	 *
+	 * \return the duk_context
+	 */
+	operator duk_context*() const noexcept;
 
-    /**
-     * Default move assignment operator.
-     *
-     * \return this
-     */
-    auto operator=(context&&) noexcept -> context& = default;
+	/**
+	 * Default move assignment operator.
+	 *
+	 * \return this
+	 */
+	auto operator=(context&&) noexcept -> context& = default;
 };
 
 // }}}
@@ -139,69 +139,69 @@
  */
 class stack_info : public std::exception {
 private:
-    std::string name_;
-    std::string message_;
-    std::string stack_;
-    std::string file_name_;
-    unsigned line_number_;
+	std::string name_;
+	std::string message_;
+	std::string stack_;
+	std::string file_name_;
+	unsigned line_number_;
 
 public:
-    /**
-     * Construct the stack information.
-     *
-     * \param name the exception name (e.g. ReferenceError)
-     * \param message the error message
-     * \param stack the stack trace
-     * \param file_name the optional filename
-     * \param line_number the optional line number
-     */
-    stack_info(std::string name,
-               std::string message,
-               std::string stack,
-               std::string file_name,
-               unsigned line_number = 0) noexcept;
+	/**
+	 * Construct the stack information.
+	 *
+	 * \param name the exception name (e.g. ReferenceError)
+	 * \param message the error message
+	 * \param stack the stack trace
+	 * \param file_name the optional filename
+	 * \param line_number the optional line number
+	 */
+	stack_info(std::string name,
+	           std::string message,
+	           std::string stack,
+	           std::string file_name,
+	           unsigned line_number = 0) noexcept;
 
-    /**
-     * Get the exception name.
-     *
-     * \return the exception name (e.g. ReferenceError)
-     */
-    auto get_name() const noexcept -> const std::string&;
+	/**
+	 * Get the exception name.
+	 *
+	 * \return the exception name (e.g. ReferenceError)
+	 */
+	auto get_name() const noexcept -> const std::string&;
 
-    /**
-     * Get the error message.
-     *
-     * \return the message
-     */
-    auto get_message() const noexcept -> const std::string&;
+	/**
+	 * Get the error message.
+	 *
+	 * \return the message
+	 */
+	auto get_message() const noexcept -> const std::string&;
 
-    /**
-     * Get the stack trace.
-     *
-     * \return the stack
-     */
-    auto get_stack() const noexcept -> const std::string&;
+	/**
+	 * Get the stack trace.
+	 *
+	 * \return the stack
+	 */
+	auto get_stack() const noexcept -> const std::string&;
 
-    /**
-     * Get the optional file name.
-     *
-     * \return the file name
-     */
-    auto get_file_name() const noexcept -> const std::string&;
+	/**
+	 * Get the optional file name.
+	 *
+	 * \return the file name
+	 */
+	auto get_file_name() const noexcept -> const std::string&;
 
-    /**
-     * Get the line number.
-     *
-     * \return the line number
-     */
-    auto get_line_number() const noexcept -> unsigned;
+	/**
+	 * Get the line number.
+	 *
+	 * \return the line number
+	 */
+	auto get_line_number() const noexcept -> unsigned;
 
-    /**
-     * Get the error message. This effectively returns message field.
-     *
-     * \return the message
-     */
-    auto what() const noexcept -> const char* override;
+	/**
+	 * Get the error message. This effectively returns message field.
+	 *
+	 * \return the message
+	 */
+	auto what() const noexcept -> const char* override;
 };
 
 // }}}
@@ -222,8 +222,8 @@
  * Example:
  *
  * ```cpp
- * push(ctx, 123);     // Uses type_traits<int>
- * push(ctx, true);    // Uses type_traits<bool>
+ * push(ctx, 123);	 // Uses type_traits<int>
+ * push(ctx, true);	// Uses type_traits<bool>
  * ```
  *
  * This class is specialized for the following types:
@@ -265,11 +265,11 @@
 template <typename T>
 auto push(duk_context* ctx, T&& value) -> int
 {
-    using Type = typename std::decay<T>::type;
+	using Type = typename std::decay<T>::type;
 
-    type_traits<Type>::push(ctx, std::forward<T>(value));
+	type_traits<Type>::push(ctx, std::forward<T>(value));
 
-    return 1;
+	return 1;
 }
 
 // }}}
@@ -288,9 +288,9 @@
 template <typename T>
 auto get(duk_context* ctx, duk_idx_t index)
 {
-    using Type = typename std::decay<T>::type;
+	using Type = typename std::decay<T>::type;
 
-    return type_traits<Type>::get(ctx, index);
+	return type_traits<Type>::get(ctx, index);
 }
 
 // }}}
@@ -309,9 +309,9 @@
 template <typename T>
 auto require(duk_context* ctx, duk_idx_t index)
 {
-    using Type = typename std::decay<T>::type;
+	using Type = typename std::decay<T>::type;
 
-    return type_traits<Type>::require(ctx, index);
+	return type_traits<Type>::require(ctx, index);
 }
 
 // }}}
@@ -324,39 +324,39 @@
  */
 class error {
 private:
-    int type_{DUK_ERR_ERROR};
-    std::string message_;
+	int type_{DUK_ERR_ERROR};
+	std::string message_;
 
 protected:
-    /**
-     * Constructor with a type of error specified, specially designed for
-     * derived errors.
-     *
-     * \param type of error (e.g. DUK_ERR_ERROR)
-     * \param message the message
-     */
-    error(int type, std::string message) noexcept;
+	/**
+	 * Constructor with a type of error specified, specially designed for
+	 * derived errors.
+	 *
+	 * \param type of error (e.g. DUK_ERR_ERROR)
+	 * \param message the message
+	 */
+	error(int type, std::string message) noexcept;
 
 public:
-    /**
-     * Constructor with a message.
-     *
-     * \param message the message
-     */
-    error(std::string message) noexcept;
+	/**
+	 * Constructor with a message.
+	 *
+	 * \param message the message
+	 */
+	error(std::string message) noexcept;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    ~error() = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	~error() = default;
 
-    /**
-     * Create the exception on the stack.
-     *
-     * \note the default implementation search for the global variables
-     * \param ctx the context
-     */
-    void create(duk_context* ctx) const;
+	/**
+	 * Create the exception on the stack.
+	 *
+	 * \note the default implementation search for the global variables
+	 * \param ctx the context
+	 */
+	void create(duk_context* ctx) const;
 };
 
 // }}}
@@ -368,12 +368,12 @@
  */
 class eval_error : public error {
 public:
-    /**
-     * Construct an EvalError.
-     *
-     * \param message the message
-     */
-    eval_error(std::string message) noexcept;
+	/**
+	 * Construct an EvalError.
+	 *
+	 * \param message the message
+	 */
+	eval_error(std::string message) noexcept;
 };
 
 // }}}
@@ -385,12 +385,12 @@
  */
 class range_error : public error {
 public:
-    /**
-     * Construct an RangeError.
-     *
-     * \param message the message
-     */
-    range_error(std::string message) noexcept;
+	/**
+	 * Construct an RangeError.
+	 *
+	 * \param message the message
+	 */
+	range_error(std::string message) noexcept;
 };
 
 // }}}
@@ -402,12 +402,12 @@
  */
 class reference_error : public error {
 public:
-    /**
-     * Construct an ReferenceError.
-     *
-     * \param message the message
-     */
-    reference_error(std::string message) noexcept;
+	/**
+	 * Construct an ReferenceError.
+	 *
+	 * \param message the message
+	 */
+	reference_error(std::string message) noexcept;
 };
 
 // }}}
@@ -419,12 +419,12 @@
  */
 class syntax_error : public error {
 public:
-    /**
-     * Construct an SyntaxError.
-     *
-     * \param message the message
-     */
-    syntax_error(std::string message) noexcept;
+	/**
+	 * Construct an SyntaxError.
+	 *
+	 * \param message the message
+	 */
+	syntax_error(std::string message) noexcept;
 };
 
 // }}}
@@ -436,12 +436,12 @@
  */
 class type_error : public error {
 public:
-    /**
-     * Construct an TypeError.
-     *
-     * \param message the message
-     */
-    type_error(std::string message) noexcept;
+	/**
+	 * Construct an TypeError.
+	 *
+	 * \param message the message
+	 */
+	type_error(std::string message) noexcept;
 };
 
 // }}}
@@ -453,12 +453,12 @@
  */
 class uri_error : public error {
 public:
-    /**
-     * Construct an URIError.
-     *
-     * \param message the message
-     */
-    uri_error(std::string message) noexcept;
+	/**
+	 * Construct an URIError.
+	 *
+	 * \param message the message
+	 */
+	uri_error(std::string message) noexcept;
 };
 
 // }}}
@@ -482,9 +482,9 @@
 template <typename Error>
 void raise(duk_context* ctx, Error&& error)
 {
-    using type = std::decay_t<Error>;
+	using type = std::decay_t<Error>;
 
-    type_traits<type>::raise(ctx, std::forward<Error>(error));
+	type_traits<type>::raise(ctx, std::forward<Error>(error));
 }
 
 // }}}
@@ -511,13 +511,13 @@
  */
 template <>
 struct type_traits<std::exception> {
-    /**
-     * Raise a Error object.
-     *
-     * \param ctx the Duktape context
-     * \param ex the exception
-     */
-    static void raise(duk_context* ctx, const std::exception& ex);
+	/**
+	 * Raise a Error object.
+	 *
+	 * \param ctx the Duktape context
+	 * \param ex the exception
+	 */
+	static void raise(duk_context* ctx, const std::exception& ex);
 };
 
 // }}}
@@ -529,13 +529,13 @@
  */
 template <>
 struct type_traits<error> {
-    /**
-     * Raise a error.
-     *
-     * \param ctx the Duktape context
-     * \param ex the exception
-     */
-    static void raise(duk_context* ctx, const error& ex);
+	/**
+	 * Raise a error.
+	 *
+	 * \param ctx the Duktape context
+	 * \param ex the exception
+	 */
+	static void raise(duk_context* ctx, const error& ex);
 };
 
 // }}}
@@ -547,37 +547,37 @@
  */
 template <>
 struct type_traits<bool> {
-    /**
-     * Push a boolean.
-     *
-     * Uses duk_push_boolean
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, bool value);
+	/**
+	 * Push a boolean.
+	 *
+	 * Uses duk_push_boolean
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, bool value);
 
-    /**
-     * Get a boolean.
-     *
-     * Uses duk_get_boolean.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> bool;
+	/**
+	 * Get a boolean.
+	 *
+	 * Uses duk_get_boolean.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> bool;
 
-    /**
-     * Require a boolean.
-     *
-     * Uses duk_require_boolean.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> bool;
+	/**
+	 * Require a boolean.
+	 *
+	 * Uses duk_require_boolean.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> bool;
 };
 
 // }}}
@@ -589,37 +589,37 @@
  */
 template <>
 struct type_traits<duk_double_t> {
-    /**
-     * Push a double.
-     *
-     * Uses duk_push_number
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, duk_double_t value);
+	/**
+	 * Push a double.
+	 *
+	 * Uses duk_push_number
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, duk_double_t value);
 
-    /**
-     * Get a double.
-     *
-     * Uses duk_get_number.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> duk_double_t;
+	/**
+	 * Get a double.
+	 *
+	 * Uses duk_get_number.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> duk_double_t;
 
-    /**
-     * Require a double.
-     *
-     * Uses duk_require_double.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> duk_double_t;
+	/**
+	 * Require a double.
+	 *
+	 * Uses duk_require_double.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> duk_double_t;
 };
 
 // }}}
@@ -631,37 +631,37 @@
  */
 template <>
 struct type_traits<duk_int_t> {
-    /**
-     * Push an int.
-     *
-     * Uses duk_push_int
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, duk_int_t value);
+	/**
+	 * Push an int.
+	 *
+	 * Uses duk_push_int
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, duk_int_t value);
 
-    /**
-     * Get an int.
-     *
-     * Uses duk_get_number.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> duk_int_t;
+	/**
+	 * Get an int.
+	 *
+	 * Uses duk_get_number.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> duk_int_t;
 
-    /**
-     * Require an int.
-     *
-     * Uses duk_require_int.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> duk_int_t;
+	/**
+	 * Require an int.
+	 *
+	 * Uses duk_require_int.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> duk_int_t;
 };
 
 // }}}
@@ -673,37 +673,37 @@
  */
 template <>
 struct type_traits<duk_uint_t> {
-    /**
-     * Push an unsigned int.
-     *
-     * Uses duk_push_uint
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, duk_uint_t value);
+	/**
+	 * Push an unsigned int.
+	 *
+	 * Uses duk_push_uint
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, duk_uint_t value);
 
-    /**
-     * Get an unsigned int.
-     *
-     * Uses duk_get_uint.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
+	/**
+	 * Get an unsigned int.
+	 *
+	 * Uses duk_get_uint.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
 
-    /**
-     * Require an unsigned int.
-     *
-     * Uses duk_require_uint.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
+	/**
+	 * Require an unsigned int.
+	 *
+	 * Uses duk_require_uint.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> duk_uint_t;
 };
 
 // }}}
@@ -715,37 +715,37 @@
  */
 template <>
 struct type_traits<const char*> {
-    /**
-     * Push a C string.
-     *
-     * Uses duk_push_string
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, const char* value);
+	/**
+	 * Push a C string.
+	 *
+	 * Uses duk_push_string
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, const char* value);
 
-    /**
-     * Get a C string.
-     *
-     * Uses duk_get_string.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> const char*;
+	/**
+	 * Get a C string.
+	 *
+	 * Uses duk_get_string.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> const char*;
 
-    /**
-     * Require a C string.
-     *
-     * Uses duk_require_string.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> const char*;
+	/**
+	 * Require a C string.
+	 *
+	 * Uses duk_require_string.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> const char*;
 };
 
 // }}}
@@ -757,37 +757,37 @@
  */
 template <>
 struct type_traits<std::string> {
-    /**
-     * Push a C++ std::string.
-     *
-     * Uses duk_push_lstring
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, const std::string& value);
+	/**
+	 * Push a C++ std::string.
+	 *
+	 * Uses duk_push_lstring
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, const std::string& value);
 
-    /**
-     * Get a C++ std::string.
-     *
-     * Uses duk_get_lstring.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> std::string;
+	/**
+	 * Get a C++ std::string.
+	 *
+	 * Uses duk_get_lstring.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> std::string;
 
-    /**
-     * Require a C++ std::string.
-     *
-     * Uses duk_require_lstring.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> std::string;
+	/**
+	 * Require a C++ std::string.
+	 *
+	 * Uses duk_require_lstring.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> std::string;
 };
 
 // }}}
@@ -799,37 +799,37 @@
  */
 template <>
 struct type_traits<std::string_view> : public std::true_type {
-    /**
-     * Push a C++ std::string_view.
-     *
-     * Uses duk_push_lstring
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, std::string_view value);
+	/**
+	 * Push a C++ std::string_view.
+	 *
+	 * Uses duk_push_lstring
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, std::string_view value);
 
-    /**
-     * Get a C++ std::string_view.
-     *
-     * Uses duk_get_lstring.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto get(duk_context* ctx, duk_idx_t index) -> std::string_view;
+	/**
+	 * Get a C++ std::string_view.
+	 *
+	 * Uses duk_get_lstring.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> std::string_view;
 
-    /**
-     * Require a C++ std::string_view.
-     *
-     * Uses duk_require_lstring.
-     *
-     * \param ctx the Duktape context
-     * \param index the value index
-     * \return the converted value
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> std::string_view;
+	/**
+	 * Require a C++ std::string_view.
+	 *
+	 * Uses duk_require_lstring.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> std::string_view;
 };
 
 // }}}
@@ -837,49 +837,53 @@
 // {{{ type_traits<std::vector<T>>
 
 /**
- * \brief Specialization for std::vector.
+ * \brief Specialization for std::vector<T>
  */
 template <typename T>
-struct type_traits<std::vector<T>> {
-    /**
-     * Push a vector.
-     *
-     * Uses duk_push_lstring
-     *
-     * \param ctx the Duktape context
-     * \param value the value
-     */
-    static void push(duk_context* ctx, const std::vector<T>& values)
-    {
-        using size_type = typename std::vector<T>::size_type;
+struct type_traits<std::vector<T>> : public std::true_type {
+	/**
+	 * Push a C++ std::vector<T>.
+	 *
+	 * \param ctx the Duktape context
+	 * \param value the value
+	 */
+	static void push(duk_context* ctx, const std::vector<T>& values)
+	{
+		duk_push_array(ctx);
 
-        duk_push_array(ctx);
+		for (std::size_t i = 0; i < values.size(); ++i) {
+			type_traits<T>::push(ctx, values[i]);
+			duk_put_prop_index(ctx, -2, i);
+		}
+	}
 
-        for (size_type i = 0; i < values.size(); ++i) {
-            type_traits<T>::push(ctx, values[i]);
-            duk_put_prop_index(ctx, -2, i);
-        }
-    }
-
-    static auto get(duk_context* ctx, duk_idx_t index) -> std::vector<T>
-    {
-        using size_type = typename std::vector<T>::size_type;
+	/**
+	 * Get a C++ std::vector<T>.
+	 *
+	 * \param ctx the Duktape context
+	 * \param index the value index
+	 * \return the converted value
+	 */
+	static auto get(duk_context* ctx, duk_idx_t index) -> std::vector<T>
+	{
+		const auto length = duk_get_length(ctx, index);
 
-        std::vector<T> result;
-        size_type length = duk_get_length(ctx, index);
+		std::vector<T> result;
+
+		result.reserve(length);
 
-        for (size_type i = 0; i < length; ++i) {
-            duk_get_prop_index(ctx, index, i);
-            result.push_back(type_traits<T>::get(ctx, -1));
-            duk_pop(ctx);
-        }
+		for (auto i = 0U; i < length; ++i) {
+			duk_get_prop_index(ctx, index, i);
+			result.push_back(type_traits<T>::get(ctx, -1));
+			duk_pop(ctx);
+		}
 
-        return result;
-    }
+		return result;
+	}
 };
 
 // }}}
 
 } // !irccd::js::duk
 
-#endif // !DUKTAPE_HPP
+#endif // !IRCCD_JS_DUK_HPP
--- a/libirccd-js/irccd/js/elapsed_timer_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/elapsed_timer_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,17 +31,17 @@
 
 auto self(duk_context* ctx) -> boost::timer::cpu_timer*
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, signature.data());
-    const auto ptr = static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
-    duk_pop_2(ctx);
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, signature.data());
+	const auto ptr = static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
+	duk_pop_2(ctx);
 
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
+	if (!ptr)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an ElapsedTimer object");
 
-    return ptr;
+	return ptr;
 }
 
 // }}}
@@ -56,9 +56,9 @@
  */
 auto ElapsedTimer_prototype_pause(duk_context* ctx) -> duk_ret_t
 {
-    self(ctx)->stop();
+	self(ctx)->stop();
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -73,9 +73,9 @@
  */
 auto ElapsedTimer_prototype_restart(duk_context* ctx) -> duk_ret_t
 {
-    self(ctx)->resume();
+	self(ctx)->resume();
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -93,9 +93,9 @@
  */
 auto ElapsedTimer_prototype_elapsed(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_uint(ctx, self(ctx)->elapsed().wall / 1000000LL);
+	duk_push_uint(ctx, self(ctx)->elapsed().wall / 1000000LL);
 
-    return 1;
+	return 1;
 }
 
 // }}}
@@ -110,12 +110,12 @@
  */
 auto ElapsedTimer_constructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_this(ctx);
-    duk_push_pointer(ctx, new boost::timer::cpu_timer);
-    duk_put_prop_string(ctx, -2, signature.data());
-    duk_pop(ctx);
+	duk_push_this(ctx);
+	duk_push_pointer(ctx, new boost::timer::cpu_timer);
+	duk_put_prop_string(ctx, -2, signature.data());
+	duk_pop(ctx);
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -130,12 +130,12 @@
  */
 auto ElapsedTimer_destructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_get_prop_string(ctx, 0, signature.data());
-    delete static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, signature.data());
+	duk_get_prop_string(ctx, 0, signature.data());
+	delete static_cast<boost::timer::cpu_timer*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
+	duk_del_prop_string(ctx, 0, signature.data());
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -143,10 +143,10 @@
 // {{{ definitions
 
 const duk_function_list_entry methods[] = {
-    { "elapsed",    ElapsedTimer_prototype_elapsed, 0 },
-    { "pause",      ElapsedTimer_prototype_pause,   0 },
-    { "restart",    ElapsedTimer_prototype_restart, 0 },
-    { nullptr,      nullptr,                        0 }
+	{ "elapsed",    ElapsedTimer_prototype_elapsed, 0 },
+	{ "pause",      ElapsedTimer_prototype_pause,   0 },
+	{ "restart",    ElapsedTimer_prototype_restart, 0 },
+	{ nullptr,      nullptr,                        0 }
 };
 
 // }}}
@@ -157,22 +157,22 @@
 
 auto elapsed_timer_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.ElapsedTimer";
+	return "Irccd.ElapsedTimer";
 }
 
 void elapsed_timer_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_c_function(plugin->get_context(), ElapsedTimer_constructor, 0);
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, methods);
-    duk_push_c_function(plugin->get_context(), ElapsedTimer_destructor, 1);
-    duk_set_finalizer(plugin->get_context(), -2);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "ElapsedTimer");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_c_function(plugin->get_context(), ElapsedTimer_constructor, 0);
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, methods);
+	duk_push_c_function(plugin->get_context(), ElapsedTimer_destructor, 1);
+	duk_set_finalizer(plugin->get_context(), -2);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "ElapsedTimer");
+	duk_pop(plugin->get_context());
 }
 
 // }}}
--- a/libirccd-js/irccd/js/elapsed_timer_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/elapsed_timer_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class elapsed_timer_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/file_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/file_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -41,10 +41,10 @@
 
 auto clear_crlf(std::string input) noexcept -> std::string
 {
-    if (input.length() > 0 && input.back() == '\r')
-        input.pop_back();
+	if (input.length() > 0 && input.back() == '\r')
+		input.pop_back();
 
-    return input;
+	return input;
 }
 
 // }}}
@@ -53,7 +53,7 @@
 
 auto from_errno() noexcept -> std::system_error
 {
-    return std::system_error(make_error_code(static_cast<std::errc>(errno)));
+	return std::system_error(make_error_code(static_cast<std::errc>(errno)));
 }
 
 // }}}
@@ -62,17 +62,17 @@
 
 auto self(duk_context* ctx) -> std::shared_ptr<file>
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, signature.data());
-    auto ptr = static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
-    duk_pop_2(ctx);
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, signature.data());
+	auto ptr = static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
+	duk_pop_2(ctx);
 
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a File object");
+	if (!ptr)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a File object");
 
-    return *ptr;
+	return *ptr;
 }
 
 // }}}
@@ -82,17 +82,17 @@
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_ret_t
 {
-    try {
-        return handler();
-    } catch (const boost::system::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler();
+	} catch (const boost::system::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -110,9 +110,9 @@
  */
 auto File_prototype_basename(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, fs_util::base_name(self(ctx)->get_path()));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, fs_util::base_name(self(ctx)->get_path()));
+	});
 }
 
 // }}}
@@ -127,11 +127,11 @@
  */
 auto File_prototype_close(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        self(ctx)->close();
+	return wrap(ctx, [&] {
+		self(ctx)->close();
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -149,9 +149,9 @@
  */
 auto File_prototype_dirname(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, fs_util::dir_name(self(ctx)->get_path()));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, fs_util::dir_name(self(ctx)->get_path()));
+	});
 }
 
 // }}}
@@ -171,39 +171,39 @@
  */
 auto File_prototype_lines(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        duk_push_array(ctx);
+	return wrap(ctx, [&] {
+		duk_push_array(ctx);
 
-        std::FILE* fp = self(ctx)->get_handle();
-        std::string buffer;
-        std::array<char, 128> data;
-        std::int32_t i = 0;
+		std::FILE* fp = self(ctx)->get_handle();
+		std::string buffer;
+		std::array<char, 128> data;
+		std::int32_t i = 0;
 
-        while (std::fgets(&data[0], data.size(), fp) != nullptr) {
-            buffer += data.data();
+		while (std::fgets(&data[0], data.size(), fp) != nullptr) {
+			buffer += data.data();
 
-            const auto pos = buffer.find('\n');
+			const auto pos = buffer.find('\n');
 
-            if (pos != std::string::npos) {
-                duk::push(ctx, clear_crlf(buffer.substr(0, pos)));
-                duk_put_prop_index(ctx, -2, i++);
+			if (pos != std::string::npos) {
+				duk::push(ctx, clear_crlf(buffer.substr(0, pos)));
+				duk_put_prop_index(ctx, -2, i++);
 
-                buffer.erase(0, pos + 1);
-            }
-        }
+				buffer.erase(0, pos + 1);
+			}
+		}
 
-        // Maybe an error in the stream.
-        if (std::ferror(fp))
-            throw from_errno();
+		// Maybe an error in the stream.
+		if (std::ferror(fp))
+			throw from_errno();
 
-        // Missing '\n' in end of file.
-        if (!buffer.empty()) {
-            duk::push(ctx, clear_crlf(buffer));
-            duk_put_prop_index(ctx, -2, i++);
-        }
+		// Missing '\n' in end of file.
+		if (!buffer.empty()) {
+			duk::push(ctx, clear_crlf(buffer));
+			duk_put_prop_index(ctx, -2, i++);
+		}
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -225,39 +225,39 @@
  */
 auto File_prototype_read(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        const auto fp = self(ctx)->get_handle();
-        const auto amount = duk_is_number(ctx, 0) ? duk_get_int(ctx, 0) : -1;
+	return wrap(ctx, [&] {
+		const auto fp = self(ctx)->get_handle();
+		const auto amount = duk_is_number(ctx, 0) ? duk_get_int(ctx, 0) : -1;
 
-        if (amount == 0 || !fp)
-            return 0;
+		if (amount == 0 || !fp)
+			return 0;
 
-        std::string data;
-        std::size_t total = 0;
+		std::string data;
+		std::size_t total = 0;
 
-        if (amount < 0) {
-            std::array<char, 128> buffer;
-            std::size_t nread;
+		if (amount < 0) {
+			std::array<char, 128> buffer;
+			std::size_t nread;
 
-            while ((nread = std::fread(&buffer[0], sizeof (buffer[0]), buffer.size(), fp)) > 0) {
-                if (std::ferror(fp))
-                    throw from_errno();
+			while ((nread = std::fread(&buffer[0], sizeof (buffer[0]), buffer.size(), fp)) > 0) {
+				if (std::ferror(fp))
+					throw from_errno();
 
-                std::copy(buffer.begin(), buffer.begin() + nread, std::back_inserter(data));
-                total += nread;
-            }
-        } else {
-            data.resize(static_cast<std::size_t>(amount));
-            total = std::fread(&data[0], sizeof (data[0]), static_cast<std::size_t>(amount), fp);
+				std::copy(buffer.begin(), buffer.begin() + nread, std::back_inserter(data));
+				total += nread;
+			}
+		} else {
+			data.resize(static_cast<std::size_t>(amount));
+			total = std::fread(&data[0], sizeof (data[0]), static_cast<std::size_t>(amount), fp);
 
-            if (std::ferror(fp))
-                throw from_errno();
+			if (std::ferror(fp))
+				throw from_errno();
 
-            data.resize(total);
-        }
+			data.resize(total);
+		}
 
-        return duk::push(ctx, data);
-    });
+		return duk::push(ctx, data);
+	});
 }
 
 // }}}
@@ -277,21 +277,21 @@
  */
 auto File_prototype_readline(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto fp = self(ctx)->get_handle();
+	return wrap(ctx, [&] {
+		auto fp = self(ctx)->get_handle();
 
-        if (fp == nullptr || std::feof(fp))
-            return 0;
+		if (fp == nullptr || std::feof(fp))
+			return 0;
 
-        std::string result;
+		std::string result;
 
-        for (int ch; (ch = std::fgetc(fp)) != EOF && ch != '\n'; )
-            result += (char)ch;
-        if (std::ferror(fp))
-            throw from_errno();
+		for (int ch; (ch = std::fgetc(fp)) != EOF && ch != '\n'; )
+			result += (char)ch;
+		if (std::ferror(fp))
+			throw from_errno();
 
-        return duk::push(ctx, clear_crlf(result));
-    });
+		return duk::push(ctx, clear_crlf(result));
+	});
 }
 
 // }}}
@@ -309,11 +309,11 @@
  */
 auto File_prototype_remove(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        boost::filesystem::remove(self(ctx)->get_path());
+	return wrap(ctx, [&] {
+		boost::filesystem::remove(self(ctx)->get_path());
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -334,16 +334,16 @@
  */
 auto File_prototype_seek(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto fp = self(ctx)->get_handle();
-        auto type = duk_require_int(ctx, 0);
-        auto amount = duk_require_int(ctx, 1);
+	return wrap(ctx, [&] {
+		auto fp = self(ctx)->get_handle();
+		auto type = duk_require_int(ctx, 0);
+		auto amount = duk_require_int(ctx, 1);
 
-        if (fp != nullptr && std::fseek(fp, amount, type) != 0)
-            throw from_errno();
+		if (fp != nullptr && std::fseek(fp, amount, type) != 0)
+			throw from_errno();
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -365,17 +365,17 @@
  */
 auto File_prototype_stat(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto file = self(ctx);
-        struct stat st;
+	return wrap(ctx, [&] {
+		auto file = self(ctx);
+		struct stat st;
 
-        if (file->get_handle() == nullptr && ::stat(file->get_path().c_str(), &st) < 0)
-            throw from_errno();
+		if (file->get_handle() == nullptr && ::stat(file->get_path().c_str(), &st) < 0)
+			throw from_errno();
 
-        duk::push(ctx, st);
+		duk::push(ctx, st);
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 #endif // !IRCCD_HAVE_STAT
@@ -397,20 +397,20 @@
  */
 auto File_prototype_tell(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto fp = self(ctx)->get_handle();
-        long pos;
+	return wrap(ctx, [&] {
+		auto fp = self(ctx)->get_handle();
+		long pos;
 
-        if (fp == nullptr)
-            return 0;
+		if (fp == nullptr)
+			return 0;
 
-        if ((pos = std::ftell(fp)) == -1L)
-            throw from_errno();
+		if ((pos = std::ftell(fp)) == -1L)
+			throw from_errno();
 
-        duk_push_int(ctx, pos);
+		duk_push_int(ctx, pos);
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -432,22 +432,22 @@
  */
 auto File_prototype_write(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto fp = self(ctx)->get_handle();
-        auto data = duk::require<std::string>(ctx, 0);
+	return wrap(ctx, [&] {
+		auto fp = self(ctx)->get_handle();
+		auto data = duk::require<std::string>(ctx, 0);
 
-        if (fp == nullptr)
-            return 0;
+		if (fp == nullptr)
+			return 0;
 
-        const auto nwritten = std::fwrite(data.c_str(), 1, data.length(), fp);
+		const auto nwritten = std::fwrite(data.c_str(), 1, data.length(), fp);
 
-        if (std::ferror(fp))
-            throw from_errno();
+		if (std::ferror(fp))
+			throw from_errno();
 
-        duk_push_uint(ctx, nwritten);
+		duk_push_uint(ctx, nwritten);
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -468,20 +468,20 @@
  */
 auto File_constructor(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        if (!duk_is_constructor_call(ctx))
-            return 0;
+	return wrap(ctx, [&] {
+		if (!duk_is_constructor_call(ctx))
+			return 0;
 
-        const auto path = duk::require<std::string>(ctx, 0);
-        const auto mode = duk::require<std::string>(ctx, 1);
+		const auto path = duk::require<std::string>(ctx, 0);
+		const auto mode = duk::require<std::string>(ctx, 1);
 
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, new std::shared_ptr<file>(new file(path, mode)));
-        duk_put_prop_string(ctx, -2, signature.data());
-        duk_pop(ctx);
+		duk_push_this(ctx);
+		duk_push_pointer(ctx, new std::shared_ptr<file>(new file(path, mode)));
+		duk_put_prop_string(ctx, -2, signature.data());
+		duk_pop(ctx);
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -496,12 +496,12 @@
  */
 auto File_destructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_get_prop_string(ctx, 0, signature.data());
-    delete static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, signature.data());
+	duk_get_prop_string(ctx, 0, signature.data());
+	delete static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
+	duk_del_prop_string(ctx, 0, signature.data());
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -523,9 +523,9 @@
  */
 auto File_basename(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, fs_util::base_name(duk_require_string(ctx, 0)));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, fs_util::base_name(duk_require_string(ctx, 0)));
+	});
 }
 
 // }}}
@@ -545,9 +545,9 @@
  */
 auto File_dirname(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, fs_util::dir_name(duk_require_string(ctx, 0)));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, fs_util::dir_name(duk_require_string(ctx, 0)));
+	});
 }
 
 // }}}
@@ -569,9 +569,9 @@
  */
 auto File_exists(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, boost::filesystem::exists(duk_require_string(ctx, 0)));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, boost::filesystem::exists(duk_require_string(ctx, 0)));
+	});
 }
 
 // }}}
@@ -591,11 +591,11 @@
  */
 auto File_remove(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        boost::filesystem::remove(duk::require<std::string>(ctx, 0));
+	return wrap(ctx, [&] {
+		boost::filesystem::remove(duk::require<std::string>(ctx, 0));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -619,14 +619,14 @@
  */
 auto File_stat(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        struct stat st;
+	return wrap(ctx, [&] {
+		struct stat st;
 
-        if (::stat(duk_require_string(ctx, 0), &st) < 0)
-            throw from_errno();
+		if (::stat(duk_require_string(ctx, 0), &st) < 0)
+			throw from_errno();
 
-        return duk::push(ctx, st);
-    });
+		return duk::push(ctx, st);
+	});
 }
 
 #endif // !IRCCD_HAVE_STAT
@@ -636,38 +636,38 @@
 // {{{ definitions
 
 const duk_function_list_entry methods[] = {
-    { "basename",   File_prototype_basename,    0 },
-    { "close",      File_prototype_close,       0 },
-    { "dirname",    File_prototype_dirname,     0 },
-    { "lines",      File_prototype_lines,       0 },
-    { "read",       File_prototype_read,        1 },
-    { "readline",   File_prototype_readline,    0 },
-    { "remove",     File_prototype_remove,      0 },
-    { "seek",       File_prototype_seek,        2 },
+	{ "basename",   File_prototype_basename,        0 },
+	{ "close",      File_prototype_close,           0 },
+	{ "dirname",    File_prototype_dirname,         0 },
+	{ "lines",      File_prototype_lines,           0 },
+	{ "read",       File_prototype_read,            1 },
+	{ "readline",   File_prototype_readline,        0 },
+	{ "remove",     File_prototype_remove,          0 },
+	{ "seek",       File_prototype_seek,            2 },
 #if defined(IRCCD_HAVE_STAT)
-    { "stat",       File_prototype_stat,        0 },
+	{ "stat",       File_prototype_stat,            0 },
 #endif
-    { "tell",       File_prototype_tell,        0 },
-    { "write",      File_prototype_write,       1 },
-    { nullptr,      nullptr,                    0 }
+	{ "tell",       File_prototype_tell,            0 },
+	{ "write",      File_prototype_write,           1 },
+	{ nullptr,      nullptr,                        0 }
 };
 
 const duk_function_list_entry functions[] = {
-    { "basename",   File_basename,              1 },
-    { "dirname",    File_dirname,               1 },
-    { "exists",     File_exists,                1 },
-    { "remove",     File_remove,                1 },
+	{ "basename",   File_basename,                  1 },
+	{ "dirname",    File_dirname,                   1 },
+	{ "exists",     File_exists,                    1 },
+	{ "remove",     File_remove,                    1 },
 #if defined(IRCCD_HAVE_STAT)
-    { "stat",       File_stat,                  1 },
+	{ "stat",       File_stat,                      1 },
 #endif
-    { nullptr,      nullptr,                    0 }
+	{ nullptr,      nullptr,                        0 }
 };
 
 const duk_number_list_entry constants[] = {
-    { "SeekCur",    SEEK_CUR },
-    { "SeekEnd",    SEEK_END },
-    { "SeekSet",    SEEK_SET },
-    { nullptr,      0        }
+	{ "SeekCur",    SEEK_CUR                          },
+	{ "SeekEnd",    SEEK_END                          },
+	{ "SeekSet",    SEEK_SET                          },
+	{ nullptr,      0                                 }
 };
 
 // }}}
@@ -678,26 +678,26 @@
 
 auto file_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.File";
+	return "Irccd.File";
 }
 
 void file_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_c_function(plugin->get_context(), File_constructor, 2);
-    duk_put_number_list(plugin->get_context(), -1, constants);
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, methods);
-    duk_push_c_function(plugin->get_context(), File_destructor, 1);
-    duk_set_finalizer(plugin->get_context(), -2);
-    duk_dup(plugin->get_context(), -1);
-    duk_put_global_string(plugin->get_context(), prototype.data());
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "File");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_c_function(plugin->get_context(), File_constructor, 2);
+	duk_put_number_list(plugin->get_context(), -1, constants);
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, methods);
+	duk_push_c_function(plugin->get_context(), File_destructor, 1);
+	duk_set_finalizer(plugin->get_context(), -2);
+	duk_dup(plugin->get_context(), -1);
+	duk_put_global_string(plugin->get_context(), prototype.data());
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "File");
+	duk_pop(plugin->get_context());
 }
 
 // }}}
@@ -708,28 +708,28 @@
 
 void file_traits::push(duk_context* ctx, std::shared_ptr<file> fp)
 {
-    assert(ctx);
-    assert(fp);
+	assert(ctx);
+	assert(fp);
 
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_push_object(ctx);
-    duk_push_pointer(ctx, new std::shared_ptr<file>(std::move(fp)));
-    duk_put_prop_string(ctx, -2, signature.data());
-    duk_get_global_string(ctx, prototype.data());
-    duk_set_prototype(ctx, -2);
+	duk_push_object(ctx);
+	duk_push_pointer(ctx, new std::shared_ptr<file>(std::move(fp)));
+	duk_put_prop_string(ctx, -2, signature.data());
+	duk_get_global_string(ctx, prototype.data());
+	duk_set_prototype(ctx, -2);
 }
 
 auto file_traits::require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<file>
 {
-    if (!duk_is_object(ctx, index) || !duk_has_prop_string(ctx, index, signature.data()))
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a File object");
+	if (!duk_is_object(ctx, index) || !duk_has_prop_string(ctx, index, signature.data()))
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a File object");
 
-    duk_get_prop_string(ctx, index, signature.data());
-    const auto fp = static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
+	duk_get_prop_string(ctx, index, signature.data());
+	const auto fp = static_cast<std::shared_ptr<file>*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
 
-    return *fp;
+	return *fp;
 }
 
 // }}}
@@ -740,61 +740,61 @@
 
 void duk::type_traits<struct stat>::push(duk_context* ctx, const struct stat& st)
 {
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_push_object(ctx);
+	duk_push_object(ctx);
 
 #if defined(IRCCD_HAVE_STAT_ST_ATIME)
-    duk_push_int(ctx, st.st_atime);
-    duk_put_prop_string(ctx, -2, "atime");
+	duk_push_int(ctx, st.st_atime);
+	duk_put_prop_string(ctx, -2, "atime");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_BLKSIZE)
-    duk_push_int(ctx, st.st_blksize);
-    duk_put_prop_string(ctx, -2, "blksize");
+	duk_push_int(ctx, st.st_blksize);
+	duk_put_prop_string(ctx, -2, "blksize");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_BLOCKS)
-    duk_push_int(ctx, st.st_blocks);
-    duk_put_prop_string(ctx, -2, "blocks");
+	duk_push_int(ctx, st.st_blocks);
+	duk_put_prop_string(ctx, -2, "blocks");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_CTIME)
-    duk_push_int(ctx, st.st_ctime);
-    duk_put_prop_string(ctx, -2, "ctime");
+	duk_push_int(ctx, st.st_ctime);
+	duk_put_prop_string(ctx, -2, "ctime");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_DEV)
-    duk_push_int(ctx, st.st_dev);
-    duk_put_prop_string(ctx, -2, "dev");
+	duk_push_int(ctx, st.st_dev);
+	duk_put_prop_string(ctx, -2, "dev");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_GID)
-    duk_push_int(ctx, st.st_gid);
-    duk_put_prop_string(ctx, -2, "gid");
+	duk_push_int(ctx, st.st_gid);
+	duk_put_prop_string(ctx, -2, "gid");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_INO)
-    duk_push_int(ctx, st.st_ino);
-    duk_put_prop_string(ctx, -2, "ino");
+	duk_push_int(ctx, st.st_ino);
+	duk_put_prop_string(ctx, -2, "ino");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_MODE)
-    duk_push_int(ctx, st.st_mode);
-    duk_put_prop_string(ctx, -2, "mode");
+	duk_push_int(ctx, st.st_mode);
+	duk_put_prop_string(ctx, -2, "mode");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_MTIME)
-    duk_push_int(ctx, st.st_mtime);
-    duk_put_prop_string(ctx, -2, "mtime");
+	duk_push_int(ctx, st.st_mtime);
+	duk_put_prop_string(ctx, -2, "mtime");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_NLINK)
-    duk_push_int(ctx, st.st_nlink);
-    duk_put_prop_string(ctx, -2, "nlink");
+	duk_push_int(ctx, st.st_nlink);
+	duk_put_prop_string(ctx, -2, "nlink");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_RDEV)
-    duk_push_int(ctx, st.st_rdev);
-    duk_put_prop_string(ctx, -2, "rdev");
+	duk_push_int(ctx, st.st_rdev);
+	duk_put_prop_string(ctx, -2, "rdev");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_SIZE)
-    duk_push_int(ctx, st.st_size);
-    duk_put_prop_string(ctx, -2, "size");
+	duk_push_int(ctx, st.st_size);
+	duk_put_prop_string(ctx, -2, "size");
 #endif
 #if defined(IRCCD_HAVE_STAT_ST_UID)
-    duk_push_int(ctx, st.st_uid);
-    duk_put_prop_string(ctx, -2, "uid");
+	duk_push_int(ctx, st.st_uid);
+	duk_put_prop_string(ctx, -2, "uid");
 #endif
 }
 
--- a/libirccd-js/irccd/js/file_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/file_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -55,88 +55,88 @@
  */
 class file {
 private:
-    file(const file&) = delete;
-    file& operator=(const file&) = delete;
+	file(const file&) = delete;
+	file& operator=(const file&) = delete;
 
-    file(file&&) = delete;
-    file& operator=(file&&) = delete;
+	file(file&&) = delete;
+	file& operator=(file&&) = delete;
 
 private:
-    std::string path_;
-    std::FILE* stream_;
-    std::function<void (std::FILE*)> destructor_;
+	std::string path_;
+	std::FILE* stream_;
+	std::function<void (std::FILE*)> destructor_;
 
 public:
-    /**
-     * Construct a file specified by path
-     *
-     * \param path the path
-     * \param mode the mode string (for std::fopen)
-     * \throw std::runtime_error on failures
-     */
-    inline file(std::string path, const std::string& mode)
-        : path_(std::move(path))
-        , destructor_([] (std::FILE* fp) { std::fclose(fp); })
-    {
-        if ((stream_ = std::fopen(path_.c_str(), mode.c_str())) == nullptr)
-            throw std::runtime_error(std::strerror(errno));
-    }
+	/**
+	 * Construct a file specified by path
+	 *
+	 * \param path the path
+	 * \param mode the mode string (for std::fopen)
+	 * \throw std::runtime_error on failures
+	 */
+	inline file(std::string path, const std::string& mode)
+		: path_(std::move(path))
+		, destructor_([] (std::FILE* fp) { std::fclose(fp); })
+	{
+		if ((stream_ = std::fopen(path_.c_str(), mode.c_str())) == nullptr)
+			throw std::runtime_error(std::strerror(errno));
+	}
 
-    /**
-     * Construct a file from a already created FILE pointer (e.g. popen).
-     *
-     * The class takes ownership of fp and will close it.
-     *
-     * \pre destructor must not be null
-     * \param fp the file pointer
-     * \param destructor the function to close fp (e.g. std::fclose)
-     */
-    inline file(std::FILE* fp, std::function<void (std::FILE*)> destructor) noexcept
-        : stream_(fp)
-        , destructor_(std::move(destructor))
-    {
-        assert(destructor_ != nullptr);
-    }
+	/**
+	 * Construct a file from a already created FILE pointer (e.g. popen).
+	 *
+	 * The class takes ownership of fp and will close it.
+	 *
+	 * \pre destructor must not be null
+	 * \param fp the file pointer
+	 * \param destructor the function to close fp (e.g. std::fclose)
+	 */
+	inline file(std::FILE* fp, std::function<void (std::FILE*)> destructor) noexcept
+		: stream_(fp)
+		, destructor_(std::move(destructor))
+	{
+		assert(destructor_ != nullptr);
+	}
 
-    /**
-     * Closes the file.
-     */
-    virtual ~file() noexcept
-    {
-        close();
-    }
+	/**
+	 * Closes the file.
+	 */
+	virtual ~file() noexcept
+	{
+		close();
+	}
 
-    /**
-     * Get the path.
-     *
-     * \return the path
-     * \warning empty when constructed from the FILE constructor
-     */
-    inline const std::string& get_path() const noexcept
-    {
-        return path_;
-    }
+	/**
+	 * Get the path.
+	 *
+	 * \return the path
+	 * \warning empty when constructed from the FILE constructor
+	 */
+	inline const std::string& get_path() const noexcept
+	{
+		return path_;
+	}
 
-    /**
-     * Get the handle.
-     *
-     * \return the handle or nullptr if the stream was closed
-     */
-    inline std::FILE* get_handle() noexcept
-    {
-        return stream_;
-    }
+	/**
+	 * Get the handle.
+	 *
+	 * \return the handle or nullptr if the stream was closed
+	 */
+	inline std::FILE* get_handle() noexcept
+	{
+		return stream_;
+	}
 
-    /**
-     * Force close, can be safely called multiple times.
-     */
-    inline void close() noexcept
-    {
-        if (stream_) {
-            destructor_(stream_);
-            stream_ = nullptr;
-        }
-    }
+	/**
+	 * Force close, can be safely called multiple times.
+	 */
+	inline void close() noexcept
+	{
+		if (stream_) {
+			destructor_(stream_);
+			stream_ = nullptr;
+		}
+	}
 };
 
 /**
@@ -145,15 +145,15 @@
  */
 class file_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 namespace duk {
@@ -165,23 +165,23 @@
  */
 template <>
 struct type_traits<std::shared_ptr<file>> {
-    /**
-     * Push a file.
-     *
-     * \pre fp != nullptr
-     * \param ctx the the context
-     * \param fp the file
-     */
-    static void push(duk_context* ctx, std::shared_ptr<file> fp);
+	/**
+	 * Push a file.
+	 *
+	 * \pre fp != nullptr
+	 * \param ctx the the context
+	 * \param fp the file
+	 */
+	static void push(duk_context* ctx, std::shared_ptr<file> fp);
 
-    /**
-     * Require a file. Raises a JavaScript error if not a File.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the file pointer
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<file>;
+	/**
+	 * Require a file. Raises a JavaScript error if not a File.
+	 *
+	 * \param ctx the context
+	 * \param index the index
+	 * \return the file pointer
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<file>;
 };
 
 #if defined(IRCCD_HAVE_STAT)
@@ -193,13 +193,13 @@
  */
 template <>
 struct type_traits<struct stat> {
-    /**
-     * Push the stat information to the stack as Javascript object.
-     *
-     * \param ctx the context
-     * \param st the stat structure
-     */
-    static void push(duk_context* ctx, const struct stat& st);
+	/**
+	 * Push the stat information to the stack as Javascript object.
+	 *
+	 * \param ctx the context
+	 * \param st the stat structure
+	 */
+	static void push(duk_context* ctx, const struct stat& st);
 };
 
 #endif // !IRCCD_HAVE_STAT
--- a/libirccd-js/irccd/js/irccd_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/irccd_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,16 +34,16 @@
 template <typename Error>
 void do_raise(duk_context* ctx, const Error& ex)
 {
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_get_global_string(ctx, "Irccd");
-    duk_get_prop_string(ctx, -1, "SystemError");
-    duk_remove(ctx, -2);
-    duk::push(ctx, ex.code().value());
-    duk::push(ctx, ex.code().message());
-    duk_new(ctx, 2);
+	duk_get_global_string(ctx, "Irccd");
+	duk_get_prop_string(ctx, -1, "SystemError");
+	duk_remove(ctx, -2);
+	duk::push(ctx, ex.code().value());
+	duk::push(ctx, ex.code().message());
+	duk_new(ctx, 2);
 
-    (void)duk_throw(ctx);
+	(void)duk_throw(ctx);
 }
 
 // }}}
@@ -52,16 +52,16 @@
 
 auto constructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_this(ctx);
-    duk_push_int(ctx, duk_require_int(ctx, 0));
-    duk_put_prop_string(ctx, -2, "errno");
-    duk_push_string(ctx, duk_require_string(ctx, 1));
-    duk_put_prop_string(ctx, -2, "message");
-    duk_push_string(ctx, "SystemError");
-    duk_put_prop_string(ctx, -2, "name");
-    duk_pop(ctx);
+	duk_push_this(ctx);
+	duk_push_int(ctx, duk_require_int(ctx, 0));
+	duk_put_prop_string(ctx, -2, "errno");
+	duk_push_string(ctx, duk_require_string(ctx, 1));
+	duk_put_prop_string(ctx, -2, "message");
+	duk_push_string(ctx, "SystemError");
+	duk_put_prop_string(ctx, -2, "name");
+	duk_pop(ctx);
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -69,104 +69,104 @@
 // {{{ definitions
 
 const std::unordered_map<std::string, int> errors{
-    { "E2BIG",              E2BIG           },
-    { "EACCES",             EACCES          },
-    { "EADDRINUSE",         EADDRINUSE      },
-    { "EADDRNOTAVAIL",      EADDRNOTAVAIL   },
-    { "EAFNOSUPPORT",       EAFNOSUPPORT    },
-    { "EAGAIN",             EAGAIN          },
-    { "EALREADY",           EALREADY        },
-    { "EBADF",              EBADF           },
+	{ "E2BIG",              E2BIG           },
+	{ "EACCES",             EACCES          },
+	{ "EADDRINUSE",         EADDRINUSE      },
+	{ "EADDRNOTAVAIL",      EADDRNOTAVAIL   },
+	{ "EAFNOSUPPORT",       EAFNOSUPPORT    },
+	{ "EAGAIN",             EAGAIN          },
+	{ "EALREADY",           EALREADY        },
+	{ "EBADF",              EBADF           },
 #if defined(EBADMSG)
-    { "EBADMSG",            EBADMSG         },
+	{ "EBADMSG",            EBADMSG         },
 #endif
-    { "EBUSY",              EBUSY           },
-    { "ECANCELED",          ECANCELED       },
-    { "ECHILD",             ECHILD          },
-    { "ECONNABORTED",       ECONNABORTED    },
-    { "ECONNREFUSED",       ECONNREFUSED    },
-    { "ECONNRESET",         ECONNRESET      },
-    { "EDEADLK",            EDEADLK         },
-    { "EDESTADDRREQ",       EDESTADDRREQ    },
-    { "EDOM",               EDOM            },
-    { "EEXIST",             EEXIST          },
-    { "EFAULT",             EFAULT          },
-    { "EFBIG",              EFBIG           },
-    { "EHOSTUNREACH",       EHOSTUNREACH    },
+	{ "EBUSY",              EBUSY           },
+	{ "ECANCELED",          ECANCELED       },
+	{ "ECHILD",             ECHILD          },
+	{ "ECONNABORTED",       ECONNABORTED    },
+	{ "ECONNREFUSED",       ECONNREFUSED    },
+	{ "ECONNRESET",         ECONNRESET      },
+	{ "EDEADLK",            EDEADLK         },
+	{ "EDESTADDRREQ",       EDESTADDRREQ    },
+	{ "EDOM",               EDOM            },
+	{ "EEXIST",             EEXIST          },
+	{ "EFAULT",             EFAULT          },
+	{ "EFBIG",              EFBIG           },
+	{ "EHOSTUNREACH",       EHOSTUNREACH    },
 #if defined(EIDRM)
-    { "EIDRM",              EIDRM           },
+	{ "EIDRM",              EIDRM           },
 #endif
-    { "EILSEQ",             EILSEQ          },
-    { "EINPROGRESS",        EINPROGRESS     },
-    { "EINTR",              EINTR           },
-    { "EINVAL",             EINVAL          },
-    { "EIO",                EIO             },
-    { "EISCONN",            EISCONN         },
-    { "EISDIR",             EISDIR          },
-    { "ELOOP",              ELOOP           },
-    { "EMFILE",             EMFILE          },
-    { "EMLINK",             EMLINK          },
-    { "EMSGSIZE",           EMSGSIZE        },
-    { "ENAMETOOLONG",       ENAMETOOLONG    },
-    { "ENETDOWN",           ENETDOWN        },
-    { "ENETRESET",          ENETRESET       },
-    { "ENETUNREACH",        ENETUNREACH     },
-    { "ENFILE",             ENFILE          },
-    { "ENOBUFS",            ENOBUFS         },
+	{ "EILSEQ",             EILSEQ          },
+	{ "EINPROGRESS",        EINPROGRESS     },
+	{ "EINTR",              EINTR           },
+	{ "EINVAL",             EINVAL          },
+	{ "EIO",                EIO             },
+	{ "EISCONN",            EISCONN         },
+	{ "EISDIR",             EISDIR          },
+	{ "ELOOP",              ELOOP           },
+	{ "EMFILE",             EMFILE          },
+	{ "EMLINK",             EMLINK          },
+	{ "EMSGSIZE",           EMSGSIZE        },
+	{ "ENAMETOOLONG",       ENAMETOOLONG    },
+	{ "ENETDOWN",           ENETDOWN        },
+	{ "ENETRESET",          ENETRESET       },
+	{ "ENETUNREACH",        ENETUNREACH     },
+	{ "ENFILE",             ENFILE          },
+	{ "ENOBUFS",            ENOBUFS         },
 #if defined(ENODATA)
-    { "ENODATA",            ENODATA         },
+	{ "ENODATA",            ENODATA         },
 #endif
-    { "ENODEV",             ENODEV          },
-    { "ENOENT",             ENOENT          },
-    { "ENOEXEC",            ENOEXEC         },
-    { "ENOLCK",             ENOLCK          },
+	{ "ENODEV",             ENODEV          },
+	{ "ENOENT",             ENOENT          },
+	{ "ENOEXEC",            ENOEXEC         },
+	{ "ENOLCK",             ENOLCK          },
 #if defined(ENOLINK)
-    { "ENOLINK",            ENOLINK         },
+	{ "ENOLINK",            ENOLINK         },
 #endif
-    { "ENOMEM",             ENOMEM          },
+	{ "ENOMEM",             ENOMEM          },
 #if defined(ENOMSG)
-    { "ENOMSG",             ENOMSG          },
+	{ "ENOMSG",             ENOMSG          },
 #endif
-    { "ENOPROTOOPT",        ENOPROTOOPT     },
-    { "ENOSPC",             ENOSPC          },
+	{ "ENOPROTOOPT",        ENOPROTOOPT     },
+	{ "ENOSPC",             ENOSPC          },
 #if defined(ENOSR)
-    { "ENOSR",              ENOSR           },
+	{ "ENOSR",              ENOSR           },
 #endif
 #if defined(ENOSTR)
-    { "ENOSTR",             ENOSTR          },
+	{ "ENOSTR",             ENOSTR          },
 #endif
-    { "ENOSYS",             ENOSYS          },
-    { "ENOTCONN",           ENOTCONN        },
-    { "ENOTDIR",            ENOTDIR         },
-    { "ENOTEMPTY",          ENOTEMPTY       },
+	{ "ENOSYS",             ENOSYS          },
+	{ "ENOTCONN",           ENOTCONN        },
+	{ "ENOTDIR",            ENOTDIR         },
+	{ "ENOTEMPTY",          ENOTEMPTY       },
 #if defined(ENOTRECOVERABLE)
-    { "ENOTRECOVERABLE",    ENOTRECOVERABLE },
+	{ "ENOTRECOVERABLE",    ENOTRECOVERABLE },
 #endif
-    { "ENOTSOCK",           ENOTSOCK        },
-    { "ENOTSUP",            ENOTSUP         },
-    { "ENOTTY",             ENOTTY          },
-    { "ENXIO",              ENXIO           },
-    { "EOPNOTSUPP",         EOPNOTSUPP      },
-    { "EOVERFLOW",          EOVERFLOW       },
-    { "EOWNERDEAD",         EOWNERDEAD      },
-    { "EPERM",              EPERM           },
-    { "EPIPE",              EPIPE           },
-    { "EPROTO",             EPROTO          },
-    { "EPROTONOSUPPORT",    EPROTONOSUPPORT },
-    { "EPROTOTYPE",         EPROTOTYPE      },
-    { "ERANGE",             ERANGE          },
-    { "EROFS",              EROFS           },
-    { "ESPIPE",             ESPIPE          },
-    { "ESRCH",              ESRCH           },
+	{ "ENOTSOCK",           ENOTSOCK        },
+	{ "ENOTSUP",            ENOTSUP         },
+	{ "ENOTTY",             ENOTTY          },
+	{ "ENXIO",              ENXIO           },
+	{ "EOPNOTSUPP",         EOPNOTSUPP      },
+	{ "EOVERFLOW",          EOVERFLOW       },
+	{ "EOWNERDEAD",         EOWNERDEAD      },
+	{ "EPERM",              EPERM           },
+	{ "EPIPE",              EPIPE           },
+	{ "EPROTO",             EPROTO          },
+	{ "EPROTONOSUPPORT",    EPROTONOSUPPORT },
+	{ "EPROTOTYPE",         EPROTOTYPE      },
+	{ "ERANGE",             ERANGE          },
+	{ "EROFS",              EROFS           },
+	{ "ESPIPE",             ESPIPE          },
+	{ "ESRCH",              ESRCH           },
 #if defined(ETIME)
-    { "ETIME",              ETIME           },
+	{ "ETIME",              ETIME           },
 #endif
-    { "ETIMEDOUT",          ETIMEDOUT       },
+	{ "ETIMEDOUT",          ETIMEDOUT       },
 #if defined(ETXTBSY)
-    { "ETXTBSY",            ETXTBSY         },
+	{ "ETXTBSY",            ETXTBSY         },
 #endif
-    { "EWOULDBLOCK",        EWOULDBLOCK     },
-    { "EXDEV",              EXDEV           }
+	{ "EWOULDBLOCK",        EWOULDBLOCK     },
+	{ "EXDEV",              EXDEV           }
 };
 
 // }}}
@@ -175,70 +175,70 @@
 
 void duk::type_traits<std::system_error>::raise(duk_context* ctx, const std::system_error& ex)
 {
-    do_raise(ctx, ex);
+	do_raise(ctx, ex);
 }
 
 void duk::type_traits<boost::system::system_error>::raise(duk_context* ctx, const boost::system::system_error& ex)
 {
-    do_raise(ctx, ex);
+	do_raise(ctx, ex);
 }
 
 auto irccd_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd";
+	return "Irccd";
 }
 
 void irccd_js_api::load(irccd& irccd, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    // irccd.
-    duk_push_object(plugin->get_context());
+	// irccd.
+	duk_push_object(plugin->get_context());
 
-    // Version.
-    duk_push_object(plugin->get_context());
-    duk::push(plugin->get_context(), IRCCD_VERSION_MAJOR);
-    duk_put_prop_string(plugin->get_context(), -2, "major");
-    duk::push(plugin->get_context(), IRCCD_VERSION_MINOR);
-    duk_put_prop_string(plugin->get_context(), -2, "minor");
-    duk::push(plugin->get_context(), IRCCD_VERSION_PATCH);
-    duk_put_prop_string(plugin->get_context(), -2, "patch");
-    duk_put_prop_string(plugin->get_context(), -2, "version");
+	// Version.
+	duk_push_object(plugin->get_context());
+	duk::push(plugin->get_context(), IRCCD_VERSION_MAJOR);
+	duk_put_prop_string(plugin->get_context(), -2, "major");
+	duk::push(plugin->get_context(), IRCCD_VERSION_MINOR);
+	duk_put_prop_string(plugin->get_context(), -2, "minor");
+	duk::push(plugin->get_context(), IRCCD_VERSION_PATCH);
+	duk_put_prop_string(plugin->get_context(), -2, "patch");
+	duk_put_prop_string(plugin->get_context(), -2, "version");
 
-    // Create the system_error that inherits from Error.
-    duk_push_c_function(plugin->get_context(), constructor, 2);
+	// Create the system_error that inherits from Error.
+	duk_push_c_function(plugin->get_context(), constructor, 2);
 
-    // Put errno codes into the irccd.system_error object.
-    for (const auto& [k, v] : errors) {
-        duk_push_int(plugin->get_context(), v);
-        duk_put_prop_string(plugin->get_context(), -2, k.c_str());
-    }
+	// Put errno codes into the irccd.system_error object.
+	for (const auto& [k, v] : errors) {
+		duk_push_int(plugin->get_context(), v);
+		duk_put_prop_string(plugin->get_context(), -2, k.c_str());
+	}
 
-    duk_push_object(plugin->get_context());
-    duk_get_global_string(plugin->get_context(), "Error");
-    duk_get_prop_string(plugin->get_context(), -1, "prototype");
-    duk_remove(plugin->get_context(), -2);
-    duk_set_prototype(plugin->get_context(), -2);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "SystemError");
+	duk_push_object(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Error");
+	duk_get_prop_string(plugin->get_context(), -1, "prototype");
+	duk_remove(plugin->get_context(), -2);
+	duk_set_prototype(plugin->get_context(), -2);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "SystemError");
 
-    // Set irccd as global.
-    duk_put_global_string(plugin->get_context(), "Irccd");
+	// Set irccd as global.
+	duk_put_global_string(plugin->get_context(), "Irccd");
 
-    // Store global instance.
-    duk_push_pointer(plugin->get_context(), &irccd);
-    duk_put_global_string(plugin->get_context(), "\xff""\xff""irccd-ref");
+	// Store global instance.
+	duk_push_pointer(plugin->get_context(), &irccd);
+	duk_put_global_string(plugin->get_context(), "\xff""\xff""irccd-ref");
 }
 
 auto duk::type_traits<irccd>::self(duk_context *ctx) -> irccd&
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_get_global_string(ctx, "\xff""\xff""irccd-ref");
-    const auto ptr = static_cast<irccd*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
+	duk_get_global_string(ctx, "\xff""\xff""irccd-ref");
+	const auto ptr = static_cast<irccd*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
 
-    return *ptr;
+	return *ptr;
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/irccd_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/irccd_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -41,15 +41,15 @@
  */
 class irccd_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 namespace duk {
@@ -59,27 +59,27 @@
  */
 template <>
 struct type_traits<irccd> {
-    /**
-     * Get irccd instance stored in this context.
-     *
-     * \param ctx the context
-     * \return the irccd reference
-     */
-    static auto self(duk_context* ctx) -> irccd&;
+	/**
+	 * Get irccd instance stored in this context.
+	 *
+	 * \param ctx the context
+	 * \return the irccd reference
+	 */
+	static auto self(duk_context* ctx) -> irccd&;
 };
 
 /**
- * \brief Specialize dukx_type_traits for std::system_error.
+ * \brief Specialize dukx_type_traits for boost::system::system_error.
  */
 template <>
 struct type_traits<std::system_error> {
-    /**
-     * Raise an Irccd.SystemError.
-     *
-     * \param ctx the context
-     * param ex the exception
-     */
-    static void raise(duk_context* ctx, const std::system_error& ex);
+	/**
+	 * Raise an Irccd.SystemError.
+	 *
+	 * \param ctx the context
+	 * param ex the exception
+	 */
+	static void raise(duk_context* ctx, const std::system_error& ex);
 };
 
 /**
@@ -87,13 +87,13 @@
  */
 template <>
 struct type_traits<boost::system::system_error> {
-    /**
-     * Raise an Irccd.SystemError.
-     *
-     * \param ctx the context
-     * param ex the exception
-     */
-    static void raise(duk_context* ctx, const boost::system::system_error& ex);
+	/**
+	 * Raise an Irccd.SystemError.
+	 *
+	 * \param ctx the context
+	 * param ex the exception
+	 */
+	static void raise(duk_context* ctx, const boost::system::system_error& ex);
 };
 
 } // !duk
--- a/libirccd-js/irccd/js/js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,26 +35,26 @@
 template <typename T>
 auto bind() noexcept -> js_api::factory
 {
-    return [] () noexcept {
-        return std::make_unique<T>();
-    };
+	return [] () noexcept {
+		return std::make_unique<T>();
+	};
 }
 
 } // !namespace
 
 const std::vector<js_api::factory> js_api::registry{
-    // Irccd API must be loaded first.
-    bind<irccd_js_api>(),
-    bind<directory_js_api>(),
-    bind<elapsed_timer_js_api>(),
-    bind<file_js_api>(),
-    bind<logger_js_api>(),
-    bind<plugin_js_api>(),
-    bind<server_js_api>(),
-    bind<system_js_api>(),
-    bind<timer_js_api>(),
-    bind<unicode_js_api>(),
-    bind<util_js_api>()
+	// Irccd API must be loaded first.
+	bind<irccd_js_api>(),
+	bind<directory_js_api>(),
+	bind<elapsed_timer_js_api>(),
+	bind<file_js_api>(),
+	bind<logger_js_api>(),
+	bind<plugin_js_api>(),
+	bind<server_js_api>(),
+	bind<system_js_api>(),
+	bind<timer_js_api>(),
+	bind<unicode_js_api>(),
+	bind<util_js_api>()
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -49,40 +49,40 @@
  */
 class js_api {
 public:
-    /**
-     * \brief Command constructor factory.
-     */
-    using factory = std::function<auto () -> std::unique_ptr<js_api>>;
+	/**
+	 * \brief Command constructor factory.
+	 */
+	using factory = std::function<auto () -> std::unique_ptr<js_api>>;
 
-    /**
-     * \brief Registry of all commands.
-     */
-    static const std::vector<factory> registry;
+	/**
+	 * \brief Registry of all commands.
+	 */
+	static const std::vector<factory> registry;
 
-    /**
-     * Default constructor.
-     */
-    js_api() noexcept = default;
+	/**
+	 * Default constructor.
+	 */
+	js_api() noexcept = default;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~js_api() noexcept = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~js_api() noexcept = default;
 
-    /**
-     * Get the module name.
-     *
-     * \return the name
-     */
-    virtual auto get_name() const noexcept -> std::string_view = 0;
+	/**
+	 * Get the module name.
+	 *
+	 * \return the name
+	 */
+	virtual auto get_name() const noexcept -> std::string_view = 0;
 
-    /**
-     * Load the module into the Javascript plugin.
-     *
-     * \param irccd the irccd instance
-     * \param plugin the plugin
-     */
-    virtual void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) = 0;
+	/**
+	 * Load the module into the Javascript plugin.
+	 *
+	 * \param irccd the irccd instance
+	 * \param plugin the plugin
+	 */
+	virtual void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) = 0;
 };
 
 } // !js
--- a/libirccd-js/irccd/js/js_plugin.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/js_plugin.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,54 +34,54 @@
 
 auto get_metadata(duk::context& ctx, std::string_view name) -> std::string_view
 {
-    std::string_view ret("unknown");
+	std::string_view ret("unknown");
 
-    duk::stack_guard guard(ctx);
-    duk_get_global_string(ctx, "info");
+	duk::stack_guard guard(ctx);
+	duk_get_global_string(ctx, "info");
 
-    if (duk_get_type(ctx, -1) == DUK_TYPE_OBJECT) {
-        duk_get_prop_string(ctx, -1, name.data());
+	if (duk_get_type(ctx, -1) == DUK_TYPE_OBJECT) {
+		duk_get_prop_string(ctx, -1, name.data());
 
-        if (duk_get_type(ctx, -1) == DUK_TYPE_STRING)
-            ret = duk_get_string(ctx, -1);
+		if (duk_get_type(ctx, -1) == DUK_TYPE_STRING)
+			ret = duk_get_string(ctx, -1);
 
-        duk_pop(ctx);
-    }
+		duk_pop(ctx);
+	}
 
-    duk_pop(ctx);
+	duk_pop(ctx);
 
-    return ret;
+	return ret;
 }
 
 auto get_table(duk::context& ctx, std::string_view name) -> plugin::map
 {
-    plugin::map result;
+	plugin::map result;
 
-    duk::stack_guard sa(ctx);
-    duk_get_global_string(ctx, name.data());
-    duk_enum(ctx, -1, 0);
+	duk::stack_guard sa(ctx);
+	duk_get_global_string(ctx, name.data());
+	duk_enum(ctx, -1, 0);
 
-    while (duk_next(ctx, -1, true)) {
-        result.emplace(duk_to_string(ctx, -2), duk_to_string(ctx, -1));
-        duk_pop_n(ctx, 2);
-    }
+	while (duk_next(ctx, -1, true)) {
+		result.emplace(duk_to_string(ctx, -2), duk_to_string(ctx, -1));
+		duk_pop_n(ctx, 2);
+	}
 
-    duk_pop_n(ctx, 2);
+	duk_pop_n(ctx, 2);
 
-    return result;
+	return result;
 }
 
 void set_table(duk::context& ctx, std::string_view name, const plugin::map& vars)
 {
-    duk::stack_guard sa(ctx);
-    duk_get_global_string(ctx, name.data());
+	duk::stack_guard sa(ctx);
+	duk_get_global_string(ctx, name.data());
 
-    for (const auto& pair : vars) {
-        duk::push(ctx, pair.second);
-        duk_put_prop_string(ctx, -2, pair.first.c_str());
-    }
+	for (const auto& pair : vars) {
+		duk::push(ctx, pair.second);
+		duk_put_prop_string(ctx, -2, pair.first.c_str());
+	}
 
-    duk_pop(ctx);
+	duk_pop(ctx);
 }
 
 } // !namespace
@@ -93,229 +93,229 @@
 template <typename Value, typename... Args>
 void js_plugin::push(Value&& value, Args&&... args)
 {
-    duk::push(context_, std::forward<Value>(value));
-    push(std::forward<Args>(args)...);
+	duk::push(context_, std::forward<Value>(value));
+	push(std::forward<Args>(args)...);
 }
 
 template <typename... Args>
 void js_plugin::call(const std::string& func, Args&&... args)
 {
-    duk::stack_guard sa(context_);
+	duk::stack_guard sa(context_);
 
-    duk_get_global_string(context_, func.c_str());
+	duk_get_global_string(context_, func.c_str());
 
-    if (duk_get_type(context_, -1) == DUK_TYPE_UNDEFINED) {
-        duk_pop(context_);
-        return;
-    }
+	if (duk_get_type(context_, -1) == DUK_TYPE_UNDEFINED) {
+		duk_pop(context_);
+		return;
+	}
 
-    push(std::forward<Args>(args)...);
+	push(std::forward<Args>(args)...);
 
-    if (duk_pcall(context_, sizeof... (Args)) != 0)
-        throw plugin_error(plugin_error::exec_error, get_name(), duk::get_stack(context_, -1).get_stack());
+	if (duk_pcall(context_, sizeof... (Args)) != 0)
+		throw plugin_error(plugin_error::exec_error, get_name(), duk::get_stack(context_, -1).get_stack());
 
-    duk_pop(context_);
+	duk_pop(context_);
 }
 
 js_plugin::js_plugin(std::string id, std::string path)
-    : plugin(std::move(id))
-    , path_(path)
+	: plugin(std::move(id))
+	, path_(path)
 {
-    duk::stack_guard sa(context_);
+	duk::stack_guard sa(context_);
 
-    /*
-     * Create two special tables for configuration and formats, they are
-     * referenced later as
-     *
-     *   - Irccd.Plugin.config
-     *   - Irccd.Plugin.format
-     *   - Irccd.Plugin.paths
-     *
-     * In js_plugin_module.cpp.
-     */
-    duk_push_object(context_);
-    duk_put_global_string(context_, config_property.data());
-    duk_push_object(context_);
-    duk_put_global_string(context_, format_property.data());
-    duk_push_object(context_);
-    duk_put_global_string(context_, paths_property.data());
+	/*
+	 * Create two special tables for configuration and formats, they are
+	 * referenced later as
+	 *
+	 *   - Irccd.Plugin.config
+	 *   - Irccd.Plugin.format
+	 *   - Irccd.Plugin.paths
+	 *
+	 * In js_plugin_module.cpp.
+	 */
+	duk_push_object(context_);
+	duk_put_global_string(context_, config_property.data());
+	duk_push_object(context_);
+	duk_put_global_string(context_, format_property.data());
+	duk_push_object(context_);
+	duk_put_global_string(context_, paths_property.data());
 
-    duk_push_pointer(context_, this);
-    duk_put_global_string(context_, "\xff""\xff""plugin");
-    duk::push(context_, path);
-    duk_put_global_string(context_, "\xff""\xff""path");
+	duk_push_pointer(context_, this);
+	duk_put_global_string(context_, "\xff""\xff""plugin");
+	duk::push(context_, path);
+	duk_put_global_string(context_, "\xff""\xff""path");
 }
 
 auto js_plugin::get_context() noexcept -> duk::context&
 {
-    return context_;
+	return context_;
 }
 
 auto js_plugin::get_name() const noexcept -> std::string_view
 {
-    return get_metadata(context_, "name");
+	return get_metadata(context_, "name");
 }
 
 auto js_plugin::get_author() const noexcept -> std::string_view
 {
-    return get_metadata(context_, "author");
+	return get_metadata(context_, "author");
 }
 
 auto js_plugin::get_license() const noexcept -> std::string_view
 {
-    return get_metadata(context_, "license");
+	return get_metadata(context_, "license");
 }
 
 auto js_plugin::get_summary() const noexcept -> std::string_view
 {
-    return get_metadata(context_, "summary");
+	return get_metadata(context_, "summary");
 }
 
 auto js_plugin::get_version() const noexcept -> std::string_view
 {
-    return get_metadata(context_, "version");
+	return get_metadata(context_, "version");
 }
 
 auto js_plugin::get_options() const -> map
 {
-    return get_table(context_, config_property);
+	return get_table(context_, config_property);
 }
 
 void js_plugin::set_options(const map& map)
 {
-    set_table(context_, config_property, map);
+	set_table(context_, config_property, map);
 }
 
 auto js_plugin::get_formats() const -> map
 {
-    return get_table(context_, format_property);
+	return get_table(context_, format_property);
 }
 
 void js_plugin::set_formats(const map& map)
 {
-    set_table(context_, format_property, map);
+	set_table(context_, format_property, map);
 }
 
 auto js_plugin::get_paths() const -> map
 {
-    return get_table(context_, paths_property);
+	return get_table(context_, paths_property);
 }
 
 void js_plugin::set_paths(const map& map)
 {
-    set_table(context_, paths_property, map);
+	set_table(context_, paths_property, map);
 }
 
 void js_plugin::open()
 {
-    std::ifstream input(path_);
+	std::ifstream input(path_);
 
-    if (!input)
-        throw plugin_error(plugin_error::exec_error, get_name(), std::strerror(errno));
+	if (!input)
+		throw plugin_error(plugin_error::exec_error, get_name(), std::strerror(errno));
 
-    std::string data(
-        std::istreambuf_iterator<char>(input.rdbuf()),
-        std::istreambuf_iterator<char>()
-    );
+	std::string data(
+		std::istreambuf_iterator<char>(input.rdbuf()),
+		std::istreambuf_iterator<char>()
+	);
 
-    if (duk_peval_string(context_, data.c_str()))
-        throw plugin_error(plugin_error::exec_error, get_name(), duk::get_stack(context_, -1).get_stack());
+	if (duk_peval_string(context_, data.c_str()))
+		throw plugin_error(plugin_error::exec_error, get_name(), duk::get_stack(context_, -1).get_stack());
 }
 
 void js_plugin::handle_command(irccd&, const message_event& event)
 {
-    call("onCommand", event.server, event.origin, event.channel, event.message);
+	call("onCommand", event.server, event.origin, event.channel, event.message);
 }
 
 void js_plugin::handle_connect(irccd&, const connect_event& event)
 {
-    call("onConnect", event.server);
+	call("onConnect", event.server);
 }
 
 void js_plugin::handle_disconnect(irccd&, const disconnect_event& event)
 {
-    call("onDisconnect", event.server);
+	call("onDisconnect", event.server);
 }
 
 void js_plugin::handle_invite(irccd&, const invite_event& event)
 {
-    call("onInvite", event.server, event.origin, event.channel);
+	call("onInvite", event.server, event.origin, event.channel);
 }
 
 void js_plugin::handle_join(irccd&, const join_event& event)
 {
-    call("onJoin", event.server, event.origin, event.channel);
+	call("onJoin", event.server, event.origin, event.channel);
 }
 
 void js_plugin::handle_kick(irccd&, const kick_event& event)
 {
-    call("onKick", event.server, event.origin, event.channel, event.target, event.reason);
+	call("onKick", event.server, event.origin, event.channel, event.target, event.reason);
 }
 
 void js_plugin::handle_load(irccd&)
 {
-    call("onLoad");
+	call("onLoad");
 }
 
 void js_plugin::handle_message(irccd&, const message_event& event)
 {
-    call("onMessage", event.server, event.origin, event.channel, event.message);
+	call("onMessage", event.server, event.origin, event.channel, event.message);
 }
 
 void js_plugin::handle_me(irccd&, const me_event& event)
 {
-    call("onMe", event.server, event.origin, event.channel, event.message);
+	call("onMe", event.server, event.origin, event.channel, event.message);
 }
 
 void js_plugin::handle_mode(irccd&, const mode_event& event)
 {
-    call("onMode", event.server, event.origin, event.channel, event.mode,
-        event.limit, event.user, event.mask);
+	call("onMode", event.server, event.origin, event.channel, event.mode,
+		event.limit, event.user, event.mask);
 }
 
 void js_plugin::handle_names(irccd&, const names_event& event)
 {
-    call("onNames", event.server, event.channel, event.names);
+	call("onNames", event.server, event.channel, event.names);
 }
 
 void js_plugin::handle_nick(irccd&, const nick_event& event)
 {
-    call("onNick", event.server, event.origin, event.nickname);
+	call("onNick", event.server, event.origin, event.nickname);
 }
 
 void js_plugin::handle_notice(irccd&, const notice_event& event)
 {
-    call("onNotice", event.server, event.origin, event.channel, event.message);
+	call("onNotice", event.server, event.origin, event.channel, event.message);
 }
 
 void js_plugin::handle_part(irccd&, const part_event& event)
 {
-    call("onPart", event.server, event.origin, event.channel, event.reason);
+	call("onPart", event.server, event.origin, event.channel, event.reason);
 }
 
 void js_plugin::handle_reload(irccd&)
 {
-    call("onReload");
+	call("onReload");
 }
 
 void js_plugin::handle_topic(irccd&, const topic_event& event)
 {
-    call("onTopic", event.server, event.origin, event.channel, event.topic);
+	call("onTopic", event.server, event.origin, event.channel, event.topic);
 }
 
 void js_plugin::handle_unload(irccd&)
 {
-    call("onUnload");
+	call("onUnload");
 }
 
 void js_plugin::handle_whois(irccd&, const whois_event& event)
 {
-    call("onWhois", event.server, event.whois);
+	call("onWhois", event.server, event.whois);
 }
 
 js_plugin_loader::js_plugin_loader(irccd& irccd) noexcept
-    : plugin_loader({}, { ".js" })
-    , irccd_(irccd)
+	: plugin_loader({}, { ".js" })
+	, irccd_(irccd)
 {
 }
 
@@ -323,42 +323,42 @@
 
 auto js_plugin_loader::get_modules() const noexcept -> const modules&
 {
-    return modules_;
+	return modules_;
 }
 
 auto js_plugin_loader::get_modules() noexcept -> modules&
 {
-    return modules_;
+	return modules_;
 }
 
 auto js_plugin_loader::open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>
 {
-    if (path.rfind(".js") == std::string::npos)
-        return nullptr;
+	if (path.rfind(".js") == std::string::npos)
+		return nullptr;
 
-    auto plugin = std::make_shared<js_plugin>(std::string(id), std::string(path));
+	auto plugin = std::make_shared<js_plugin>(std::string(id), std::string(path));
 
-    for (const auto& mod : modules_)
-        mod->load(irccd_, plugin);
+	for (const auto& mod : modules_)
+		mod->load(irccd_, plugin);
 
-    plugin->open();
+	plugin->open();
 
-    return plugin;
+	return plugin;
 }
 
 void duk::type_traits<whois_info>::push(duk_context* ctx, const whois_info& whois)
 {
-    duk_push_object(ctx);
-    duk::push(ctx, whois.nick);
-    duk_put_prop_string(ctx, -2, "nickname");
-    duk::push(ctx, whois.user);
-    duk_put_prop_string(ctx, -2, "username");
-    duk::push(ctx, whois.realname);
-    duk_put_prop_string(ctx, -2, "realname");
-    duk::push(ctx, whois.host);
-    duk_put_prop_string(ctx, -2, "host");
-    duk::push(ctx, whois.channels);
-    duk_put_prop_string(ctx, -2, "channels");
+	duk_push_object(ctx);
+	duk::push(ctx, whois.nick);
+	duk_put_prop_string(ctx, -2, "nickname");
+	duk::push(ctx, whois.user);
+	duk_put_prop_string(ctx, -2, "username");
+	duk::push(ctx, whois.realname);
+	duk_put_prop_string(ctx, -2, "realname");
+	duk::push(ctx, whois.host);
+	duk_put_prop_string(ctx, -2, "host");
+	duk::push(ctx, whois.channels);
+	duk_put_prop_string(ctx, -2, "channels");
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/js_plugin.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/js_plugin.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -39,201 +39,201 @@
  */
 class js_plugin : public plugin {
 public:
-    /**
-     * Global property where to read/write plugin configuration (object).
-     */
-    static inline const std::string_view config_property{"\xff\xff""config"};
+	/**
+	 * Global property where to read/write plugin configuration (object).
+	 */
+	static inline const std::string_view config_property{"\xff\xff""config"};
 
-    /**
-     * Global property where to read/write plugin formats (object).
-     */
-    static inline const std::string_view format_property{"\xff\xff""formats"};
+	/**
+	 * Global property where to read/write plugin formats (object).
+	 */
+	static inline const std::string_view format_property{"\xff\xff""formats"};
 
-    /**
-     * Global property where paths are defined (object).
-     */
-    static inline const std::string_view paths_property{"\xff\xff""paths"};
+	/**
+	 * Global property where paths are defined (object).
+	 */
+	static inline const std::string_view paths_property{"\xff\xff""paths"};
 
 private:
-    // JavaScript context.
-    mutable duk::context context_;
+	// JavaScript context.
+	mutable duk::context context_;
 
-    // Path to Javascript script file.
-    std::string path_;
+	// Path to Javascript script file.
+	std::string path_;
 
-    void push() noexcept;
+	void push() noexcept;
 
-    template <typename Value, typename... Args>
-    void push(Value&& value, Args&&... args);
+	template <typename Value, typename... Args>
+	void push(Value&& value, Args&&... args);
 
-    template <typename... Args>
-    void call(const std::string&, Args&&... args);
+	template <typename... Args>
+	void call(const std::string&, Args&&... args);
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param id the plugin id
-     * \param path the path to the plugin
-     */
-    js_plugin(std::string id, std::string path);
+	/**
+	 * Constructor.
+	 *
+	 * \param id the plugin id
+	 * \param path the path to the plugin
+	 */
+	js_plugin(std::string id, std::string path);
 
-    /**
-     * Access the Duktape context.
-     *
-     * \return the context
-     */
-    auto get_context() noexcept -> duk::context&;
+	/**
+	 * Access the Duktape context.
+	 *
+	 * \return the context
+	 */
+	auto get_context() noexcept -> duk::context&;
 
-    /**
-     * Open the script file associated.
-     */
-    void open();
+	/**
+	 * Open the script file associated.
+	 */
+	void open();
 
-    /**
-     * \copydoc plugin::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_author
-     */
-    auto get_author() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_author
+	 */
+	auto get_author() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_license
-     */
-    auto get_license() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_license
+	 */
+	auto get_license() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_summary
-     */
-    auto get_summary() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_summary
+	 */
+	auto get_summary() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_version
-     */
-    auto get_version() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_version
+	 */
+	auto get_version() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_options
-     */
-    auto get_options() const -> map override;
+	/**
+	 * \copydoc plugin::get_options
+	 */
+	auto get_options() const -> map override;
 
-    /**
-     * \copydoc plugin::set_options
-     */
-    void set_options(const map& map) override;
+	/**
+	 * \copydoc plugin::set_options
+	 */
+	void set_options(const map& map) override;
 
-    /**
-     * \copydoc plugin::get_formats
-     */
-    auto get_formats() const -> map override;
+	/**
+	 * \copydoc plugin::get_formats
+	 */
+	auto get_formats() const -> map override;
 
-    /**
-     * \copydoc plugin::set_formats
-     */
-    void set_formats(const map& map) override;
+	/**
+	 * \copydoc plugin::set_formats
+	 */
+	void set_formats(const map& map) override;
 
-    /**
-     * \copydoc plugin::get_paths
-     */
-    auto get_paths() const -> map override;
+	/**
+	 * \copydoc plugin::get_paths
+	 */
+	auto get_paths() const -> map override;
 
-    /**
-     * \copydoc plugin::set_path
-     */
-    void set_paths(const map& map) override;
+	/**
+	 * \copydoc plugin::set_path
+	 */
+	void set_paths(const map& map) override;
 
-    /**
-     * \copydoc plugin::handle_command
-     */
-    void handle_command(irccd& irccd, const message_event& event) override;
+	/**
+	 * \copydoc plugin::handle_command
+	 */
+	void handle_command(irccd& irccd, const message_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_connect
-     */
-    void handle_connect(irccd& irccd, const connect_event& event) override;
+	/**
+	 * \copydoc plugin::handle_connect
+	 */
+	void handle_connect(irccd& irccd, const connect_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_disconnect
-     */
-    void handle_disconnect(irccd& irccd, const disconnect_event& event) override;
+	/**
+	 * \copydoc plugin::handle_disconnect
+	 */
+	void handle_disconnect(irccd& irccd, const disconnect_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_invite
-     */
-    void handle_invite(irccd& irccd, const invite_event& event) override;
+	/**
+	 * \copydoc plugin::handle_invite
+	 */
+	void handle_invite(irccd& irccd, const invite_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_join
-     */
-    void handle_join(irccd& irccd, const join_event& event) override;
+	/**
+	 * \copydoc plugin::handle_join
+	 */
+	void handle_join(irccd& irccd, const join_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_kick
-     */
-    void handle_kick(irccd& irccd, const kick_event& event) override;
+	/**
+	 * \copydoc plugin::handle_kick
+	 */
+	void handle_kick(irccd& irccd, const kick_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_load
-     */
-    void handle_load(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_load
+	 */
+	void handle_load(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_message
-     */
-    void handle_message(irccd& irccd, const message_event& event) override;
+	/**
+	 * \copydoc plugin::handle_message
+	 */
+	void handle_message(irccd& irccd, const message_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_me
-     */
-    void handle_me(irccd& irccd, const me_event& event) override;
+	/**
+	 * \copydoc plugin::handle_me
+	 */
+	void handle_me(irccd& irccd, const me_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_mode
-     */
-    void handle_mode(irccd& irccd, const mode_event& event) override;
+	/**
+	 * \copydoc plugin::handle_mode
+	 */
+	void handle_mode(irccd& irccd, const mode_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_names
-     */
-    void handle_names(irccd& irccd, const names_event& event) override;
+	/**
+	 * \copydoc plugin::handle_names
+	 */
+	void handle_names(irccd& irccd, const names_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_nick
-     */
-    void handle_nick(irccd& irccd, const nick_event& event) override;
+	/**
+	 * \copydoc plugin::handle_nick
+	 */
+	void handle_nick(irccd& irccd, const nick_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_notice
-     */
-    void handle_notice(irccd& irccd, const notice_event& event) override;
+	/**
+	 * \copydoc plugin::handle_notice
+	 */
+	void handle_notice(irccd& irccd, const notice_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_part
-     */
-    void handle_part(irccd& irccd, const part_event& event) override;
+	/**
+	 * \copydoc plugin::handle_part
+	 */
+	void handle_part(irccd& irccd, const part_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_reload
-     */
-    void handle_reload(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_reload
+	 */
+	void handle_reload(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_topic
-     */
-    void handle_topic(irccd& irccd, const topic_event& event) override;
+	/**
+	 * \copydoc plugin::handle_topic
+	 */
+	void handle_topic(irccd& irccd, const topic_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_unload
-     */
-    void handle_unload(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_unload
+	 */
+	void handle_unload(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_whois
-     */
-    void handle_whois(irccd& irccd, const whois_event& event) override;
+	/**
+	 * \copydoc plugin::handle_whois
+	 */
+	void handle_whois(irccd& irccd, const whois_event& event) override;
 };
 
 /**
@@ -241,43 +241,43 @@
  */
 class js_plugin_loader : public plugin_loader {
 public:
-    using modules = std::vector<std::unique_ptr<js_api>>;
+	using modules = std::vector<std::unique_ptr<js_api>>;
 
 private:
-    irccd& irccd_;
-    modules modules_;
+	irccd& irccd_;
+	modules modules_;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param irccd the irccd instance
-     */
-    js_plugin_loader(irccd& irccd) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	js_plugin_loader(irccd& irccd) noexcept;
 
-    /**
-     * Destructor defaulted.
-     */
-    ~js_plugin_loader() noexcept;
+	/**
+	 * Destructor defaulted.
+	 */
+	~js_plugin_loader() noexcept;
 
-    /**
-     * Get the list of modules.
-     *
-     * \return the modules
-     */
-    auto get_modules() const noexcept -> const modules&;
+	/**
+	 * Get the list of modules.
+	 *
+	 * \return the modules
+	 */
+	auto get_modules() const noexcept -> const modules&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the modules
-     */
-    auto get_modules() noexcept -> modules&;
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the modules
+	 */
+	auto get_modules() noexcept -> modules&;
 
-    /**
-     * \copydoc plugin_loader::open
-     */
-    auto open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>;
+	/**
+	 * \copydoc plugin_loader::open
+	 */
+	auto open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>;
 };
 
 namespace duk {
@@ -287,13 +287,13 @@
  */
 template <>
 struct type_traits<whois_info> : public std::true_type {
-    /**
-     * Push a whois_info.
-     *
-     * \param ctx the Duktape context
-     * \param who the information
-     */
-    static void push(duk_context* ctx, const whois_info& who);
+	/**
+	 * Push a whois_info.
+	 *
+	 * \param ctx the Duktape context
+	 * \param who the information
+	 */
+	static void push(duk_context* ctx, const whois_info& who);
 };
 
 } // !duk
--- a/libirccd-js/irccd/js/logger_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/logger_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,28 +33,28 @@
 
 auto print(duk_context* ctx, unsigned level) -> duk_ret_t
 {
-    assert(level <= 2);
+	assert(level <= 2);
 
-    try {
-        auto& sink = duk::type_traits<irccd>::self(ctx).get_log();
-        auto& self = duk::type_traits<js_plugin>::self(ctx);
+	try {
+		auto& sink = duk::type_traits<irccd>::self(ctx).get_log();
+		auto& self = duk::type_traits<js_plugin>::self(ctx);
 
-        switch (level) {
-        case 0:
-            sink.debug<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
-            break;
-        case 1:
-            sink.info<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
-            break;
-        default:
-            sink.warning<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
-            break;
-        }
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+		switch (level) {
+		case 0:
+			sink.debug<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
+			break;
+		case 1:
+			sink.info<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
+			break;
+		default:
+			sink.warning<plugin>(self) << duk_require_string(ctx, 0) << std::endl;
+			break;
+		}
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -74,7 +74,7 @@
  */
 auto Logger_info(duk_context* ctx) -> duk_ret_t
 {
-    return print(ctx, 1);
+	return print(ctx, 1);
 }
 
 // }}}
@@ -94,7 +94,7 @@
  */
 auto Logger_warning(duk_context* ctx) -> duk_ret_t
 {
-    return print(ctx, 2);
+	return print(ctx, 2);
 }
 
 // }}}
@@ -114,34 +114,34 @@
  */
 auto Logger_debug(duk_context* ctx) -> duk_ret_t
 {
-    return print(ctx, 0);
+	return print(ctx, 0);
 }
 
 // }}}
 
 const duk_function_list_entry functions[] = {
-    { "info",       Logger_info,    1 },
-    { "warning",    Logger_warning, 1 },
-    { "debug",      Logger_debug,   1 },
-    { nullptr,      nullptr,        0 }
+	{ "info",       Logger_info,    1 },
+	{ "warning",    Logger_warning, 1 },
+	{ "debug",      Logger_debug,   1 },
+	{ nullptr,      nullptr,        0 }
 };
 
 } // !namespace
 
 auto logger_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Logger";
+	return "Irccd.Logger";
 }
 
 void logger_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_put_prop_string(plugin->get_context(), -2, "Logger");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_put_prop_string(plugin->get_context(), -2, "Logger");
+	duk_pop(plugin->get_context());
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/logger_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/logger_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class logger_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc Module::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc Module::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/plugin_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/plugin_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,17 +32,17 @@
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_idx_t
 {
-    try {
-        return handler();
-    } catch (const plugin_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler();
+	} catch (const plugin_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 /*
@@ -61,8 +61,8 @@
  * Plugin 'xyz' does:
  *
  * Irccd.Plugin.config = {
- *      mode: "simple",
- *      level: "123"
+ *	  mode: "simple",
+ *	  level: "123"
  * };
  *
  * The user configuration is:
@@ -74,30 +74,30 @@
  * The final user table looks like this:
  *
  * Irccd.Plugin.Config = {
- *      mode: "hard",
- *      level: "123",
- *      path: "/var"
+ *	  mode: "hard",
+ *	  level: "123",
+ *	  path: "/var"
  * };
  */
 auto set(duk_context* ctx, std::string_view name) -> duk_ret_t
 {
-    if (!duk_is_object(ctx, 0))
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "'%s' property must be object", name.data());
+	if (!duk_is_object(ctx, 0))
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "'%s' property must be object", name.data());
 
-    // Merge old table with new one.
-    duk_get_global_string(ctx, name.data());
-    duk_enum(ctx, -1, 0);
+	// Merge old table with new one.
+	duk_get_global_string(ctx, name.data());
+	duk_enum(ctx, -1, 0);
 
-    while (duk_next(ctx, -1, true))
-        duk_put_prop(ctx, 0);
+	while (duk_next(ctx, -1, true))
+		duk_put_prop(ctx, 0);
 
-    // Pop enum and old table.
-    duk_pop_2(ctx);
+	// Pop enum and old table.
+	duk_pop_2(ctx);
 
-    // Replace the old table with the new assigned one.
-    duk_put_global_string(ctx, name.data());
+	// Replace the old table with the new assigned one.
+	duk_put_global_string(ctx, name.data());
 
-    return 0;
+	return 0;
 }
 
 /*
@@ -108,9 +108,9 @@
  */
 auto get(duk_context* ctx, std::string_view name) -> duk_ret_t
 {
-    duk_get_global_string(ctx, name.data());
+	duk_get_global_string(ctx, name.data());
 
-    return 1;
+	return 1;
 }
 
 /*
@@ -121,7 +121,7 @@
  */
 auto set_config(duk_context* ctx) -> duk_ret_t
 {
-    return set(ctx, js_plugin::config_property);
+	return set(ctx, js_plugin::config_property);
 }
 
 /*
@@ -132,7 +132,7 @@
  */
 auto get_config(duk_context* ctx) -> duk_ret_t
 {
-    return get(ctx, js_plugin::config_property);
+	return get(ctx, js_plugin::config_property);
 }
 
 /*
@@ -143,7 +143,7 @@
  */
 auto set_format(duk_context* ctx) -> duk_ret_t
 {
-    return set(ctx, js_plugin::format_property);
+	return set(ctx, js_plugin::format_property);
 }
 
 /*
@@ -154,7 +154,7 @@
  */
 auto get_format(duk_context* ctx) -> duk_ret_t
 {
-    return get(ctx, js_plugin::format_property);
+	return get(ctx, js_plugin::format_property);
 }
 
 /*
@@ -165,7 +165,7 @@
  */
 auto set_paths(duk_context* ctx) -> duk_ret_t
 {
-    return set(ctx, js_plugin::paths_property);
+	return set(ctx, js_plugin::paths_property);
 }
 
 /*
@@ -176,7 +176,7 @@
  */
 auto get_paths(duk_context* ctx) -> duk_ret_t
 {
-    return get(ctx, js_plugin::paths_property);
+	return get(ctx, js_plugin::paths_property);
 }
 
 // {{{ Irccd.Plugin.info
@@ -197,7 +197,7 @@
  *
  * Arguments:
  *   - name, the plugin identifier, if not specified the current plugin is
- *     selected.
+ *	 selected.
  * Returns:
  *   The plugin information or undefined if the plugin was not found.
  * Throws:
@@ -205,31 +205,31 @@
  */
 auto Plugin_info(duk_context* ctx) -> duk_idx_t
 {
-    return wrap(ctx, [&] {
-        plugin* plugin;
+	return wrap(ctx, [&] {
+		plugin* plugin;
 
-        if (duk_get_top(ctx) >= 1)
-            plugin = duk::type_traits<irccd>::self(ctx).plugins().get(duk_require_string(ctx, 0)).get();
-        else
-            plugin = std::addressof(duk::type_traits<js_plugin>::self(ctx));
+		if (duk_get_top(ctx) >= 1)
+			plugin = duk::type_traits<irccd>::self(ctx).plugins().get(duk_require_string(ctx, 0)).get();
+		else
+			plugin = std::addressof(duk::type_traits<js_plugin>::self(ctx));
 
-        if (!plugin)
-            return 0;
+		if (!plugin)
+			return 0;
 
-        duk_push_object(ctx);
-        duk::push(ctx, plugin->get_name());
-        duk_put_prop_string(ctx, -2, "name");
-        duk::push(ctx, plugin->get_author());
-        duk_put_prop_string(ctx, -2, "author");
-        duk::push(ctx, plugin->get_license());
-        duk_put_prop_string(ctx, -2, "license");
-        duk::push(ctx, plugin->get_summary());
-        duk_put_prop_string(ctx, -2, "summary");
-        duk::push(ctx, plugin->get_version());
-        duk_put_prop_string(ctx, -2, "version");
+		duk_push_object(ctx);
+		duk::push(ctx, plugin->get_name());
+		duk_put_prop_string(ctx, -2, "name");
+		duk::push(ctx, plugin->get_author());
+		duk_put_prop_string(ctx, -2, "author");
+		duk::push(ctx, plugin->get_license());
+		duk_put_prop_string(ctx, -2, "license");
+		duk::push(ctx, plugin->get_summary());
+		duk_put_prop_string(ctx, -2, "summary");
+		duk::push(ctx, plugin->get_version());
+		duk_put_prop_string(ctx, -2, "version");
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -247,16 +247,16 @@
  */
 auto Plugin_list(duk_context* ctx) -> duk_idx_t
 {
-    int i = 0;
+	int i = 0;
 
-    duk_push_array(ctx);
+	duk_push_array(ctx);
 
-    for (const auto& plg : duk::type_traits<irccd>::self(ctx).plugins().all()) {
-        duk::push(ctx, plg->get_id());
-        duk_put_prop_index(ctx, -2, i++);
-    }
+	for (const auto& plg : duk::type_traits<irccd>::self(ctx).plugins().all()) {
+		duk::push(ctx, plg->get_id());
+		duk_put_prop_index(ctx, -2, i++);
+	}
 
-    return 1;
+	return 1;
 }
 
 // }}}
@@ -278,12 +278,12 @@
  */
 auto Plugin_load(duk_context* ctx) -> duk_idx_t
 {
-    return wrap(ctx, [&] {
-        duk::type_traits<irccd>::self(ctx).plugins().load(
-            duk::require<std::string_view>(ctx, 0), "");
+	return wrap(ctx, [&] {
+		duk::type_traits<irccd>::self(ctx).plugins().load(
+			duk::require<std::string_view>(ctx, 0), "");
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -304,11 +304,11 @@
  */
 auto Plugin_reload(duk_context* ctx) -> duk_idx_t
 {
-    return wrap(ctx, [&] {
-        duk::type_traits<irccd>::self(ctx).plugins().reload(duk::require<std::string>(ctx, 0));
+	return wrap(ctx, [&] {
+		duk::type_traits<irccd>::self(ctx).plugins().reload(duk::require<std::string>(ctx, 0));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -329,11 +329,11 @@
  */
 auto Plugin_unload(duk_context* ctx) -> duk_idx_t
 {
-    return wrap(ctx, [&] {
-        duk::type_traits<irccd>::self(ctx).plugins().unload(duk::require<std::string>(ctx, 0));
+	return wrap(ctx, [&] {
+		duk::type_traits<irccd>::self(ctx).plugins().unload(duk::require<std::string>(ctx, 0));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -352,105 +352,105 @@
  */
 auto PluginError_constructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_this(ctx);
-    duk_push_int(ctx, duk_require_int(ctx, 0));
-    duk_put_prop_string(ctx, -2, "code");
-    duk_push_string(ctx, duk_require_string(ctx, 1));
-    duk_put_prop_string(ctx, -2, "message");
-    duk_push_string(ctx, "PluginError");
-    duk_put_prop_string(ctx, -2, "name");
-    duk_pop(ctx);
+	duk_push_this(ctx);
+	duk_push_int(ctx, duk_require_int(ctx, 0));
+	duk_put_prop_string(ctx, -2, "code");
+	duk_push_string(ctx, duk_require_string(ctx, 1));
+	duk_put_prop_string(ctx, -2, "message");
+	duk_push_string(ctx, "PluginError");
+	duk_put_prop_string(ctx, -2, "name");
+	duk_pop(ctx);
 
-    return 0;
+	return 0;
 }
 
 // }}}
 
 const duk_function_list_entry functions[] = {
-    { "info",   Plugin_info,    DUK_VARARGS },
-    { "list",   Plugin_list,    0           },
-    { "load",   Plugin_load,    1           },
-    { "reload", Plugin_reload,  1           },
-    { "unload", Plugin_unload,  1           },
-    { nullptr,  nullptr,        0           }
+	{ "info",       Plugin_info,    DUK_VARARGS     },
+	{ "list",       Plugin_list,    0               },
+	{ "load",       Plugin_load,    1               },
+	{ "reload",     Plugin_reload,  1               },
+	{ "unload",     Plugin_unload,  1               },
+	{ nullptr,      nullptr,        0               }
 };
 
 } // !namespace
 
 auto plugin_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Plugin";
+	return "Irccd.Plugin";
 }
 
 void plugin_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    // Store plugin.
-    duk_push_pointer(plugin->get_context(), plugin.get());
-    duk_put_global_string(plugin->get_context(), signature.data());
+	// Store plugin.
+	duk_push_pointer(plugin->get_context(), plugin.get());
+	duk_put_global_string(plugin->get_context(), signature.data());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, functions);
 
-    // 'config' property.
-    duk_push_string(plugin->get_context(), "config");
-    duk_push_c_function(plugin->get_context(), get_config, 0);
-    duk_push_c_function(plugin->get_context(), set_config, 1);
-    duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+	// 'config' property.
+	duk_push_string(plugin->get_context(), "config");
+	duk_push_c_function(plugin->get_context(), get_config, 0);
+	duk_push_c_function(plugin->get_context(), set_config, 1);
+	duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
 
-    // 'format' property.
-    duk_push_string(plugin->get_context(), "format");
-    duk_push_c_function(plugin->get_context(), get_format, 0);
-    duk_push_c_function(plugin->get_context(), set_format, 1);
-    duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+	// 'format' property.
+	duk_push_string(plugin->get_context(), "format");
+	duk_push_c_function(plugin->get_context(), get_format, 0);
+	duk_push_c_function(plugin->get_context(), set_format, 1);
+	duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
 
-    // 'format' property.
-    duk_push_string(plugin->get_context(), "paths");
-    duk_push_c_function(plugin->get_context(), get_paths, 0);
-    duk_push_c_function(plugin->get_context(), set_paths, 1);
-    duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
+	// 'format' property.
+	duk_push_string(plugin->get_context(), "paths");
+	duk_push_c_function(plugin->get_context(), get_paths, 0);
+	duk_push_c_function(plugin->get_context(), set_paths, 1);
+	duk_def_prop(plugin->get_context(), -4, DUK_DEFPROP_HAVE_GETTER | DUK_DEFPROP_HAVE_SETTER);
 
-    // PluginError function.
-    duk_push_c_function(plugin->get_context(), PluginError_constructor, 2);
-    duk_push_object(plugin->get_context());
-    duk_get_global_string(plugin->get_context(), "Error");
-    duk_get_prop_string(plugin->get_context(), -1, "prototype");
-    duk_remove(plugin->get_context(), -2);
-    duk_set_prototype(plugin->get_context(), -2);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "PluginError");
+	// PluginError function.
+	duk_push_c_function(plugin->get_context(), PluginError_constructor, 2);
+	duk_push_object(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Error");
+	duk_get_prop_string(plugin->get_context(), -1, "prototype");
+	duk_remove(plugin->get_context(), -2);
+	duk_set_prototype(plugin->get_context(), -2);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "PluginError");
 
-    duk_put_prop_string(plugin->get_context(), -2, "Plugin");
-    duk_pop(plugin->get_context());
+	duk_put_prop_string(plugin->get_context(), -2, "Plugin");
+	duk_pop(plugin->get_context());
 }
 
 namespace duk {
 
 auto type_traits<js_plugin>::self(duk_context* ctx) -> js_plugin&
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_get_global_string(ctx, signature.data());
-    auto plugin = static_cast<js_plugin*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
+	duk_get_global_string(ctx, signature.data());
+	auto plugin = static_cast<js_plugin*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
 
-    return *plugin;
+	return *plugin;
 }
 
 void type_traits<plugin_error>::raise(duk_context* ctx, const plugin_error& ex)
 {
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_get_global_string(ctx, "Irccd");
-    duk_get_prop_string(ctx, -1, "PluginError");
-    duk_remove(ctx, -2);
-    duk::push(ctx, ex.code().value());
-    duk::push(ctx, ex.code().message());
-    duk_new(ctx, 2);
+	duk_get_global_string(ctx, "Irccd");
+	duk_get_prop_string(ctx, -1, "PluginError");
+	duk_remove(ctx, -2);
+	duk::push(ctx, ex.code().value());
+	duk::push(ctx, ex.code().message());
+	duk_new(ctx, 2);
 
-    (void)duk_throw(ctx);
+	(void)duk_throw(ctx);
 }
 
 } // !duk
--- a/libirccd-js/irccd/js/plugin_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/plugin_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,15 +35,15 @@
  */
 class plugin_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc Module::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc Module::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 namespace duk {
@@ -53,13 +53,13 @@
  */
 template <>
 struct type_traits<js_plugin> {
-    /**
-     * Access the plugin stored in this context.
-     *
-     * \param ctx the context
-     * \return the plugin
-     */
-    static auto self(duk_context* ctx) -> js_plugin&;
+	/**
+	 * Access the plugin stored in this context.
+	 *
+	 * \param ctx the context
+	 * \return the plugin
+	 */
+	static auto self(duk_context* ctx) -> js_plugin&;
 };
 
 /**
@@ -67,13 +67,13 @@
  */
 template <>
 struct type_traits<plugin_error> {
-    /**
-     * Raise a plugin_error.
-     *
-     * \param ctx the context
-     * \param error the error
-     */
-    static void raise(duk_context* ctx, const plugin_error& error);
+	/**
+	 * Raise a plugin_error.
+	 *
+	 * \param ctx the context
+	 * \param error the error
+	 */
+	static void raise(duk_context* ctx, const plugin_error& error);
 };
 
 } // !duk
--- a/libirccd-js/irccd/js/server_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/server_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -37,31 +37,31 @@
 
 auto self(duk_context* ctx) -> std::shared_ptr<server>
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, signature.data());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, signature.data());
+	auto ptr = duk_to_pointer(ctx, -1);
+	duk_pop_2(ctx);
 
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Server object");
+	if (!ptr)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Server object");
 
-    return *static_cast<std::shared_ptr<server>*>(ptr);
+	return *static_cast<std::shared_ptr<server>*>(ptr);
 }
 
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_ret_t
 {
-    try {
-        return handler(ctx);
-    } catch (const server_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler(ctx);
+	} catch (const server_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // {{{ Irccd.Server.prototype.info
@@ -81,34 +81,34 @@
  */
 auto Server_prototype_info(duk_context* ctx) -> duk_ret_t
 {
-    const auto server = self(ctx);
-    const auto& channels = server->get_channels();
+	const auto server = self(ctx);
+	const auto& channels = server->get_channels();
 
-    duk_push_object(ctx);
-    duk::push(ctx, server->get_id());
-    duk_put_prop_string(ctx, -2, "name");
-    duk::push(ctx, server->get_host());
-    duk_put_prop_string(ctx, -2, "host");
-    duk_push_int(ctx, server->get_port());
-    duk_put_prop_string(ctx, -2, "port");
-    duk_push_boolean(ctx,
-        (server->get_options() & server::options::ssl) == server::options::ssl);
-    duk_put_prop_string(ctx, -2, "ssl");
-    duk_push_boolean(ctx,
-        (server->get_options() & server::options::ssl_verify) == server::options::ssl_verify);
-    duk_put_prop_string(ctx, -2, "sslVerify");
-    duk::push(ctx, server->get_command_char());
-    duk_put_prop_string(ctx, -2, "commandChar");
-    duk::push(ctx, server->get_realname());
-    duk_put_prop_string(ctx, -2, "realname");
-    duk::push(ctx, server->get_nickname());
-    duk_put_prop_string(ctx, -2, "nickname");
-    duk::push(ctx, server->get_username());
-    duk_put_prop_string(ctx, -2, "username");
-    duk::push(ctx, std::vector<std::string>(channels.begin(), channels.end()));
-    duk_put_prop_string(ctx, -2, "channels");
+	duk_push_object(ctx);
+	duk::push(ctx, server->get_id());
+	duk_put_prop_string(ctx, -2, "name");
+	duk::push(ctx, server->get_host());
+	duk_put_prop_string(ctx, -2, "host");
+	duk_push_int(ctx, server->get_port());
+	duk_put_prop_string(ctx, -2, "port");
+	duk_push_boolean(ctx,
+		(server->get_options() & server::options::ssl) == server::options::ssl);
+	duk_put_prop_string(ctx, -2, "ssl");
+	duk_push_boolean(ctx,
+		(server->get_options() & server::options::ssl_verify) == server::options::ssl_verify);
+	duk_put_prop_string(ctx, -2, "sslVerify");
+	duk::push(ctx, server->get_command_char());
+	duk_put_prop_string(ctx, -2, "commandChar");
+	duk::push(ctx, server->get_realname());
+	duk_put_prop_string(ctx, -2, "realname");
+	duk::push(ctx, server->get_nickname());
+	duk_put_prop_string(ctx, -2, "nickname");
+	duk::push(ctx, server->get_username());
+	duk_put_prop_string(ctx, -2, "username");
+	duk::push(ctx, std::vector<std::string>(channels.begin(), channels.end()));
+	duk_put_prop_string(ctx, -2, "channels");
 
-    return 1;
+	return 1;
 }
 
 // }}}
@@ -130,19 +130,19 @@
  */
 auto Server_prototype_invite(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
-        auto channel = duk::require<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
+		auto channel = duk::require<std::string>(ctx, 1);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->invite(std::move(target), std::move(channel));
+		self(ctx)->invite(std::move(target), std::move(channel));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -162,9 +162,9 @@
  */
 auto Server_prototype_isSelf(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        return duk::push(ctx, self(ctx)->is_self(duk::require<std::string>(ctx, 0)));
-    });
+	return wrap(ctx, [] (auto ctx) {
+		return duk::push(ctx, self(ctx)->is_self(duk::require<std::string>(ctx, 0)));
+	});
 }
 
 // }}}
@@ -186,17 +186,17 @@
  */
 auto Server_prototype_join(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto channel = duk::require<std::string>(ctx, 0);
-        auto password = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto channel = duk::require<std::string>(ctx, 0);
+		auto password = duk::get<std::string>(ctx, 1);
 
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->join(std::move(channel), std::move(password));
+		self(ctx)->join(std::move(channel), std::move(password));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -219,20 +219,20 @@
  */
 auto Server_prototype_kick(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
-        auto channel = duk::require<std::string>(ctx, 1);
-        auto reason = duk::get<std::string>(ctx, 2);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
+		auto channel = duk::require<std::string>(ctx, 1);
+		auto reason = duk::get<std::string>(ctx, 2);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->kick(std::move(target), std::move(channel), std::move(reason));
+		self(ctx)->kick(std::move(target), std::move(channel), std::move(reason));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -254,17 +254,17 @@
  */
 auto Server_prototype_me(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
-        auto message = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
+		auto message = duk::get<std::string>(ctx, 1);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
 
-        self(ctx)->me(std::move(target), std::move(message));
+		self(ctx)->me(std::move(target), std::move(message));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -286,17 +286,17 @@
  */
 auto Server_prototype_message(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
-        auto message = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
+		auto message = duk::get<std::string>(ctx, 1);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
 
-        self(ctx)->message(std::move(target), std::move(message));
+		self(ctx)->message(std::move(target), std::move(message));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -317,28 +317,28 @@
  */
 auto Server_prototype_mode(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto channel = duk::require<std::string>(ctx, 0);
-        auto mode = duk::require<std::string>(ctx, 1);
-        auto limit = duk::get<std::string>(ctx, 2);
-        auto user = duk::get<std::string>(ctx, 3);
-        auto mask = duk::get<std::string>(ctx, 4);
+	return wrap(ctx, [] (auto ctx) {
+		auto channel = duk::require<std::string>(ctx, 0);
+		auto mode = duk::require<std::string>(ctx, 1);
+		auto limit = duk::get<std::string>(ctx, 2);
+		auto user = duk::get<std::string>(ctx, 3);
+		auto mask = duk::get<std::string>(ctx, 4);
 
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
-        if (mode.empty())
-            throw server_error(server_error::invalid_mode);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
+		if (mode.empty())
+			throw server_error(server_error::invalid_mode);
 
-        self(ctx)->mode(
-            std::move(channel),
-            std::move(mode),
-            std::move(limit),
-            std::move(user),
-            std::move(mask)
-        );
+		self(ctx)->mode(
+			std::move(channel),
+			std::move(mode),
+			std::move(limit),
+			std::move(user),
+			std::move(mask)
+		);
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -359,16 +359,16 @@
  */
 auto Server_prototype_names(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto channel = duk::require<std::string>(ctx, 0);
+	return wrap(ctx, [] (auto ctx) {
+		auto channel = duk::require<std::string>(ctx, 0);
 
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->names(std::move(channel));
+		self(ctx)->names(std::move(channel));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -389,16 +389,16 @@
  */
 auto Server_prototype_nick(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto nickname = duk::require<std::string>(ctx, 0);
+	return wrap(ctx, [] (auto ctx) {
+		auto nickname = duk::require<std::string>(ctx, 0);
 
-        if (nickname.empty())
-            throw server_error(server_error::invalid_nickname);
+		if (nickname.empty())
+			throw server_error(server_error::invalid_nickname);
 
-        self(ctx)->set_nickname(std::move(nickname));
+		self(ctx)->set_nickname(std::move(nickname));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -420,17 +420,17 @@
  */
 auto Server_prototype_notice(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
-        auto message = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
+		auto message = duk::get<std::string>(ctx, 1);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
 
-        self(ctx)->notice(std::move(target), std::move(message));
+		self(ctx)->notice(std::move(target), std::move(message));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -452,17 +452,17 @@
  */
 auto Server_prototype_part(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto channel = duk::require<std::string>(ctx, 0);
-        auto reason = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto channel = duk::require<std::string>(ctx, 0);
+		auto reason = duk::get<std::string>(ctx, 1);
 
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->part(std::move(channel), std::move(reason));
+		self(ctx)->part(std::move(channel), std::move(reason));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -483,16 +483,16 @@
  */
 auto Server_prototype_send(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto raw = duk::require<std::string>(ctx, 0);
+	return wrap(ctx, [] (auto ctx) {
+		auto raw = duk::require<std::string>(ctx, 0);
 
-        if (raw.empty())
-            throw server_error(server_error::invalid_message);
+		if (raw.empty())
+			throw server_error(server_error::invalid_message);
 
-        self(ctx)->send(std::move(raw));
+		self(ctx)->send(std::move(raw));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -514,17 +514,17 @@
  */
 auto Server_prototype_topic(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto channel = duk::require<std::string>(ctx, 0);
-        auto topic = duk::get<std::string>(ctx, 1);
+	return wrap(ctx, [] (auto ctx) {
+		auto channel = duk::require<std::string>(ctx, 0);
+		auto topic = duk::get<std::string>(ctx, 1);
 
-        if (channel.empty())
-            throw server_error(server_error::invalid_channel);
+		if (channel.empty())
+			throw server_error(server_error::invalid_channel);
 
-        self(ctx)->topic(std::move(channel), std::move(topic));
+		self(ctx)->topic(std::move(channel), std::move(topic));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -545,16 +545,16 @@
  */
 auto Server_prototype_whois(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto target = duk::require<std::string>(ctx, 0);
+	return wrap(ctx, [] (auto ctx) {
+		auto target = duk::require<std::string>(ctx, 0);
 
-        if (target.empty())
-            throw server_error(server_error::invalid_nickname);
+		if (target.empty())
+			throw server_error(server_error::invalid_nickname);
 
-        self(ctx)->whois(std::move(target));
+		self(ctx)->whois(std::move(target));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -575,11 +575,11 @@
  */
 auto Server_prototype_toString(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        duk::push(ctx, self(ctx)->get_id());
+	return wrap(ctx, [] (auto ctx) {
+		duk::push(ctx, self(ctx)->get_id());
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -615,22 +615,22 @@
  */
 auto Server_constructor(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        if (!duk_is_constructor_call(ctx))
-            return 0;
+	return wrap(ctx, [] (auto ctx) {
+		if (!duk_is_constructor_call(ctx))
+			return 0;
 
-        duk_check_type(ctx, 0, DUK_TYPE_OBJECT);
+		duk_check_type(ctx, 0, DUK_TYPE_OBJECT);
 
-        auto json = nlohmann::json::parse(duk_json_encode(ctx, 0));
-        auto s = server_util::from_json(duk::type_traits<irccd>::self(ctx).get_service(), json);
+		auto json = nlohmann::json::parse(duk_json_encode(ctx, 0));
+		auto s = server_util::from_json(duk::type_traits<irccd>::self(ctx).get_service(), json);
 
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, new std::shared_ptr<server>(std::move(s)));
-        duk_put_prop_string(ctx, -2, signature.data());
-        duk_pop(ctx);
+		duk_push_this(ctx);
+		duk_push_pointer(ctx, new std::shared_ptr<server>(std::move(s)));
+		duk_put_prop_string(ctx, -2, signature.data());
+		duk_pop(ctx);
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -645,12 +645,12 @@
  */
 auto Server_destructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_get_prop_string(ctx, 0, signature.data());
-    delete static_cast<std::shared_ptr<server>*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
-    duk_del_prop_string(ctx, 0, signature.data());
+	duk_get_prop_string(ctx, 0, signature.data());
+	delete static_cast<std::shared_ptr<server>*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
+	duk_del_prop_string(ctx, 0, signature.data());
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -670,12 +670,12 @@
  */
 auto Server_add(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        duk::type_traits<irccd>::self(ctx).servers().add(
-            duk::require<std::shared_ptr<server>>(ctx, 0));
+	return wrap(ctx, [] (auto ctx) {
+		duk::type_traits<irccd>::self(ctx).servers().add(
+			duk::require<std::shared_ptr<server>>(ctx, 0));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -697,17 +697,17 @@
  */
 auto Server_find(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [] (auto ctx) {
-        auto id = duk::require<std::string>(ctx, 0);
-        auto server = duk::type_traits<irccd>::self(ctx).servers().get(id);
+	return wrap(ctx, [] (auto ctx) {
+		auto id = duk::require<std::string>(ctx, 0);
+		auto server = duk::type_traits<irccd>::self(ctx).servers().get(id);
 
-        if (!server)
-            return 0;
+		if (!server)
+			return 0;
 
-        duk::push(ctx, server);
+		duk::push(ctx, server);
 
-        return 1;
-    });
+		return 1;
+	});
 }
 
 // }}}
@@ -725,14 +725,14 @@
  */
 auto Server_list(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_object(ctx);
+	duk_push_object(ctx);
 
-    for (const auto& server : duk::type_traits<irccd>::self(ctx).servers().all()) {
-        duk::push(ctx, server);
-        duk_put_prop_string(ctx, -2, server->get_id().c_str());
-    }
+	for (const auto& server : duk::type_traits<irccd>::self(ctx).servers().all()) {
+		duk::push(ctx, server);
+		duk_put_prop_string(ctx, -2, server->get_id().c_str());
+	}
 
-    return 1;
+	return 1;
 }
 
 // }}}
@@ -751,9 +751,9 @@
  */
 auto Server_remove(duk_context* ctx) -> duk_ret_t
 {
-    duk::type_traits<irccd>::self(ctx).servers().remove(duk_require_string(ctx, 0));
+	duk::type_traits<irccd>::self(ctx).servers().remove(duk_require_string(ctx, 0));
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -772,125 +772,125 @@
  */
 auto ServerError_constructor(duk_context* ctx) -> duk_ret_t
 {
-    duk_push_this(ctx);
-    duk_push_int(ctx, duk_require_int(ctx, 0));
-    duk_put_prop_string(ctx, -2, "code");
-    duk_push_string(ctx, duk_require_string(ctx, 1));
-    duk_put_prop_string(ctx, -2, "message");
-    duk_push_string(ctx, "ServerError");
-    duk_put_prop_string(ctx, -2, "name");
-    duk_pop(ctx);
+	duk_push_this(ctx);
+	duk_push_int(ctx, duk_require_int(ctx, 0));
+	duk_put_prop_string(ctx, -2, "code");
+	duk_push_string(ctx, duk_require_string(ctx, 1));
+	duk_put_prop_string(ctx, -2, "message");
+	duk_push_string(ctx, "ServerError");
+	duk_put_prop_string(ctx, -2, "name");
+	duk_pop(ctx);
 
-    return 0;
+	return 0;
 }
 
 // }}}
 
 const duk_function_list_entry methods[] = {
-    { "info",       Server_prototype_info,      0           },
-    { "invite",     Server_prototype_invite,    2           },
-    { "isSelf",     Server_prototype_isSelf,    1           },
-    { "join",       Server_prototype_join,      DUK_VARARGS },
-    { "kick",       Server_prototype_kick,      DUK_VARARGS },
-    { "me",         Server_prototype_me,        2           },
-    { "message",    Server_prototype_message,   2           },
-    { "mode",       Server_prototype_mode,      1           },
-    { "names",      Server_prototype_names,     1           },
-    { "nick",       Server_prototype_nick,      1           },
-    { "notice",     Server_prototype_notice,    2           },
-    { "part",       Server_prototype_part,      DUK_VARARGS },
-    { "send",       Server_prototype_send,      1           },
-    { "topic",      Server_prototype_topic,     2           },
-    { "toString",   Server_prototype_toString,  0           },
-    { "whois",      Server_prototype_whois,     1           },
-    { nullptr,      nullptr,                    0           }
+	{ "info",       Server_prototype_info,          0               },
+	{ "invite",     Server_prototype_invite,        2               },
+	{ "isSelf",     Server_prototype_isSelf,        1               },
+	{ "join",       Server_prototype_join,          DUK_VARARGS     },
+	{ "kick",       Server_prototype_kick,          DUK_VARARGS     },
+	{ "me",         Server_prototype_me,            2               },
+	{ "message",    Server_prototype_message,       2               },
+	{ "mode",       Server_prototype_mode,          1               },
+	{ "names",      Server_prototype_names,         1               },
+	{ "nick",       Server_prototype_nick,          1               },
+	{ "notice",     Server_prototype_notice,        2               },
+	{ "part",       Server_prototype_part,          DUK_VARARGS     },
+	{ "send",       Server_prototype_send,          1               },
+	{ "topic",      Server_prototype_topic,         2               },
+	{ "toString",   Server_prototype_toString,      0               },
+	{ "whois",      Server_prototype_whois,         1               },
+	{ nullptr,      nullptr,                        0               }
 };
 
 const duk_function_list_entry functions[] = {
-    { "add",        Server_add,                 1           },
-    { "find",       Server_find,                1           },
-    { "list",       Server_list,                0           },
-    { "remove",     Server_remove,              1           },
-    { nullptr,      nullptr,                    0           }
+	{ "add",        Server_add,                     1               },
+	{ "find",       Server_find,                    1               },
+	{ "list",       Server_list,                    0               },
+	{ "remove",     Server_remove,                  1               },
+	{ nullptr,      nullptr,                        0               }
 };
 
 } // !namespace
 
 auto server_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Server";
+	return "Irccd.Server";
 }
 
 void server_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_get_global_string(plugin->get_context(), "Irccd");
 
-    // ServerError function.
-    duk_push_c_function(plugin->get_context(), ServerError_constructor, 2);
-    duk_push_object(plugin->get_context());
-    duk_get_global_string(plugin->get_context(), "Error");
-    duk_get_prop_string(plugin->get_context(), -1, "prototype");
-    duk_remove(plugin->get_context(), -2);
-    duk_set_prototype(plugin->get_context(), -2);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "ServerError");
+	// ServerError function.
+	duk_push_c_function(plugin->get_context(), ServerError_constructor, 2);
+	duk_push_object(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Error");
+	duk_get_prop_string(plugin->get_context(), -1, "prototype");
+	duk_remove(plugin->get_context(), -2);
+	duk_set_prototype(plugin->get_context(), -2);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "ServerError");
 
-    // Server constructor.
-    duk_push_c_function(plugin->get_context(), Server_constructor, 1);
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, methods);
-    duk_push_c_function(plugin->get_context(), Server_destructor, 1);
-    duk_set_finalizer(plugin->get_context(), -2);
-    duk_dup_top(plugin->get_context());
-    duk_put_global_string(plugin->get_context(), prototype.data());
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "Server");
-    duk_pop(plugin->get_context());
+	// Server constructor.
+	duk_push_c_function(plugin->get_context(), Server_constructor, 1);
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, methods);
+	duk_push_c_function(plugin->get_context(), Server_destructor, 1);
+	duk_set_finalizer(plugin->get_context(), -2);
+	duk_dup_top(plugin->get_context());
+	duk_put_global_string(plugin->get_context(), prototype.data());
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "Server");
+	duk_pop(plugin->get_context());
 }
 
 namespace duk {
 
 void type_traits<std::shared_ptr<server>>::push(duk_context* ctx, std::shared_ptr<server> server)
 {
-    assert(ctx);
-    assert(server);
+	assert(ctx);
+	assert(server);
 
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_push_object(ctx);
-    duk_push_pointer(ctx, new std::shared_ptr<class server>(std::move(server)));
-    duk_put_prop_string(ctx, -2, signature.data());
-    duk_get_global_string(ctx, prototype.data());
-    duk_set_prototype(ctx, -2);
+	duk_push_object(ctx);
+	duk_push_pointer(ctx, new std::shared_ptr<class server>(std::move(server)));
+	duk_put_prop_string(ctx, -2, signature.data());
+	duk_get_global_string(ctx, prototype.data());
+	duk_set_prototype(ctx, -2);
 }
 
 auto type_traits<std::shared_ptr<server>>::require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<server>
 {
-    if (!duk_is_object(ctx, index) || !duk_has_prop_string(ctx, index, signature.data()))
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Server object");
+	if (!duk_is_object(ctx, index) || !duk_has_prop_string(ctx, index, signature.data()))
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Server object");
 
-    duk_get_prop_string(ctx, index, signature.data());
-    auto file = *static_cast<std::shared_ptr<server>*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
+	duk_get_prop_string(ctx, index, signature.data());
+	auto file = *static_cast<std::shared_ptr<server>*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
 
-    return file;
+	return file;
 }
 
 void type_traits<server_error>::raise(duk_context* ctx, const server_error& ex)
 {
-    duk::stack_guard sa(ctx, 1);
+	duk::stack_guard sa(ctx, 1);
 
-    duk_get_global_string(ctx, "Irccd");
-    duk_get_prop_string(ctx, -1, "ServerError");
-    duk_remove(ctx, -2);
-    duk::push(ctx, ex.code().value());
-    duk::push(ctx, ex.code().message());
-    duk_new(ctx, 2);
+	duk_get_global_string(ctx, "Irccd");
+	duk_get_prop_string(ctx, -1, "ServerError");
+	duk_remove(ctx, -2);
+	duk::push(ctx, ex.code().value());
+	duk::push(ctx, ex.code().message());
+	duk_new(ctx, 2);
 
-    (void)duk_throw(ctx);
+	(void)duk_throw(ctx);
 }
 
 } // !duk
--- a/libirccd-js/irccd/js/server_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/server_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,15 +36,15 @@
  */
 class server_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 namespace duk {
@@ -56,23 +56,23 @@
  */
 template <>
 struct type_traits<std::shared_ptr<server>> {
-    /**
-     * Push a server.
-     *
-     * \pre server != nullptr
-     * \param ctx the context
-     * \param server the server
-     */
-    static void push(duk_context* ctx, std::shared_ptr<server> server);
+	/**
+	 * Push a server.
+	 *
+	 * \pre server != nullptr
+	 * \param ctx the context
+	 * \param server the server
+	 */
+	static void push(duk_context* ctx, std::shared_ptr<server> server);
 
-    /**
-     * Require a server. Raise a Javascript error if not a Server.
-     *
-     * \param ctx the context
-     * \param index the index
-     * \return the server
-     */
-    static auto require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<server>;
+	/**
+	 * Require a server. Raise a Javascript error if not a Server.
+	 *
+	 * \param ctx the context
+	 * \param index the index
+	 * \return the server
+	 */
+	static auto require(duk_context* ctx, duk_idx_t index) -> std::shared_ptr<server>;
 };
 
 /**
@@ -80,13 +80,13 @@
  */
 template <>
 struct type_traits<server_error> {
-    /**
-     * Raise a server_error.
-     *
-     * \param ctx the context
-     * \param error the error
-     */
-    static void raise(duk_context* ctx, const server_error& error);
+	/**
+	 * Raise a server_error.
+	 *
+	 * \param ctx the context
+	 * \param error the error
+	 */
+	static void raise(duk_context* ctx, const server_error& error);
 };
 
 } // !duk
--- a/libirccd-js/irccd/js/system_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/system_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -42,15 +42,15 @@
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_ret_t
 {
-    try {
-        return handler();
-    } catch (const std::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler();
+	} catch (const std::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -72,9 +72,9 @@
  */
 auto System_env(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, sys::env(duk::get<std::string>(ctx, 0)));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, sys::env(duk::get<std::string>(ctx, 0)));
+	});
 }
 
 // }}}
@@ -94,9 +94,9 @@
  */
 auto System_exec(duk_context* ctx) -> duk_ret_t
 {
-    std::system(duk_require_string(ctx, 0));
+	std::system(duk_require_string(ctx, 0));
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -116,9 +116,9 @@
  */
 auto System_home(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, sys::home());
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, sys::home());
+	});
 }
 
 // }}}
@@ -138,9 +138,9 @@
  */
 auto System_name(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, sys::name());
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, sys::name());
+	});
 }
 
 // }}}
@@ -165,14 +165,14 @@
  */
 auto System_popen(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        auto fp = ::popen(duk_require_string(ctx, 0), duk_require_string(ctx, 1));
+	return wrap(ctx, [&] {
+		auto fp = ::popen(duk_require_string(ctx, 0), duk_require_string(ctx, 1));
 
-        if (fp == nullptr)
-            throw std::system_error(make_error_code(static_cast<std::errc>(errno)));
+		if (fp == nullptr)
+			throw std::system_error(make_error_code(static_cast<std::errc>(errno)));
 
-        return duk::push(ctx, std::make_shared<file>(fp, [] (auto fp) { ::pclose(fp); }));
-    });
+		return duk::push(ctx, std::make_shared<file>(fp, [] (auto fp) { ::pclose(fp); }));
+	});
 }
 
 #endif // !IRCCD_HAVE_POPEN
@@ -194,11 +194,11 @@
  */
 auto System_sleep(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        std::this_thread::sleep_for(std::chrono::seconds(duk_get_int(ctx, 0)));
+	return wrap(ctx, [&] {
+		std::this_thread::sleep_for(std::chrono::seconds(duk_get_int(ctx, 0)));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -218,9 +218,9 @@
  */
 auto System_ticks(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push<unsigned>(ctx, sys::ticks());
-    });
+	return wrap(ctx, [&] {
+		return duk::push<unsigned>(ctx, sys::ticks());
+	});
 }
 
 // }}}
@@ -240,11 +240,11 @@
  */
 auto System_usleep(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        std::this_thread::sleep_for(std::chrono::microseconds(duk_get_int(ctx, 0)));
+	return wrap(ctx, [&] {
+		std::this_thread::sleep_for(std::chrono::microseconds(duk_get_int(ctx, 0)));
 
-        return 0;
-    });
+		return 0;
+	});
 }
 
 // }}}
@@ -264,9 +264,9 @@
  */
 auto System_uptime(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push<unsigned>(ctx, sys::uptime());
-    });
+	return wrap(ctx, [&] {
+		return duk::push<unsigned>(ctx, sys::uptime());
+	});
 }
 
 // }}}
@@ -286,45 +286,45 @@
  */
 auto System_version(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, sys::version());
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, sys::version());
+	});
 }
 
 // }}}
 
 const duk_function_list_entry functions[] = {
-    { "env",        System_env,     1 },
-    { "exec",       System_exec,    1 },
-    { "home",       System_home,    0 },
-    { "name",       System_name,    0 },
+	{ "env",        System_env,     1 },
+	{ "exec",       System_exec,    1 },
+	{ "home",       System_home,    0 },
+	{ "name",       System_name,    0 },
 #if defined(IRCCD_HAVE_POPEN)
-    { "popen",      System_popen,   2 },
+	{ "popen",      System_popen,   2 },
 #endif
-    { "sleep",      System_sleep,   1 },
-    { "ticks",      System_ticks,   0 },
-    { "uptime",     System_uptime,  0 },
-    { "usleep",     System_usleep,  1 },
-    { "version",    System_version, 0 },
-    { nullptr,      nullptr,        0 }
+	{ "sleep",      System_sleep,   1 },
+	{ "ticks",      System_ticks,   0 },
+	{ "uptime",     System_uptime,  0 },
+	{ "usleep",     System_usleep,  1 },
+	{ "version",    System_version, 0 },
+	{ nullptr,      nullptr,        0 }
 };
 
 } // !namespace
 
 auto system_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.System";
+	return "Irccd.System";
 }
 
 void system_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_put_prop_string(plugin->get_context(), -2, "System");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_put_prop_string(plugin->get_context(), -2, "System");
+	duk_pop(plugin->get_context());
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/system_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/system_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class system_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/timer_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/timer_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -40,95 +40,95 @@
 
 class timer : public std::enable_shared_from_this<timer> {
 public:
-    enum class type {
-        single,
-        repeat
-    };
+	enum class type {
+		single,
+		repeat
+	};
 
 private:
-    boost::asio::deadline_timer handle_;
-    js_plugin& plugin_;
+	boost::asio::deadline_timer handle_;
+	js_plugin& plugin_;
 
-    std::string key_;
-    type type_;
-    int delay_;
+	std::string key_;
+	type type_;
+	int delay_;
 
-    bool is_running_{false};
-    bool is_waiting_{false};
+	bool is_running_{false};
+	bool is_waiting_{false};
 
-    void handle();
+	void handle();
 
 public:
-    timer(boost::asio::io_service&, js_plugin&, type, int);
+	timer(boost::asio::io_service&, js_plugin&, type, int);
 
-    auto key() const noexcept -> const std::string&;
+	auto key() const noexcept -> const std::string&;
 
-    void start();
+	void start();
 
-    void stop();
+	void stop();
 };
 
 void timer::handle()
 {
-    duk::stack_guard sa(plugin_.get_context());
+	duk::stack_guard sa(plugin_.get_context());
 
-    duk_push_global_stash(plugin_.get_context());
-    duk_get_prop_string(plugin_.get_context(), -1, table.data());
-    duk_remove(plugin_.get_context(), -2);
-    duk_get_prop_string(plugin_.get_context(), -1, key_.c_str());
-    duk_remove(plugin_.get_context(), -2);
+	duk_push_global_stash(plugin_.get_context());
+	duk_get_prop_string(plugin_.get_context(), -1, table.data());
+	duk_remove(plugin_.get_context(), -2);
+	duk_get_prop_string(plugin_.get_context(), -1, key_.c_str());
+	duk_remove(plugin_.get_context(), -2);
 
-    if (duk_pcall(plugin_.get_context(), 0)) {
-        auto& log = duk::type_traits<irccd>::self(plugin_.get_context()).get_log();
+	if (duk_pcall(plugin_.get_context(), 0)) {
+		auto& log = duk::type_traits<irccd>::self(plugin_.get_context()).get_log();
 
-        log.warning(static_cast<const plugin&>(plugin_)) << "timer error:" << std::endl;
-        log.warning(static_cast<const plugin&>(plugin_)) << "  " << duk::get_stack(plugin_.get_context(), -1).what() << std::endl;
-    } else
-        duk_pop(plugin_.get_context());
+		log.warning(static_cast<const plugin&>(plugin_)) << "timer error:" << std::endl;
+		log.warning(static_cast<const plugin&>(plugin_)) << "  " << duk::get_stack(plugin_.get_context(), -1).what() << std::endl;
+	} else
+		duk_pop(plugin_.get_context());
 }
 
 timer::timer(boost::asio::io_service& service, js_plugin& plugin, type type, int delay)
-    : handle_(service)
-    , plugin_(plugin)
-    , type_(type)
-    , delay_(delay)
+	: handle_(service)
+	, plugin_(plugin)
+	, type_(type)
+	, delay_(delay)
 {
 }
 
 auto timer::key() const noexcept -> const std::string&
 {
-    return key_;
+	return key_;
 }
 
 void timer::start()
 {
-    if (is_waiting_)
-        return;
+	if (is_waiting_)
+		return;
 
-    is_running_ = is_waiting_ = true;
+	is_running_ = is_waiting_ = true;
 
-    handle_.expires_from_now(boost::posix_time::milliseconds(delay_));
-    handle_.async_wait([this] (auto code) {
-        is_waiting_ = false;
+	handle_.expires_from_now(boost::posix_time::milliseconds(delay_));
+	handle_.async_wait([this] (auto code) {
+		is_waiting_ = false;
 
-        if (code) {
-            is_running_ = false;
-            return;
-        }
+		if (code) {
+			is_running_ = false;
+			return;
+		}
 
-        handle();
+		handle();
 
-        if (is_running_ && type_ == type::repeat)
-            start();
-    });
+		if (is_running_ && type_ == type::repeat)
+			start();
+	});
 }
 
 void timer::stop()
 {
-    if (is_running_) {
-        handle_.cancel();
-        is_running_ = false;
-    }
+	if (is_running_) {
+		handle_.cancel();
+		is_running_ = false;
+	}
 }
 
 // }}}
@@ -137,17 +137,17 @@
 
 auto self(duk_context* ctx) -> timer*
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    duk_push_this(ctx);
-    duk_get_prop_string(ctx, -1, signature.data());
-    auto ptr = duk_to_pointer(ctx, -1);
-    duk_pop_2(ctx);
+	duk_push_this(ctx);
+	duk_get_prop_string(ctx, -1, signature.data());
+	auto ptr = duk_to_pointer(ctx, -1);
+	duk_pop_2(ctx);
 
-    if (!ptr)
-        duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Timer object");
+	if (!ptr)
+		duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Timer object");
 
-    return static_cast<timer*>(ptr);
+	return static_cast<timer*>(ptr);
 }
 
 // }}}
@@ -162,9 +162,9 @@
  */
 auto Timer_prototype_start(duk_context* ctx) -> duk_ret_t
 {
-    self(ctx)->start();
+	self(ctx)->start();
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -179,9 +179,9 @@
  */
 auto Timer_prototype_stop(duk_context* ctx) -> duk_ret_t
 {
-    self(ctx)->stop();
+	self(ctx)->stop();
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -196,23 +196,23 @@
  */
 auto Timer_destructor(duk_context* ctx) -> duk_ret_t
 {
-    duk::stack_guard sa(ctx);
+	duk::stack_guard sa(ctx);
 
-    // Get timer from this.
-    duk_get_prop_string(ctx, 0, signature.data());
-    auto ptr = static_cast<timer*>(duk_to_pointer(ctx, -1));
-    duk_pop(ctx);
+	// Get timer from this.
+	duk_get_prop_string(ctx, 0, signature.data());
+	auto ptr = static_cast<timer*>(duk_to_pointer(ctx, -1));
+	duk_pop(ctx);
 
-    // Remove callback from timer table.
-    duk_push_global_stash(ctx);
-    duk_get_prop_string(ctx, -1, table.data());
-    duk_remove(ctx, -2);
-    duk_del_prop_string(ctx, -1, ptr->key().c_str());
-    duk_pop(ctx);
+	// Remove callback from timer table.
+	duk_push_global_stash(ctx);
+	duk_get_prop_string(ctx, -1, table.data());
+	duk_remove(ctx, -2);
+	duk_del_prop_string(ctx, -1, ptr->key().c_str());
+	duk_pop(ctx);
 
-    delete ptr;
+	delete ptr;
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -232,83 +232,83 @@
  */
 auto Timer_constructor(duk_context* ctx) -> duk_ret_t
 {
-    if (!duk_is_constructor_call(ctx))
-        return 0;
+	if (!duk_is_constructor_call(ctx))
+		return 0;
 
-    try {
-        // Check parameters.
-        const auto type = duk_require_int(ctx, 0);
-        const auto delay = duk_require_int(ctx, 1);
+	try {
+		// Check parameters.
+		const auto type = duk_require_int(ctx, 0);
+		const auto delay = duk_require_int(ctx, 1);
 
-        if (type < static_cast<int>(timer::type::single) || type > static_cast<int>(timer::type::repeat))
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid timer type");
-        if (delay < 0)
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "negative delay given");
-        if (!duk_is_callable(ctx, 2))
-            duk_error(ctx, DUK_ERR_TYPE_ERROR, "missing callback function");
+		if (type < static_cast<int>(timer::type::single) || type > static_cast<int>(timer::type::repeat))
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "invalid timer type");
+		if (delay < 0)
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "negative delay given");
+		if (!duk_is_callable(ctx, 2))
+			duk_error(ctx, DUK_ERR_TYPE_ERROR, "missing callback function");
 
-        auto& plugin = duk::type_traits<js_plugin>::self(ctx);
-        auto& daemon = duk::type_traits<irccd>::self(ctx);
-        auto object = new timer(daemon.get_service(), plugin, static_cast<timer::type>(type), delay);
+		auto& plugin = duk::type_traits<js_plugin>::self(ctx);
+		auto& daemon = duk::type_traits<irccd>::self(ctx);
+		auto object = new timer(daemon.get_service(), plugin, static_cast<timer::type>(type), delay);
 
-        duk_push_this(ctx);
-        duk_push_pointer(ctx, object);
-        duk_put_prop_string(ctx, -2, signature.data());
-        duk_push_c_function(ctx, Timer_destructor, 1);
-        duk_set_finalizer(ctx, -2);
-        duk_pop(ctx);
+		duk_push_this(ctx);
+		duk_push_pointer(ctx, object);
+		duk_put_prop_string(ctx, -2, signature.data());
+		duk_push_c_function(ctx, Timer_destructor, 1);
+		duk_set_finalizer(ctx, -2);
+		duk_pop(ctx);
 
-        // Store the function in a table to be called later.
-        duk_push_global_stash(ctx);
-        duk_get_prop_string(ctx, -1, table.data());
-        duk_remove(ctx, -2);
-        duk_dup(ctx, 2);
-        duk_put_prop_string(ctx, -2, object->key().c_str());
-        duk_pop(ctx);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+		// Store the function in a table to be called later.
+		duk_push_global_stash(ctx);
+		duk_get_prop_string(ctx, -1, table.data());
+		duk_remove(ctx, -2);
+		duk_dup(ctx, 2);
+		duk_put_prop_string(ctx, -2, object->key().c_str());
+		duk_pop(ctx);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
 
 const duk_function_list_entry methods[] = {
-    { "start",  Timer_prototype_start,  0                   },
-    { "stop",   Timer_prototype_stop,   0                   },
-    { nullptr,  nullptr,                0                   }
+	{ "start",      Timer_prototype_start,  0               },
+	{ "stop",       Timer_prototype_stop,   0               },
+	{ nullptr,      nullptr,                0               }
 };
 
 const duk_number_list_entry constants[] = {
-    { "Single",     static_cast<int>(timer::type::single)   },
-    { "Repeat",     static_cast<int>(timer::type::repeat)   },
-    { nullptr,      0                                       }
+	{ "Single",     static_cast<int>(timer::type::single)   },
+	{ "Repeat",     static_cast<int>(timer::type::repeat)   },
+	{ nullptr,      0                                       }
 };
 
 } // !namespace
 
 auto timer_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Timer";
+	return "Irccd.Timer";
 }
 
 void timer_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_c_function(plugin->get_context(), Timer_constructor, 3);
-    duk_put_number_list(plugin->get_context(), -1, constants);
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, methods);
-    duk_put_prop_string(plugin->get_context(), -2, "prototype");
-    duk_put_prop_string(plugin->get_context(), -2, "Timer");
-    duk_pop(plugin->get_context());
-    duk_push_global_stash(plugin->get_context());
-    duk_push_object(plugin->get_context());
-    duk_put_prop_string(plugin->get_context(), -2, table.data());
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_c_function(plugin->get_context(), Timer_constructor, 3);
+	duk_put_number_list(plugin->get_context(), -1, constants);
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, methods);
+	duk_put_prop_string(plugin->get_context(), -2, "prototype");
+	duk_put_prop_string(plugin->get_context(), -2, "Timer");
+	duk_pop(plugin->get_context());
+	duk_push_global_stash(plugin->get_context());
+	duk_push_object(plugin->get_context());
+	duk_put_prop_string(plugin->get_context(), -2, table.data());
+	duk_pop(plugin->get_context());
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/timer_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/timer_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class timer_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/unicode.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/unicode.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -23,34 +23,32 @@
  * needs.
  */
 
-namespace irccd {
-
-namespace unicode {
+namespace irccd::unicode {
 
 #define nelem(x) (sizeof (x) / sizeof ((x)[0]))
 
 namespace {
 
-const char32_t *rbsearch(char32_t c, const char32_t *t, int n, int ne) noexcept
+auto search(char32_t c, const char32_t* t, int n, int ne) noexcept -> const char32_t*
 {
-   const char32_t *p;
-   int m;
+	const char32_t* p;
+	int m;
 
-   while (n > 1) {
-       m = n >> 1;
-       p = t + m * ne;
+	while (n > 1) {
+		m = n >> 1;
+		p = t + m * ne;
 
-       if (c >= p[0]) {
-           t = p;
-           n = n - m;
-       } else
-           n = m;
-   }
+		if (c >= p[0]) {
+			t = p;
+			n = n - m;
+		} else
+			n = m;
+	}
 
-   if (n && c >= t[0])
-       return t;
+	if (n && c >= t[0])
+		return t;
 
-   return nullptr;
+	return nullptr;
 }
 
 } // !namespace
@@ -58,533 +56,533 @@
 namespace {
 
 const char32_t isspacer[] = {
-    0x0009, 0x000d,
-    0x0020, 0x0020,
-    0x0085, 0x0085,
-    0x00a0, 0x00a0,
-    0x1680, 0x1680,
-    0x2000, 0x200a,
-    0x2028, 0x2029,
-    0x202f, 0x202f,
-    0x205f, 0x205f,
-    0x3000, 0x3000,
-    0xfeff, 0xfeff,
+	0x0009, 0x000d,
+	0x0020, 0x0020,
+	0x0085, 0x0085,
+	0x00a0, 0x00a0,
+	0x1680, 0x1680,
+	0x2000, 0x200a,
+	0x2028, 0x2029,
+	0x202f, 0x202f,
+	0x205f, 0x205f,
+	0x3000, 0x3000,
+	0xfeff, 0xfeff,
 };
 
 } // !namespace
 
-bool isspace(char32_t c) noexcept
+auto isspace(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, isspacer, nelem (isspacer)/2, 2);
+	p = search(c, isspacer, nelem (isspacer) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
-   return false;
+	return false;
 }
 
 namespace {
 
 const char32_t isdigitr[] = {
-    0x0030, 0x0039,
-    0x0660, 0x0669,
-    0x06f0, 0x06f9,
-    0x07c0, 0x07c9,
-    0x0966, 0x096f,
-    0x09e6, 0x09ef,
-    0x0a66, 0x0a6f,
-    0x0ae6, 0x0aef,
-    0x0b66, 0x0b6f,
-    0x0be6, 0x0bef,
-    0x0c66, 0x0c6f,
-    0x0ce6, 0x0cef,
-    0x0d66, 0x0d6f,
-    0x0de6, 0x0def,
-    0x0e50, 0x0e59,
-    0x0ed0, 0x0ed9,
-    0x0f20, 0x0f29,
-    0x1040, 0x1049,
-    0x1090, 0x1099,
-    0x17e0, 0x17e9,
-    0x1810, 0x1819,
-    0x1946, 0x194f,
-    0x19d0, 0x19d9,
-    0x1a80, 0x1a89,
-    0x1a90, 0x1a99,
-    0x1b50, 0x1b59,
-    0x1bb0, 0x1bb9,
-    0x1c40, 0x1c49,
-    0x1c50, 0x1c59,
-    0xa620, 0xa629,
-    0xa8d0, 0xa8d9,
-    0xa900, 0xa909,
-    0xa9d0, 0xa9d9,
-    0xa9f0, 0xa9f9,
-    0xaa50, 0xaa59,
-    0xabf0, 0xabf9,
-    0xff10, 0xff19,
-    0x104a0, 0x104a9,
-    0x11066, 0x1106f,
-    0x110f0, 0x110f9,
-    0x11136, 0x1113f,
-    0x111d0, 0x111d9,
-    0x112f0, 0x112f9,
-    0x114d0, 0x114d9,
-    0x11650, 0x11659,
-    0x116c0, 0x116c9,
-    0x118e0, 0x118e9,
-    0x16a60, 0x16a69,
-    0x16b50, 0x16b59,
-    0x1d7ce, 0x1d7ff,
+	0x0030, 0x0039,
+	0x0660, 0x0669,
+	0x06f0, 0x06f9,
+	0x07c0, 0x07c9,
+	0x0966, 0x096f,
+	0x09e6, 0x09ef,
+	0x0a66, 0x0a6f,
+	0x0ae6, 0x0aef,
+	0x0b66, 0x0b6f,
+	0x0be6, 0x0bef,
+	0x0c66, 0x0c6f,
+	0x0ce6, 0x0cef,
+	0x0d66, 0x0d6f,
+	0x0de6, 0x0def,
+	0x0e50, 0x0e59,
+	0x0ed0, 0x0ed9,
+	0x0f20, 0x0f29,
+	0x1040, 0x1049,
+	0x1090, 0x1099,
+	0x17e0, 0x17e9,
+	0x1810, 0x1819,
+	0x1946, 0x194f,
+	0x19d0, 0x19d9,
+	0x1a80, 0x1a89,
+	0x1a90, 0x1a99,
+	0x1b50, 0x1b59,
+	0x1bb0, 0x1bb9,
+	0x1c40, 0x1c49,
+	0x1c50, 0x1c59,
+	0xa620, 0xa629,
+	0xa8d0, 0xa8d9,
+	0xa900, 0xa909,
+	0xa9d0, 0xa9d9,
+	0xa9f0, 0xa9f9,
+	0xaa50, 0xaa59,
+	0xabf0, 0xabf9,
+	0xff10, 0xff19,
+	0x104a0, 0x104a9,
+	0x11066, 0x1106f,
+	0x110f0, 0x110f9,
+	0x11136, 0x1113f,
+	0x111d0, 0x111d9,
+	0x112f0, 0x112f9,
+	0x114d0, 0x114d9,
+	0x11650, 0x11659,
+	0x116c0, 0x116c9,
+	0x118e0, 0x118e9,
+	0x16a60, 0x16a69,
+	0x16b50, 0x16b59,
+	0x1d7ce, 0x1d7ff,
 };
 
 } // !namespace
 
-bool isdigit(char32_t c) noexcept
+auto isdigit(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, isdigitr, nelem (isdigitr)/2, 2);
+	p = search(c, isdigitr, nelem (isdigitr) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
-   return false;
+	return false;
 }
 
 namespace {
 
 const char32_t isalphar[] = {
-    0x0041, 0x005a,
-    0x0061, 0x007a,
-    0x00c0, 0x00d6,
-    0x00d8, 0x00f6,
-    0x00f8, 0x02c1,
-    0x02c6, 0x02d1,
-    0x02e0, 0x02e4,
-    0x0370, 0x0374,
-    0x0376, 0x0377,
-    0x037a, 0x037d,
-    0x0388, 0x038a,
-    0x038e, 0x03a1,
-    0x03a3, 0x03f5,
-    0x03f7, 0x0481,
-    0x048a, 0x052f,
-    0x0531, 0x0556,
-    0x0561, 0x0587,
-    0x05d0, 0x05ea,
-    0x05f0, 0x05f2,
-    0x0620, 0x064a,
-    0x066e, 0x066f,
-    0x0671, 0x06d3,
-    0x06e5, 0x06e6,
-    0x06ee, 0x06ef,
-    0x06fa, 0x06fc,
-    0x0712, 0x072f,
-    0x074d, 0x07a5,
-    0x07ca, 0x07ea,
-    0x07f4, 0x07f5,
-    0x0800, 0x0815,
-    0x0840, 0x0858,
-    0x08a0, 0x08b2,
-    0x0904, 0x0939,
-    0x0958, 0x0961,
-    0x0971, 0x0980,
-    0x0985, 0x098c,
-    0x098f, 0x0990,
-    0x0993, 0x09a8,
-    0x09aa, 0x09b0,
-    0x09b6, 0x09b9,
-    0x09dc, 0x09dd,
-    0x09df, 0x09e1,
-    0x09f0, 0x09f1,
-    0x0a05, 0x0a0a,
-    0x0a0f, 0x0a10,
-    0x0a13, 0x0a28,
-    0x0a2a, 0x0a30,
-    0x0a32, 0x0a33,
-    0x0a35, 0x0a36,
-    0x0a38, 0x0a39,
-    0x0a59, 0x0a5c,
-    0x0a72, 0x0a74,
-    0x0a85, 0x0a8d,
-    0x0a8f, 0x0a91,
-    0x0a93, 0x0aa8,
-    0x0aaa, 0x0ab0,
-    0x0ab2, 0x0ab3,
-    0x0ab5, 0x0ab9,
-    0x0ae0, 0x0ae1,
-    0x0b05, 0x0b0c,
-    0x0b0f, 0x0b10,
-    0x0b13, 0x0b28,
-    0x0b2a, 0x0b30,
-    0x0b32, 0x0b33,
-    0x0b35, 0x0b39,
-    0x0b5c, 0x0b5d,
-    0x0b5f, 0x0b61,
-    0x0b85, 0x0b8a,
-    0x0b8e, 0x0b90,
-    0x0b92, 0x0b95,
-    0x0b99, 0x0b9a,
-    0x0b9e, 0x0b9f,
-    0x0ba3, 0x0ba4,
-    0x0ba8, 0x0baa,
-    0x0bae, 0x0bb9,
-    0x0c05, 0x0c0c,
-    0x0c0e, 0x0c10,
-    0x0c12, 0x0c28,
-    0x0c2a, 0x0c39,
-    0x0c58, 0x0c59,
-    0x0c60, 0x0c61,
-    0x0c85, 0x0c8c,
-    0x0c8e, 0x0c90,
-    0x0c92, 0x0ca8,
-    0x0caa, 0x0cb3,
-    0x0cb5, 0x0cb9,
-    0x0ce0, 0x0ce1,
-    0x0cf1, 0x0cf2,
-    0x0d05, 0x0d0c,
-    0x0d0e, 0x0d10,
-    0x0d12, 0x0d3a,
-    0x0d60, 0x0d61,
-    0x0d7a, 0x0d7f,
-    0x0d85, 0x0d96,
-    0x0d9a, 0x0db1,
-    0x0db3, 0x0dbb,
-    0x0dc0, 0x0dc6,
-    0x0e01, 0x0e30,
-    0x0e32, 0x0e33,
-    0x0e40, 0x0e46,
-    0x0e81, 0x0e82,
-    0x0e87, 0x0e88,
-    0x0e94, 0x0e97,
-    0x0e99, 0x0e9f,
-    0x0ea1, 0x0ea3,
-    0x0eaa, 0x0eab,
-    0x0ead, 0x0eb0,
-    0x0eb2, 0x0eb3,
-    0x0ec0, 0x0ec4,
-    0x0edc, 0x0edf,
-    0x0f40, 0x0f47,
-    0x0f49, 0x0f6c,
-    0x0f88, 0x0f8c,
-    0x1000, 0x102a,
-    0x1050, 0x1055,
-    0x105a, 0x105d,
-    0x1065, 0x1066,
-    0x106e, 0x1070,
-    0x1075, 0x1081,
-    0x10a0, 0x10c5,
-    0x10d0, 0x10fa,
-    0x10fc, 0x1248,
-    0x124a, 0x124d,
-    0x1250, 0x1256,
-    0x125a, 0x125d,
-    0x1260, 0x1288,
-    0x128a, 0x128d,
-    0x1290, 0x12b0,
-    0x12b2, 0x12b5,
-    0x12b8, 0x12be,
-    0x12c2, 0x12c5,
-    0x12c8, 0x12d6,
-    0x12d8, 0x1310,
-    0x1312, 0x1315,
-    0x1318, 0x135a,
-    0x1380, 0x138f,
-    0x13a0, 0x13f4,
-    0x1401, 0x166c,
-    0x166f, 0x167f,
-    0x1681, 0x169a,
-    0x16a0, 0x16ea,
-    0x16f1, 0x16f8,
-    0x1700, 0x170c,
-    0x170e, 0x1711,
-    0x1720, 0x1731,
-    0x1740, 0x1751,
-    0x1760, 0x176c,
-    0x176e, 0x1770,
-    0x1780, 0x17b3,
-    0x1820, 0x1877,
-    0x1880, 0x18a8,
-    0x18b0, 0x18f5,
-    0x1900, 0x191e,
-    0x1950, 0x196d,
-    0x1970, 0x1974,
-    0x1980, 0x19ab,
-    0x19c1, 0x19c7,
-    0x1a00, 0x1a16,
-    0x1a20, 0x1a54,
-    0x1b05, 0x1b33,
-    0x1b45, 0x1b4b,
-    0x1b83, 0x1ba0,
-    0x1bae, 0x1baf,
-    0x1bba, 0x1be5,
-    0x1c00, 0x1c23,
-    0x1c4d, 0x1c4f,
-    0x1c5a, 0x1c7d,
-    0x1ce9, 0x1cec,
-    0x1cee, 0x1cf1,
-    0x1cf5, 0x1cf6,
-    0x1d00, 0x1dbf,
-    0x1e00, 0x1f15,
-    0x1f18, 0x1f1d,
-    0x1f20, 0x1f45,
-    0x1f48, 0x1f4d,
-    0x1f50, 0x1f57,
-    0x1f5f, 0x1f7d,
-    0x1f80, 0x1fb4,
-    0x1fb6, 0x1fbc,
-    0x1fc2, 0x1fc4,
-    0x1fc6, 0x1fcc,
-    0x1fd0, 0x1fd3,
-    0x1fd6, 0x1fdb,
-    0x1fe0, 0x1fec,
-    0x1ff2, 0x1ff4,
-    0x1ff6, 0x1ffc,
-    0x2090, 0x209c,
-    0x210a, 0x2113,
-    0x2119, 0x211d,
-    0x212a, 0x212d,
-    0x212f, 0x2139,
-    0x213c, 0x213f,
-    0x2145, 0x2149,
-    0x2183, 0x2184,
-    0x2c00, 0x2c2e,
-    0x2c30, 0x2c5e,
-    0x2c60, 0x2ce4,
-    0x2ceb, 0x2cee,
-    0x2cf2, 0x2cf3,
-    0x2d00, 0x2d25,
-    0x2d30, 0x2d67,
-    0x2d80, 0x2d96,
-    0x2da0, 0x2da6,
-    0x2da8, 0x2dae,
-    0x2db0, 0x2db6,
-    0x2db8, 0x2dbe,
-    0x2dc0, 0x2dc6,
-    0x2dc8, 0x2dce,
-    0x2dd0, 0x2dd6,
-    0x2dd8, 0x2dde,
-    0x3005, 0x3006,
-    0x3031, 0x3035,
-    0x303b, 0x303c,
-    0x3041, 0x3096,
-    0x309d, 0x309f,
-    0x30a1, 0x30fa,
-    0x30fc, 0x30ff,
-    0x3105, 0x312d,
-    0x3131, 0x318e,
-    0x31a0, 0x31ba,
-    0x31f0, 0x31ff,
-    0x3400, 0x4db5,
-    0x4e00, 0x9fcc,
-    0xa000, 0xa48c,
-    0xa4d0, 0xa4fd,
-    0xa500, 0xa60c,
-    0xa610, 0xa61f,
-    0xa62a, 0xa62b,
-    0xa640, 0xa66e,
-    0xa67f, 0xa69d,
-    0xa6a0, 0xa6e5,
-    0xa717, 0xa71f,
-    0xa722, 0xa788,
-    0xa78b, 0xa78e,
-    0xa790, 0xa7ad,
-    0xa7b0, 0xa7b1,
-    0xa7f7, 0xa801,
-    0xa803, 0xa805,
-    0xa807, 0xa80a,
-    0xa80c, 0xa822,
-    0xa840, 0xa873,
-    0xa882, 0xa8b3,
-    0xa8f2, 0xa8f7,
-    0xa90a, 0xa925,
-    0xa930, 0xa946,
-    0xa960, 0xa97c,
-    0xa984, 0xa9b2,
-    0xa9e0, 0xa9e4,
-    0xa9e6, 0xa9ef,
-    0xa9fa, 0xa9fe,
-    0xaa00, 0xaa28,
-    0xaa40, 0xaa42,
-    0xaa44, 0xaa4b,
-    0xaa60, 0xaa76,
-    0xaa7e, 0xaaaf,
-    0xaab5, 0xaab6,
-    0xaab9, 0xaabd,
-    0xaadb, 0xaadd,
-    0xaae0, 0xaaea,
-    0xaaf2, 0xaaf4,
-    0xab01, 0xab06,
-    0xab09, 0xab0e,
-    0xab11, 0xab16,
-    0xab20, 0xab26,
-    0xab28, 0xab2e,
-    0xab30, 0xab5a,
-    0xab5c, 0xab5f,
-    0xab64, 0xab65,
-    0xabc0, 0xabe2,
-    0xac00, 0xd7a3,
-    0xd7b0, 0xd7c6,
-    0xd7cb, 0xd7fb,
-    0xf900, 0xfa6d,
-    0xfa70, 0xfad9,
-    0xfb00, 0xfb06,
-    0xfb13, 0xfb17,
-    0xfb1f, 0xfb28,
-    0xfb2a, 0xfb36,
-    0xfb38, 0xfb3c,
-    0xfb40, 0xfb41,
-    0xfb43, 0xfb44,
-    0xfb46, 0xfbb1,
-    0xfbd3, 0xfd3d,
-    0xfd50, 0xfd8f,
-    0xfd92, 0xfdc7,
-    0xfdf0, 0xfdfb,
-    0xfe70, 0xfe74,
-    0xfe76, 0xfefc,
-    0xff21, 0xff3a,
-    0xff41, 0xff5a,
-    0xff66, 0xffbe,
-    0xffc2, 0xffc7,
-    0xffca, 0xffcf,
-    0xffd2, 0xffd7,
-    0xffda, 0xffdc,
-    0x10000, 0x1000b,
-    0x1000d, 0x10026,
-    0x10028, 0x1003a,
-    0x1003c, 0x1003d,
-    0x1003f, 0x1004d,
-    0x10050, 0x1005d,
-    0x10080, 0x100fa,
-    0x10280, 0x1029c,
-    0x102a0, 0x102d0,
-    0x10300, 0x1031f,
-    0x10330, 0x10340,
-    0x10342, 0x10349,
-    0x10350, 0x10375,
-    0x10380, 0x1039d,
-    0x103a0, 0x103c3,
-    0x103c8, 0x103cf,
-    0x10400, 0x1049d,
-    0x10500, 0x10527,
-    0x10530, 0x10563,
-    0x10600, 0x10736,
-    0x10740, 0x10755,
-    0x10760, 0x10767,
-    0x10800, 0x10805,
-    0x1080a, 0x10835,
-    0x10837, 0x10838,
-    0x1083f, 0x10855,
-    0x10860, 0x10876,
-    0x10880, 0x1089e,
-    0x10900, 0x10915,
-    0x10920, 0x10939,
-    0x10980, 0x109b7,
-    0x109be, 0x109bf,
-    0x10a10, 0x10a13,
-    0x10a15, 0x10a17,
-    0x10a19, 0x10a33,
-    0x10a60, 0x10a7c,
-    0x10a80, 0x10a9c,
-    0x10ac0, 0x10ac7,
-    0x10ac9, 0x10ae4,
-    0x10b00, 0x10b35,
-    0x10b40, 0x10b55,
-    0x10b60, 0x10b72,
-    0x10b80, 0x10b91,
-    0x10c00, 0x10c48,
-    0x11003, 0x11037,
-    0x11083, 0x110af,
-    0x110d0, 0x110e8,
-    0x11103, 0x11126,
-    0x11150, 0x11172,
-    0x11183, 0x111b2,
-    0x111c1, 0x111c4,
-    0x11200, 0x11211,
-    0x11213, 0x1122b,
-    0x112b0, 0x112de,
-    0x11305, 0x1130c,
-    0x1130f, 0x11310,
-    0x11313, 0x11328,
-    0x1132a, 0x11330,
-    0x11332, 0x11333,
-    0x11335, 0x11339,
-    0x1135d, 0x11361,
-    0x11480, 0x114af,
-    0x114c4, 0x114c5,
-    0x11580, 0x115ae,
-    0x11600, 0x1162f,
-    0x11680, 0x116aa,
-    0x118a0, 0x118df,
-    0x11ac0, 0x11af8,
-    0x12000, 0x12398,
-    0x13000, 0x1342e,
-    0x16800, 0x16a38,
-    0x16a40, 0x16a5e,
-    0x16ad0, 0x16aed,
-    0x16b00, 0x16b2f,
-    0x16b40, 0x16b43,
-    0x16b63, 0x16b77,
-    0x16b7d, 0x16b8f,
-    0x16f00, 0x16f44,
-    0x16f93, 0x16f9f,
-    0x1b000, 0x1b001,
-    0x1bc00, 0x1bc6a,
-    0x1bc70, 0x1bc7c,
-    0x1bc80, 0x1bc88,
-    0x1bc90, 0x1bc99,
-    0x1d400, 0x1d454,
-    0x1d456, 0x1d49c,
-    0x1d49e, 0x1d49f,
-    0x1d4a5, 0x1d4a6,
-    0x1d4a9, 0x1d4ac,
-    0x1d4ae, 0x1d4b9,
-    0x1d4bd, 0x1d4c3,
-    0x1d4c5, 0x1d505,
-    0x1d507, 0x1d50a,
-    0x1d50d, 0x1d514,
-    0x1d516, 0x1d51c,
-    0x1d51e, 0x1d539,
-    0x1d53b, 0x1d53e,
-    0x1d540, 0x1d544,
-    0x1d54a, 0x1d550,
-    0x1d552, 0x1d6a5,
-    0x1d6a8, 0x1d6c0,
-    0x1d6c2, 0x1d6da,
-    0x1d6dc, 0x1d6fa,
-    0x1d6fc, 0x1d714,
-    0x1d716, 0x1d734,
-    0x1d736, 0x1d74e,
-    0x1d750, 0x1d76e,
-    0x1d770, 0x1d788,
-    0x1d78a, 0x1d7a8,
-    0x1d7aa, 0x1d7c2,
-    0x1d7c4, 0x1d7cb,
-    0x1e800, 0x1e8c4,
-    0x1ee00, 0x1ee03,
-    0x1ee05, 0x1ee1f,
-    0x1ee21, 0x1ee22,
-    0x1ee29, 0x1ee32,
-    0x1ee34, 0x1ee37,
-    0x1ee4d, 0x1ee4f,
-    0x1ee51, 0x1ee52,
-    0x1ee61, 0x1ee62,
-    0x1ee67, 0x1ee6a,
-    0x1ee6c, 0x1ee72,
-    0x1ee74, 0x1ee77,
-    0x1ee79, 0x1ee7c,
-    0x1ee80, 0x1ee89,
-    0x1ee8b, 0x1ee9b,
-    0x1eea1, 0x1eea3,
-    0x1eea5, 0x1eea9,
-    0x1eeab, 0x1eebb,
-    0x20000, 0x2a6d6,
-    0x2a700, 0x2b734,
-    0x2b740, 0x2b81d,
-    0x2f800, 0x2fa1d,
+	0x0041, 0x005a,
+	0x0061, 0x007a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00f6,
+	0x00f8, 0x02c1,
+	0x02c6, 0x02d1,
+	0x02e0, 0x02e4,
+	0x0370, 0x0374,
+	0x0376, 0x0377,
+	0x037a, 0x037d,
+	0x0388, 0x038a,
+	0x038e, 0x03a1,
+	0x03a3, 0x03f5,
+	0x03f7, 0x0481,
+	0x048a, 0x052f,
+	0x0531, 0x0556,
+	0x0561, 0x0587,
+	0x05d0, 0x05ea,
+	0x05f0, 0x05f2,
+	0x0620, 0x064a,
+	0x066e, 0x066f,
+	0x0671, 0x06d3,
+	0x06e5, 0x06e6,
+	0x06ee, 0x06ef,
+	0x06fa, 0x06fc,
+	0x0712, 0x072f,
+	0x074d, 0x07a5,
+	0x07ca, 0x07ea,
+	0x07f4, 0x07f5,
+	0x0800, 0x0815,
+	0x0840, 0x0858,
+	0x08a0, 0x08b2,
+	0x0904, 0x0939,
+	0x0958, 0x0961,
+	0x0971, 0x0980,
+	0x0985, 0x098c,
+	0x098f, 0x0990,
+	0x0993, 0x09a8,
+	0x09aa, 0x09b0,
+	0x09b6, 0x09b9,
+	0x09dc, 0x09dd,
+	0x09df, 0x09e1,
+	0x09f0, 0x09f1,
+	0x0a05, 0x0a0a,
+	0x0a0f, 0x0a10,
+	0x0a13, 0x0a28,
+	0x0a2a, 0x0a30,
+	0x0a32, 0x0a33,
+	0x0a35, 0x0a36,
+	0x0a38, 0x0a39,
+	0x0a59, 0x0a5c,
+	0x0a72, 0x0a74,
+	0x0a85, 0x0a8d,
+	0x0a8f, 0x0a91,
+	0x0a93, 0x0aa8,
+	0x0aaa, 0x0ab0,
+	0x0ab2, 0x0ab3,
+	0x0ab5, 0x0ab9,
+	0x0ae0, 0x0ae1,
+	0x0b05, 0x0b0c,
+	0x0b0f, 0x0b10,
+	0x0b13, 0x0b28,
+	0x0b2a, 0x0b30,
+	0x0b32, 0x0b33,
+	0x0b35, 0x0b39,
+	0x0b5c, 0x0b5d,
+	0x0b5f, 0x0b61,
+	0x0b85, 0x0b8a,
+	0x0b8e, 0x0b90,
+	0x0b92, 0x0b95,
+	0x0b99, 0x0b9a,
+	0x0b9e, 0x0b9f,
+	0x0ba3, 0x0ba4,
+	0x0ba8, 0x0baa,
+	0x0bae, 0x0bb9,
+	0x0c05, 0x0c0c,
+	0x0c0e, 0x0c10,
+	0x0c12, 0x0c28,
+	0x0c2a, 0x0c39,
+	0x0c58, 0x0c59,
+	0x0c60, 0x0c61,
+	0x0c85, 0x0c8c,
+	0x0c8e, 0x0c90,
+	0x0c92, 0x0ca8,
+	0x0caa, 0x0cb3,
+	0x0cb5, 0x0cb9,
+	0x0ce0, 0x0ce1,
+	0x0cf1, 0x0cf2,
+	0x0d05, 0x0d0c,
+	0x0d0e, 0x0d10,
+	0x0d12, 0x0d3a,
+	0x0d60, 0x0d61,
+	0x0d7a, 0x0d7f,
+	0x0d85, 0x0d96,
+	0x0d9a, 0x0db1,
+	0x0db3, 0x0dbb,
+	0x0dc0, 0x0dc6,
+	0x0e01, 0x0e30,
+	0x0e32, 0x0e33,
+	0x0e40, 0x0e46,
+	0x0e81, 0x0e82,
+	0x0e87, 0x0e88,
+	0x0e94, 0x0e97,
+	0x0e99, 0x0e9f,
+	0x0ea1, 0x0ea3,
+	0x0eaa, 0x0eab,
+	0x0ead, 0x0eb0,
+	0x0eb2, 0x0eb3,
+	0x0ec0, 0x0ec4,
+	0x0edc, 0x0edf,
+	0x0f40, 0x0f47,
+	0x0f49, 0x0f6c,
+	0x0f88, 0x0f8c,
+	0x1000, 0x102a,
+	0x1050, 0x1055,
+	0x105a, 0x105d,
+	0x1065, 0x1066,
+	0x106e, 0x1070,
+	0x1075, 0x1081,
+	0x10a0, 0x10c5,
+	0x10d0, 0x10fa,
+	0x10fc, 0x1248,
+	0x124a, 0x124d,
+	0x1250, 0x1256,
+	0x125a, 0x125d,
+	0x1260, 0x1288,
+	0x128a, 0x128d,
+	0x1290, 0x12b0,
+	0x12b2, 0x12b5,
+	0x12b8, 0x12be,
+	0x12c2, 0x12c5,
+	0x12c8, 0x12d6,
+	0x12d8, 0x1310,
+	0x1312, 0x1315,
+	0x1318, 0x135a,
+	0x1380, 0x138f,
+	0x13a0, 0x13f4,
+	0x1401, 0x166c,
+	0x166f, 0x167f,
+	0x1681, 0x169a,
+	0x16a0, 0x16ea,
+	0x16f1, 0x16f8,
+	0x1700, 0x170c,
+	0x170e, 0x1711,
+	0x1720, 0x1731,
+	0x1740, 0x1751,
+	0x1760, 0x176c,
+	0x176e, 0x1770,
+	0x1780, 0x17b3,
+	0x1820, 0x1877,
+	0x1880, 0x18a8,
+	0x18b0, 0x18f5,
+	0x1900, 0x191e,
+	0x1950, 0x196d,
+	0x1970, 0x1974,
+	0x1980, 0x19ab,
+	0x19c1, 0x19c7,
+	0x1a00, 0x1a16,
+	0x1a20, 0x1a54,
+	0x1b05, 0x1b33,
+	0x1b45, 0x1b4b,
+	0x1b83, 0x1ba0,
+	0x1bae, 0x1baf,
+	0x1bba, 0x1be5,
+	0x1c00, 0x1c23,
+	0x1c4d, 0x1c4f,
+	0x1c5a, 0x1c7d,
+	0x1ce9, 0x1cec,
+	0x1cee, 0x1cf1,
+	0x1cf5, 0x1cf6,
+	0x1d00, 0x1dbf,
+	0x1e00, 0x1f15,
+	0x1f18, 0x1f1d,
+	0x1f20, 0x1f45,
+	0x1f48, 0x1f4d,
+	0x1f50, 0x1f57,
+	0x1f5f, 0x1f7d,
+	0x1f80, 0x1fb4,
+	0x1fb6, 0x1fbc,
+	0x1fc2, 0x1fc4,
+	0x1fc6, 0x1fcc,
+	0x1fd0, 0x1fd3,
+	0x1fd6, 0x1fdb,
+	0x1fe0, 0x1fec,
+	0x1ff2, 0x1ff4,
+	0x1ff6, 0x1ffc,
+	0x2090, 0x209c,
+	0x210a, 0x2113,
+	0x2119, 0x211d,
+	0x212a, 0x212d,
+	0x212f, 0x2139,
+	0x213c, 0x213f,
+	0x2145, 0x2149,
+	0x2183, 0x2184,
+	0x2c00, 0x2c2e,
+	0x2c30, 0x2c5e,
+	0x2c60, 0x2ce4,
+	0x2ceb, 0x2cee,
+	0x2cf2, 0x2cf3,
+	0x2d00, 0x2d25,
+	0x2d30, 0x2d67,
+	0x2d80, 0x2d96,
+	0x2da0, 0x2da6,
+	0x2da8, 0x2dae,
+	0x2db0, 0x2db6,
+	0x2db8, 0x2dbe,
+	0x2dc0, 0x2dc6,
+	0x2dc8, 0x2dce,
+	0x2dd0, 0x2dd6,
+	0x2dd8, 0x2dde,
+	0x3005, 0x3006,
+	0x3031, 0x3035,
+	0x303b, 0x303c,
+	0x3041, 0x3096,
+	0x309d, 0x309f,
+	0x30a1, 0x30fa,
+	0x30fc, 0x30ff,
+	0x3105, 0x312d,
+	0x3131, 0x318e,
+	0x31a0, 0x31ba,
+	0x31f0, 0x31ff,
+	0x3400, 0x4db5,
+	0x4e00, 0x9fcc,
+	0xa000, 0xa48c,
+	0xa4d0, 0xa4fd,
+	0xa500, 0xa60c,
+	0xa610, 0xa61f,
+	0xa62a, 0xa62b,
+	0xa640, 0xa66e,
+	0xa67f, 0xa69d,
+	0xa6a0, 0xa6e5,
+	0xa717, 0xa71f,
+	0xa722, 0xa788,
+	0xa78b, 0xa78e,
+	0xa790, 0xa7ad,
+	0xa7b0, 0xa7b1,
+	0xa7f7, 0xa801,
+	0xa803, 0xa805,
+	0xa807, 0xa80a,
+	0xa80c, 0xa822,
+	0xa840, 0xa873,
+	0xa882, 0xa8b3,
+	0xa8f2, 0xa8f7,
+	0xa90a, 0xa925,
+	0xa930, 0xa946,
+	0xa960, 0xa97c,
+	0xa984, 0xa9b2,
+	0xa9e0, 0xa9e4,
+	0xa9e6, 0xa9ef,
+	0xa9fa, 0xa9fe,
+	0xaa00, 0xaa28,
+	0xaa40, 0xaa42,
+	0xaa44, 0xaa4b,
+	0xaa60, 0xaa76,
+	0xaa7e, 0xaaaf,
+	0xaab5, 0xaab6,
+	0xaab9, 0xaabd,
+	0xaadb, 0xaadd,
+	0xaae0, 0xaaea,
+	0xaaf2, 0xaaf4,
+	0xab01, 0xab06,
+	0xab09, 0xab0e,
+	0xab11, 0xab16,
+	0xab20, 0xab26,
+	0xab28, 0xab2e,
+	0xab30, 0xab5a,
+	0xab5c, 0xab5f,
+	0xab64, 0xab65,
+	0xabc0, 0xabe2,
+	0xac00, 0xd7a3,
+	0xd7b0, 0xd7c6,
+	0xd7cb, 0xd7fb,
+	0xf900, 0xfa6d,
+	0xfa70, 0xfad9,
+	0xfb00, 0xfb06,
+	0xfb13, 0xfb17,
+	0xfb1f, 0xfb28,
+	0xfb2a, 0xfb36,
+	0xfb38, 0xfb3c,
+	0xfb40, 0xfb41,
+	0xfb43, 0xfb44,
+	0xfb46, 0xfbb1,
+	0xfbd3, 0xfd3d,
+	0xfd50, 0xfd8f,
+	0xfd92, 0xfdc7,
+	0xfdf0, 0xfdfb,
+	0xfe70, 0xfe74,
+	0xfe76, 0xfefc,
+	0xff21, 0xff3a,
+	0xff41, 0xff5a,
+	0xff66, 0xffbe,
+	0xffc2, 0xffc7,
+	0xffca, 0xffcf,
+	0xffd2, 0xffd7,
+	0xffda, 0xffdc,
+	0x10000, 0x1000b,
+	0x1000d, 0x10026,
+	0x10028, 0x1003a,
+	0x1003c, 0x1003d,
+	0x1003f, 0x1004d,
+	0x10050, 0x1005d,
+	0x10080, 0x100fa,
+	0x10280, 0x1029c,
+	0x102a0, 0x102d0,
+	0x10300, 0x1031f,
+	0x10330, 0x10340,
+	0x10342, 0x10349,
+	0x10350, 0x10375,
+	0x10380, 0x1039d,
+	0x103a0, 0x103c3,
+	0x103c8, 0x103cf,
+	0x10400, 0x1049d,
+	0x10500, 0x10527,
+	0x10530, 0x10563,
+	0x10600, 0x10736,
+	0x10740, 0x10755,
+	0x10760, 0x10767,
+	0x10800, 0x10805,
+	0x1080a, 0x10835,
+	0x10837, 0x10838,
+	0x1083f, 0x10855,
+	0x10860, 0x10876,
+	0x10880, 0x1089e,
+	0x10900, 0x10915,
+	0x10920, 0x10939,
+	0x10980, 0x109b7,
+	0x109be, 0x109bf,
+	0x10a10, 0x10a13,
+	0x10a15, 0x10a17,
+	0x10a19, 0x10a33,
+	0x10a60, 0x10a7c,
+	0x10a80, 0x10a9c,
+	0x10ac0, 0x10ac7,
+	0x10ac9, 0x10ae4,
+	0x10b00, 0x10b35,
+	0x10b40, 0x10b55,
+	0x10b60, 0x10b72,
+	0x10b80, 0x10b91,
+	0x10c00, 0x10c48,
+	0x11003, 0x11037,
+	0x11083, 0x110af,
+	0x110d0, 0x110e8,
+	0x11103, 0x11126,
+	0x11150, 0x11172,
+	0x11183, 0x111b2,
+	0x111c1, 0x111c4,
+	0x11200, 0x11211,
+	0x11213, 0x1122b,
+	0x112b0, 0x112de,
+	0x11305, 0x1130c,
+	0x1130f, 0x11310,
+	0x11313, 0x11328,
+	0x1132a, 0x11330,
+	0x11332, 0x11333,
+	0x11335, 0x11339,
+	0x1135d, 0x11361,
+	0x11480, 0x114af,
+	0x114c4, 0x114c5,
+	0x11580, 0x115ae,
+	0x11600, 0x1162f,
+	0x11680, 0x116aa,
+	0x118a0, 0x118df,
+	0x11ac0, 0x11af8,
+	0x12000, 0x12398,
+	0x13000, 0x1342e,
+	0x16800, 0x16a38,
+	0x16a40, 0x16a5e,
+	0x16ad0, 0x16aed,
+	0x16b00, 0x16b2f,
+	0x16b40, 0x16b43,
+	0x16b63, 0x16b77,
+	0x16b7d, 0x16b8f,
+	0x16f00, 0x16f44,
+	0x16f93, 0x16f9f,
+	0x1b000, 0x1b001,
+	0x1bc00, 0x1bc6a,
+	0x1bc70, 0x1bc7c,
+	0x1bc80, 0x1bc88,
+	0x1bc90, 0x1bc99,
+	0x1d400, 0x1d454,
+	0x1d456, 0x1d49c,
+	0x1d49e, 0x1d49f,
+	0x1d4a5, 0x1d4a6,
+	0x1d4a9, 0x1d4ac,
+	0x1d4ae, 0x1d4b9,
+	0x1d4bd, 0x1d4c3,
+	0x1d4c5, 0x1d505,
+	0x1d507, 0x1d50a,
+	0x1d50d, 0x1d514,
+	0x1d516, 0x1d51c,
+	0x1d51e, 0x1d539,
+	0x1d53b, 0x1d53e,
+	0x1d540, 0x1d544,
+	0x1d54a, 0x1d550,
+	0x1d552, 0x1d6a5,
+	0x1d6a8, 0x1d6c0,
+	0x1d6c2, 0x1d6da,
+	0x1d6dc, 0x1d6fa,
+	0x1d6fc, 0x1d714,
+	0x1d716, 0x1d734,
+	0x1d736, 0x1d74e,
+	0x1d750, 0x1d76e,
+	0x1d770, 0x1d788,
+	0x1d78a, 0x1d7a8,
+	0x1d7aa, 0x1d7c2,
+	0x1d7c4, 0x1d7cb,
+	0x1e800, 0x1e8c4,
+	0x1ee00, 0x1ee03,
+	0x1ee05, 0x1ee1f,
+	0x1ee21, 0x1ee22,
+	0x1ee29, 0x1ee32,
+	0x1ee34, 0x1ee37,
+	0x1ee4d, 0x1ee4f,
+	0x1ee51, 0x1ee52,
+	0x1ee61, 0x1ee62,
+	0x1ee67, 0x1ee6a,
+	0x1ee6c, 0x1ee72,
+	0x1ee74, 0x1ee77,
+	0x1ee79, 0x1ee7c,
+	0x1ee80, 0x1ee89,
+	0x1ee8b, 0x1ee9b,
+	0x1eea1, 0x1eea3,
+	0x1eea5, 0x1eea9,
+	0x1eeab, 0x1eebb,
+	0x20000, 0x2a6d6,
+	0x2a700, 0x2b734,
+	0x2b740, 0x2b81d,
+	0x2f800, 0x2fa1d,
 };
 
 } // !namespace
@@ -592,228 +590,228 @@
 namespace {
 
 const char32_t isalphas[] = {
-    0x00aa,
-    0x00b5,
-    0x00ba,
-    0x02ec,
-    0x02ee,
-    0x037f,
-    0x0386,
-    0x038c,
-    0x0559,
-    0x06d5,
-    0x06ff,
-    0x0710,
-    0x07b1,
-    0x07fa,
-    0x081a,
-    0x0824,
-    0x0828,
-    0x093d,
-    0x0950,
-    0x09b2,
-    0x09bd,
-    0x09ce,
-    0x0a5e,
-    0x0abd,
-    0x0ad0,
-    0x0b3d,
-    0x0b71,
-    0x0b83,
-    0x0b9c,
-    0x0bd0,
-    0x0c3d,
-    0x0cbd,
-    0x0cde,
-    0x0d3d,
-    0x0d4e,
-    0x0dbd,
-    0x0e84,
-    0x0e8a,
-    0x0e8d,
-    0x0ea5,
-    0x0ea7,
-    0x0ebd,
-    0x0ec6,
-    0x0f00,
-    0x103f,
-    0x1061,
-    0x108e,
-    0x10c7,
-    0x10cd,
-    0x1258,
-    0x12c0,
-    0x17d7,
-    0x17dc,
-    0x18aa,
-    0x1aa7,
-    0x1f59,
-    0x1f5b,
-    0x1f5d,
-    0x1fbe,
-    0x2071,
-    0x207f,
-    0x2102,
-    0x2107,
-    0x2115,
-    0x2124,
-    0x2126,
-    0x2128,
-    0x214e,
-    0x2d27,
-    0x2d2d,
-    0x2d6f,
-    0x2e2f,
-    0xa8fb,
-    0xa9cf,
-    0xaa7a,
-    0xaab1,
-    0xaac0,
-    0xaac2,
-    0xfb1d,
-    0xfb3e,
-    0x10808,
-    0x1083c,
-    0x10a00,
-    0x11176,
-    0x111da,
-    0x1133d,
-    0x114c7,
-    0x11644,
-    0x118ff,
-    0x16f50,
-    0x1d4a2,
-    0x1d4bb,
-    0x1d546,
-    0x1ee24,
-    0x1ee27,
-    0x1ee39,
-    0x1ee3b,
-    0x1ee42,
-    0x1ee47,
-    0x1ee49,
-    0x1ee4b,
-    0x1ee54,
-    0x1ee57,
-    0x1ee59,
-    0x1ee5b,
-    0x1ee5d,
-    0x1ee5f,
-    0x1ee64,
-    0x1ee7e,
+	0x00aa,
+	0x00b5,
+	0x00ba,
+	0x02ec,
+	0x02ee,
+	0x037f,
+	0x0386,
+	0x038c,
+	0x0559,
+	0x06d5,
+	0x06ff,
+	0x0710,
+	0x07b1,
+	0x07fa,
+	0x081a,
+	0x0824,
+	0x0828,
+	0x093d,
+	0x0950,
+	0x09b2,
+	0x09bd,
+	0x09ce,
+	0x0a5e,
+	0x0abd,
+	0x0ad0,
+	0x0b3d,
+	0x0b71,
+	0x0b83,
+	0x0b9c,
+	0x0bd0,
+	0x0c3d,
+	0x0cbd,
+	0x0cde,
+	0x0d3d,
+	0x0d4e,
+	0x0dbd,
+	0x0e84,
+	0x0e8a,
+	0x0e8d,
+	0x0ea5,
+	0x0ea7,
+	0x0ebd,
+	0x0ec6,
+	0x0f00,
+	0x103f,
+	0x1061,
+	0x108e,
+	0x10c7,
+	0x10cd,
+	0x1258,
+	0x12c0,
+	0x17d7,
+	0x17dc,
+	0x18aa,
+	0x1aa7,
+	0x1f59,
+	0x1f5b,
+	0x1f5d,
+	0x1fbe,
+	0x2071,
+	0x207f,
+	0x2102,
+	0x2107,
+	0x2115,
+	0x2124,
+	0x2126,
+	0x2128,
+	0x214e,
+	0x2d27,
+	0x2d2d,
+	0x2d6f,
+	0x2e2f,
+	0xa8fb,
+	0xa9cf,
+	0xaa7a,
+	0xaab1,
+	0xaac0,
+	0xaac2,
+	0xfb1d,
+	0xfb3e,
+	0x10808,
+	0x1083c,
+	0x10a00,
+	0x11176,
+	0x111da,
+	0x1133d,
+	0x114c7,
+	0x11644,
+	0x118ff,
+	0x16f50,
+	0x1d4a2,
+	0x1d4bb,
+	0x1d546,
+	0x1ee24,
+	0x1ee27,
+	0x1ee39,
+	0x1ee3b,
+	0x1ee42,
+	0x1ee47,
+	0x1ee49,
+	0x1ee4b,
+	0x1ee54,
+	0x1ee57,
+	0x1ee59,
+	0x1ee5b,
+	0x1ee5d,
+	0x1ee5f,
+	0x1ee64,
+	0x1ee7e,
 };
 
 } // !namespace
 
-bool isalpha(char32_t c) noexcept
+auto isalpha(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, isalphar, nelem (isalphar)/2, 2);
+	p = search(c, isalphar, nelem (isalphar) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
- p = rbsearch(c, isalphas, nelem (isalphas), 1);
+	p = search(c, isalphas, nelem (isalphas), 1);
 
-   if (p && c == p[0])
-       return true;
+	if (p && c == p[0])
+		return true;
 
- return false;
+	return false;
 }
 
 namespace {
 
 const char32_t isupperr[] = {
-    0x0041, 0x005a,
-    0x00c0, 0x00d6,
-    0x00d8, 0x00de,
-    0x0178, 0x0179,
-    0x0181, 0x0182,
-    0x0186, 0x0187,
-    0x0189, 0x018b,
-    0x018e, 0x0191,
-    0x0193, 0x0194,
-    0x0196, 0x0198,
-    0x019c, 0x019d,
-    0x019f, 0x01a0,
-    0x01a6, 0x01a7,
-    0x01ae, 0x01af,
-    0x01b1, 0x01b3,
-    0x01b7, 0x01b8,
-    0x01f6, 0x01f8,
-    0x023a, 0x023b,
-    0x023d, 0x023e,
-    0x0243, 0x0246,
-    0x0388, 0x038a,
-    0x038e, 0x038f,
-    0x0391, 0x03a1,
-    0x03a3, 0x03ab,
-    0x03d2, 0x03d4,
-    0x03f9, 0x03fa,
-    0x03fd, 0x042f,
-    0x04c0, 0x04c1,
-    0x0531, 0x0556,
-    0x10a0, 0x10c5,
-    0x1f08, 0x1f0f,
-    0x1f18, 0x1f1d,
-    0x1f28, 0x1f2f,
-    0x1f38, 0x1f3f,
-    0x1f48, 0x1f4d,
-    0x1f68, 0x1f6f,
-    0x1f88, 0x1f8f,
-    0x1f98, 0x1f9f,
-    0x1fa8, 0x1faf,
-    0x1fb8, 0x1fbc,
-    0x1fc8, 0x1fcc,
-    0x1fd8, 0x1fdb,
-    0x1fe8, 0x1fec,
-    0x1ff8, 0x1ffc,
-    0x210b, 0x210d,
-    0x2110, 0x2112,
-    0x2119, 0x211d,
-    0x212a, 0x212d,
-    0x2130, 0x2133,
-    0x213e, 0x213f,
-    0x2160, 0x216f,
-    0x24b6, 0x24cf,
-    0x2c00, 0x2c2e,
-    0x2c62, 0x2c64,
-    0x2c6d, 0x2c70,
-    0x2c7e, 0x2c80,
-    0xa77d, 0xa77e,
-    0xa7aa, 0xa7ad,
-    0xa7b0, 0xa7b1,
-    0xff21, 0xff3a,
-    0x10400, 0x10427,
-    0x118a0, 0x118bf,
-    0x1d400, 0x1d419,
-    0x1d434, 0x1d44d,
-    0x1d468, 0x1d481,
-    0x1d49e, 0x1d49f,
-    0x1d4a5, 0x1d4a6,
-    0x1d4a9, 0x1d4ac,
-    0x1d4ae, 0x1d4b5,
-    0x1d4d0, 0x1d4e9,
-    0x1d504, 0x1d505,
-    0x1d507, 0x1d50a,
-    0x1d50d, 0x1d514,
-    0x1d516, 0x1d51c,
-    0x1d538, 0x1d539,
-    0x1d53b, 0x1d53e,
-    0x1d540, 0x1d544,
-    0x1d54a, 0x1d550,
-    0x1d56c, 0x1d585,
-    0x1d5a0, 0x1d5b9,
-    0x1d5d4, 0x1d5ed,
-    0x1d608, 0x1d621,
-    0x1d63c, 0x1d655,
-    0x1d670, 0x1d689,
-    0x1d6a8, 0x1d6c0,
-    0x1d6e2, 0x1d6fa,
-    0x1d71c, 0x1d734,
-    0x1d756, 0x1d76e,
-    0x1d790, 0x1d7a8,
+	0x0041, 0x005a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00de,
+	0x0178, 0x0179,
+	0x0181, 0x0182,
+	0x0186, 0x0187,
+	0x0189, 0x018b,
+	0x018e, 0x0191,
+	0x0193, 0x0194,
+	0x0196, 0x0198,
+	0x019c, 0x019d,
+	0x019f, 0x01a0,
+	0x01a6, 0x01a7,
+	0x01ae, 0x01af,
+	0x01b1, 0x01b3,
+	0x01b7, 0x01b8,
+	0x01f6, 0x01f8,
+	0x023a, 0x023b,
+	0x023d, 0x023e,
+	0x0243, 0x0246,
+	0x0388, 0x038a,
+	0x038e, 0x038f,
+	0x0391, 0x03a1,
+	0x03a3, 0x03ab,
+	0x03d2, 0x03d4,
+	0x03f9, 0x03fa,
+	0x03fd, 0x042f,
+	0x04c0, 0x04c1,
+	0x0531, 0x0556,
+	0x10a0, 0x10c5,
+	0x1f08, 0x1f0f,
+	0x1f18, 0x1f1d,
+	0x1f28, 0x1f2f,
+	0x1f38, 0x1f3f,
+	0x1f48, 0x1f4d,
+	0x1f68, 0x1f6f,
+	0x1f88, 0x1f8f,
+	0x1f98, 0x1f9f,
+	0x1fa8, 0x1faf,
+	0x1fb8, 0x1fbc,
+	0x1fc8, 0x1fcc,
+	0x1fd8, 0x1fdb,
+	0x1fe8, 0x1fec,
+	0x1ff8, 0x1ffc,
+	0x210b, 0x210d,
+	0x2110, 0x2112,
+	0x2119, 0x211d,
+	0x212a, 0x212d,
+	0x2130, 0x2133,
+	0x213e, 0x213f,
+	0x2160, 0x216f,
+	0x24b6, 0x24cf,
+	0x2c00, 0x2c2e,
+	0x2c62, 0x2c64,
+	0x2c6d, 0x2c70,
+	0x2c7e, 0x2c80,
+	0xa77d, 0xa77e,
+	0xa7aa, 0xa7ad,
+	0xa7b0, 0xa7b1,
+	0xff21, 0xff3a,
+	0x10400, 0x10427,
+	0x118a0, 0x118bf,
+	0x1d400, 0x1d419,
+	0x1d434, 0x1d44d,
+	0x1d468, 0x1d481,
+	0x1d49e, 0x1d49f,
+	0x1d4a5, 0x1d4a6,
+	0x1d4a9, 0x1d4ac,
+	0x1d4ae, 0x1d4b5,
+	0x1d4d0, 0x1d4e9,
+	0x1d504, 0x1d505,
+	0x1d507, 0x1d50a,
+	0x1d50d, 0x1d514,
+	0x1d516, 0x1d51c,
+	0x1d538, 0x1d539,
+	0x1d53b, 0x1d53e,
+	0x1d540, 0x1d544,
+	0x1d54a, 0x1d550,
+	0x1d56c, 0x1d585,
+	0x1d5a0, 0x1d5b9,
+	0x1d5d4, 0x1d5ed,
+	0x1d608, 0x1d621,
+	0x1d63c, 0x1d655,
+	0x1d670, 0x1d689,
+	0x1d6a8, 0x1d6c0,
+	0x1d6e2, 0x1d6fa,
+	0x1d71c, 0x1d734,
+	0x1d756, 0x1d76e,
+	0x1d790, 0x1d7a8,
 };
 
 } // !namespace
@@ -821,665 +819,665 @@
 namespace {
 
 const char32_t isuppers[] = {
-    0x0100,
-    0x0102,
-    0x0104,
-    0x0106,
-    0x0108,
-    0x010a,
-    0x010c,
-    0x010e,
-    0x0110,
-    0x0112,
-    0x0114,
-    0x0116,
-    0x0118,
-    0x011a,
-    0x011c,
-    0x011e,
-    0x0120,
-    0x0122,
-    0x0124,
-    0x0126,
-    0x0128,
-    0x012a,
-    0x012c,
-    0x012e,
-    0x0130,
-    0x0132,
-    0x0134,
-    0x0136,
-    0x0139,
-    0x013b,
-    0x013d,
-    0x013f,
-    0x0141,
-    0x0143,
-    0x0145,
-    0x0147,
-    0x014a,
-    0x014c,
-    0x014e,
-    0x0150,
-    0x0152,
-    0x0154,
-    0x0156,
-    0x0158,
-    0x015a,
-    0x015c,
-    0x015e,
-    0x0160,
-    0x0162,
-    0x0164,
-    0x0166,
-    0x0168,
-    0x016a,
-    0x016c,
-    0x016e,
-    0x0170,
-    0x0172,
-    0x0174,
-    0x0176,
-    0x017b,
-    0x017d,
-    0x0184,
-    0x01a2,
-    0x01a4,
-    0x01a9,
-    0x01ac,
-    0x01b5,
-    0x01bc,
-    0x01c4,
-    0x01c7,
-    0x01ca,
-    0x01cd,
-    0x01cf,
-    0x01d1,
-    0x01d3,
-    0x01d5,
-    0x01d7,
-    0x01d9,
-    0x01db,
-    0x01de,
-    0x01e0,
-    0x01e2,
-    0x01e4,
-    0x01e6,
-    0x01e8,
-    0x01ea,
-    0x01ec,
-    0x01ee,
-    0x01f1,
-    0x01f4,
-    0x01fa,
-    0x01fc,
-    0x01fe,
-    0x0200,
-    0x0202,
-    0x0204,
-    0x0206,
-    0x0208,
-    0x020a,
-    0x020c,
-    0x020e,
-    0x0210,
-    0x0212,
-    0x0214,
-    0x0216,
-    0x0218,
-    0x021a,
-    0x021c,
-    0x021e,
-    0x0220,
-    0x0222,
-    0x0224,
-    0x0226,
-    0x0228,
-    0x022a,
-    0x022c,
-    0x022e,
-    0x0230,
-    0x0232,
-    0x0241,
-    0x0248,
-    0x024a,
-    0x024c,
-    0x024e,
-    0x0370,
-    0x0372,
-    0x0376,
-    0x037f,
-    0x0386,
-    0x038c,
-    0x03cf,
-    0x03d8,
-    0x03da,
-    0x03dc,
-    0x03de,
-    0x03e0,
-    0x03e2,
-    0x03e4,
-    0x03e6,
-    0x03e8,
-    0x03ea,
-    0x03ec,
-    0x03ee,
-    0x03f4,
-    0x03f7,
-    0x0460,
-    0x0462,
-    0x0464,
-    0x0466,
-    0x0468,
-    0x046a,
-    0x046c,
-    0x046e,
-    0x0470,
-    0x0472,
-    0x0474,
-    0x0476,
-    0x0478,
-    0x047a,
-    0x047c,
-    0x047e,
-    0x0480,
-    0x048a,
-    0x048c,
-    0x048e,
-    0x0490,
-    0x0492,
-    0x0494,
-    0x0496,
-    0x0498,
-    0x049a,
-    0x049c,
-    0x049e,
-    0x04a0,
-    0x04a2,
-    0x04a4,
-    0x04a6,
-    0x04a8,
-    0x04aa,
-    0x04ac,
-    0x04ae,
-    0x04b0,
-    0x04b2,
-    0x04b4,
-    0x04b6,
-    0x04b8,
-    0x04ba,
-    0x04bc,
-    0x04be,
-    0x04c3,
-    0x04c5,
-    0x04c7,
-    0x04c9,
-    0x04cb,
-    0x04cd,
-    0x04d0,
-    0x04d2,
-    0x04d4,
-    0x04d6,
-    0x04d8,
-    0x04da,
-    0x04dc,
-    0x04de,
-    0x04e0,
-    0x04e2,
-    0x04e4,
-    0x04e6,
-    0x04e8,
-    0x04ea,
-    0x04ec,
-    0x04ee,
-    0x04f0,
-    0x04f2,
-    0x04f4,
-    0x04f6,
-    0x04f8,
-    0x04fa,
-    0x04fc,
-    0x04fe,
-    0x0500,
-    0x0502,
-    0x0504,
-    0x0506,
-    0x0508,
-    0x050a,
-    0x050c,
-    0x050e,
-    0x0510,
-    0x0512,
-    0x0514,
-    0x0516,
-    0x0518,
-    0x051a,
-    0x051c,
-    0x051e,
-    0x0520,
-    0x0522,
-    0x0524,
-    0x0526,
-    0x0528,
-    0x052a,
-    0x052c,
-    0x052e,
-    0x10c7,
-    0x10cd,
-    0x1e00,
-    0x1e02,
-    0x1e04,
-    0x1e06,
-    0x1e08,
-    0x1e0a,
-    0x1e0c,
-    0x1e0e,
-    0x1e10,
-    0x1e12,
-    0x1e14,
-    0x1e16,
-    0x1e18,
-    0x1e1a,
-    0x1e1c,
-    0x1e1e,
-    0x1e20,
-    0x1e22,
-    0x1e24,
-    0x1e26,
-    0x1e28,
-    0x1e2a,
-    0x1e2c,
-    0x1e2e,
-    0x1e30,
-    0x1e32,
-    0x1e34,
-    0x1e36,
-    0x1e38,
-    0x1e3a,
-    0x1e3c,
-    0x1e3e,
-    0x1e40,
-    0x1e42,
-    0x1e44,
-    0x1e46,
-    0x1e48,
-    0x1e4a,
-    0x1e4c,
-    0x1e4e,
-    0x1e50,
-    0x1e52,
-    0x1e54,
-    0x1e56,
-    0x1e58,
-    0x1e5a,
-    0x1e5c,
-    0x1e5e,
-    0x1e60,
-    0x1e62,
-    0x1e64,
-    0x1e66,
-    0x1e68,
-    0x1e6a,
-    0x1e6c,
-    0x1e6e,
-    0x1e70,
-    0x1e72,
-    0x1e74,
-    0x1e76,
-    0x1e78,
-    0x1e7a,
-    0x1e7c,
-    0x1e7e,
-    0x1e80,
-    0x1e82,
-    0x1e84,
-    0x1e86,
-    0x1e88,
-    0x1e8a,
-    0x1e8c,
-    0x1e8e,
-    0x1e90,
-    0x1e92,
-    0x1e94,
-    0x1e9e,
-    0x1ea0,
-    0x1ea2,
-    0x1ea4,
-    0x1ea6,
-    0x1ea8,
-    0x1eaa,
-    0x1eac,
-    0x1eae,
-    0x1eb0,
-    0x1eb2,
-    0x1eb4,
-    0x1eb6,
-    0x1eb8,
-    0x1eba,
-    0x1ebc,
-    0x1ebe,
-    0x1ec0,
-    0x1ec2,
-    0x1ec4,
-    0x1ec6,
-    0x1ec8,
-    0x1eca,
-    0x1ecc,
-    0x1ece,
-    0x1ed0,
-    0x1ed2,
-    0x1ed4,
-    0x1ed6,
-    0x1ed8,
-    0x1eda,
-    0x1edc,
-    0x1ede,
-    0x1ee0,
-    0x1ee2,
-    0x1ee4,
-    0x1ee6,
-    0x1ee8,
-    0x1eea,
-    0x1eec,
-    0x1eee,
-    0x1ef0,
-    0x1ef2,
-    0x1ef4,
-    0x1ef6,
-    0x1ef8,
-    0x1efa,
-    0x1efc,
-    0x1efe,
-    0x1f59,
-    0x1f5b,
-    0x1f5d,
-    0x1f5f,
-    0x2102,
-    0x2107,
-    0x2115,
-    0x2124,
-    0x2126,
-    0x2128,
-    0x2145,
-    0x2183,
-    0x2c60,
-    0x2c67,
-    0x2c69,
-    0x2c6b,
-    0x2c72,
-    0x2c75,
-    0x2c82,
-    0x2c84,
-    0x2c86,
-    0x2c88,
-    0x2c8a,
-    0x2c8c,
-    0x2c8e,
-    0x2c90,
-    0x2c92,
-    0x2c94,
-    0x2c96,
-    0x2c98,
-    0x2c9a,
-    0x2c9c,
-    0x2c9e,
-    0x2ca0,
-    0x2ca2,
-    0x2ca4,
-    0x2ca6,
-    0x2ca8,
-    0x2caa,
-    0x2cac,
-    0x2cae,
-    0x2cb0,
-    0x2cb2,
-    0x2cb4,
-    0x2cb6,
-    0x2cb8,
-    0x2cba,
-    0x2cbc,
-    0x2cbe,
-    0x2cc0,
-    0x2cc2,
-    0x2cc4,
-    0x2cc6,
-    0x2cc8,
-    0x2cca,
-    0x2ccc,
-    0x2cce,
-    0x2cd0,
-    0x2cd2,
-    0x2cd4,
-    0x2cd6,
-    0x2cd8,
-    0x2cda,
-    0x2cdc,
-    0x2cde,
-    0x2ce0,
-    0x2ce2,
-    0x2ceb,
-    0x2ced,
-    0x2cf2,
-    0xa640,
-    0xa642,
-    0xa644,
-    0xa646,
-    0xa648,
-    0xa64a,
-    0xa64c,
-    0xa64e,
-    0xa650,
-    0xa652,
-    0xa654,
-    0xa656,
-    0xa658,
-    0xa65a,
-    0xa65c,
-    0xa65e,
-    0xa660,
-    0xa662,
-    0xa664,
-    0xa666,
-    0xa668,
-    0xa66a,
-    0xa66c,
-    0xa680,
-    0xa682,
-    0xa684,
-    0xa686,
-    0xa688,
-    0xa68a,
-    0xa68c,
-    0xa68e,
-    0xa690,
-    0xa692,
-    0xa694,
-    0xa696,
-    0xa698,
-    0xa69a,
-    0xa722,
-    0xa724,
-    0xa726,
-    0xa728,
-    0xa72a,
-    0xa72c,
-    0xa72e,
-    0xa732,
-    0xa734,
-    0xa736,
-    0xa738,
-    0xa73a,
-    0xa73c,
-    0xa73e,
-    0xa740,
-    0xa742,
-    0xa744,
-    0xa746,
-    0xa748,
-    0xa74a,
-    0xa74c,
-    0xa74e,
-    0xa750,
-    0xa752,
-    0xa754,
-    0xa756,
-    0xa758,
-    0xa75a,
-    0xa75c,
-    0xa75e,
-    0xa760,
-    0xa762,
-    0xa764,
-    0xa766,
-    0xa768,
-    0xa76a,
-    0xa76c,
-    0xa76e,
-    0xa779,
-    0xa77b,
-    0xa780,
-    0xa782,
-    0xa784,
-    0xa786,
-    0xa78b,
-    0xa78d,
-    0xa790,
-    0xa792,
-    0xa796,
-    0xa798,
-    0xa79a,
-    0xa79c,
-    0xa79e,
-    0xa7a0,
-    0xa7a2,
-    0xa7a4,
-    0xa7a6,
-    0xa7a8,
-    0x1d49c,
-    0x1d4a2,
-    0x1d546,
-    0x1d7ca,
+	0x0100,
+	0x0102,
+	0x0104,
+	0x0106,
+	0x0108,
+	0x010a,
+	0x010c,
+	0x010e,
+	0x0110,
+	0x0112,
+	0x0114,
+	0x0116,
+	0x0118,
+	0x011a,
+	0x011c,
+	0x011e,
+	0x0120,
+	0x0122,
+	0x0124,
+	0x0126,
+	0x0128,
+	0x012a,
+	0x012c,
+	0x012e,
+	0x0130,
+	0x0132,
+	0x0134,
+	0x0136,
+	0x0139,
+	0x013b,
+	0x013d,
+	0x013f,
+	0x0141,
+	0x0143,
+	0x0145,
+	0x0147,
+	0x014a,
+	0x014c,
+	0x014e,
+	0x0150,
+	0x0152,
+	0x0154,
+	0x0156,
+	0x0158,
+	0x015a,
+	0x015c,
+	0x015e,
+	0x0160,
+	0x0162,
+	0x0164,
+	0x0166,
+	0x0168,
+	0x016a,
+	0x016c,
+	0x016e,
+	0x0170,
+	0x0172,
+	0x0174,
+	0x0176,
+	0x017b,
+	0x017d,
+	0x0184,
+	0x01a2,
+	0x01a4,
+	0x01a9,
+	0x01ac,
+	0x01b5,
+	0x01bc,
+	0x01c4,
+	0x01c7,
+	0x01ca,
+	0x01cd,
+	0x01cf,
+	0x01d1,
+	0x01d3,
+	0x01d5,
+	0x01d7,
+	0x01d9,
+	0x01db,
+	0x01de,
+	0x01e0,
+	0x01e2,
+	0x01e4,
+	0x01e6,
+	0x01e8,
+	0x01ea,
+	0x01ec,
+	0x01ee,
+	0x01f1,
+	0x01f4,
+	0x01fa,
+	0x01fc,
+	0x01fe,
+	0x0200,
+	0x0202,
+	0x0204,
+	0x0206,
+	0x0208,
+	0x020a,
+	0x020c,
+	0x020e,
+	0x0210,
+	0x0212,
+	0x0214,
+	0x0216,
+	0x0218,
+	0x021a,
+	0x021c,
+	0x021e,
+	0x0220,
+	0x0222,
+	0x0224,
+	0x0226,
+	0x0228,
+	0x022a,
+	0x022c,
+	0x022e,
+	0x0230,
+	0x0232,
+	0x0241,
+	0x0248,
+	0x024a,
+	0x024c,
+	0x024e,
+	0x0370,
+	0x0372,
+	0x0376,
+	0x037f,
+	0x0386,
+	0x038c,
+	0x03cf,
+	0x03d8,
+	0x03da,
+	0x03dc,
+	0x03de,
+	0x03e0,
+	0x03e2,
+	0x03e4,
+	0x03e6,
+	0x03e8,
+	0x03ea,
+	0x03ec,
+	0x03ee,
+	0x03f4,
+	0x03f7,
+	0x0460,
+	0x0462,
+	0x0464,
+	0x0466,
+	0x0468,
+	0x046a,
+	0x046c,
+	0x046e,
+	0x0470,
+	0x0472,
+	0x0474,
+	0x0476,
+	0x0478,
+	0x047a,
+	0x047c,
+	0x047e,
+	0x0480,
+	0x048a,
+	0x048c,
+	0x048e,
+	0x0490,
+	0x0492,
+	0x0494,
+	0x0496,
+	0x0498,
+	0x049a,
+	0x049c,
+	0x049e,
+	0x04a0,
+	0x04a2,
+	0x04a4,
+	0x04a6,
+	0x04a8,
+	0x04aa,
+	0x04ac,
+	0x04ae,
+	0x04b0,
+	0x04b2,
+	0x04b4,
+	0x04b6,
+	0x04b8,
+	0x04ba,
+	0x04bc,
+	0x04be,
+	0x04c3,
+	0x04c5,
+	0x04c7,
+	0x04c9,
+	0x04cb,
+	0x04cd,
+	0x04d0,
+	0x04d2,
+	0x04d4,
+	0x04d6,
+	0x04d8,
+	0x04da,
+	0x04dc,
+	0x04de,
+	0x04e0,
+	0x04e2,
+	0x04e4,
+	0x04e6,
+	0x04e8,
+	0x04ea,
+	0x04ec,
+	0x04ee,
+	0x04f0,
+	0x04f2,
+	0x04f4,
+	0x04f6,
+	0x04f8,
+	0x04fa,
+	0x04fc,
+	0x04fe,
+	0x0500,
+	0x0502,
+	0x0504,
+	0x0506,
+	0x0508,
+	0x050a,
+	0x050c,
+	0x050e,
+	0x0510,
+	0x0512,
+	0x0514,
+	0x0516,
+	0x0518,
+	0x051a,
+	0x051c,
+	0x051e,
+	0x0520,
+	0x0522,
+	0x0524,
+	0x0526,
+	0x0528,
+	0x052a,
+	0x052c,
+	0x052e,
+	0x10c7,
+	0x10cd,
+	0x1e00,
+	0x1e02,
+	0x1e04,
+	0x1e06,
+	0x1e08,
+	0x1e0a,
+	0x1e0c,
+	0x1e0e,
+	0x1e10,
+	0x1e12,
+	0x1e14,
+	0x1e16,
+	0x1e18,
+	0x1e1a,
+	0x1e1c,
+	0x1e1e,
+	0x1e20,
+	0x1e22,
+	0x1e24,
+	0x1e26,
+	0x1e28,
+	0x1e2a,
+	0x1e2c,
+	0x1e2e,
+	0x1e30,
+	0x1e32,
+	0x1e34,
+	0x1e36,
+	0x1e38,
+	0x1e3a,
+	0x1e3c,
+	0x1e3e,
+	0x1e40,
+	0x1e42,
+	0x1e44,
+	0x1e46,
+	0x1e48,
+	0x1e4a,
+	0x1e4c,
+	0x1e4e,
+	0x1e50,
+	0x1e52,
+	0x1e54,
+	0x1e56,
+	0x1e58,
+	0x1e5a,
+	0x1e5c,
+	0x1e5e,
+	0x1e60,
+	0x1e62,
+	0x1e64,
+	0x1e66,
+	0x1e68,
+	0x1e6a,
+	0x1e6c,
+	0x1e6e,
+	0x1e70,
+	0x1e72,
+	0x1e74,
+	0x1e76,
+	0x1e78,
+	0x1e7a,
+	0x1e7c,
+	0x1e7e,
+	0x1e80,
+	0x1e82,
+	0x1e84,
+	0x1e86,
+	0x1e88,
+	0x1e8a,
+	0x1e8c,
+	0x1e8e,
+	0x1e90,
+	0x1e92,
+	0x1e94,
+	0x1e9e,
+	0x1ea0,
+	0x1ea2,
+	0x1ea4,
+	0x1ea6,
+	0x1ea8,
+	0x1eaa,
+	0x1eac,
+	0x1eae,
+	0x1eb0,
+	0x1eb2,
+	0x1eb4,
+	0x1eb6,
+	0x1eb8,
+	0x1eba,
+	0x1ebc,
+	0x1ebe,
+	0x1ec0,
+	0x1ec2,
+	0x1ec4,
+	0x1ec6,
+	0x1ec8,
+	0x1eca,
+	0x1ecc,
+	0x1ece,
+	0x1ed0,
+	0x1ed2,
+	0x1ed4,
+	0x1ed6,
+	0x1ed8,
+	0x1eda,
+	0x1edc,
+	0x1ede,
+	0x1ee0,
+	0x1ee2,
+	0x1ee4,
+	0x1ee6,
+	0x1ee8,
+	0x1eea,
+	0x1eec,
+	0x1eee,
+	0x1ef0,
+	0x1ef2,
+	0x1ef4,
+	0x1ef6,
+	0x1ef8,
+	0x1efa,
+	0x1efc,
+	0x1efe,
+	0x1f59,
+	0x1f5b,
+	0x1f5d,
+	0x1f5f,
+	0x2102,
+	0x2107,
+	0x2115,
+	0x2124,
+	0x2126,
+	0x2128,
+	0x2145,
+	0x2183,
+	0x2c60,
+	0x2c67,
+	0x2c69,
+	0x2c6b,
+	0x2c72,
+	0x2c75,
+	0x2c82,
+	0x2c84,
+	0x2c86,
+	0x2c88,
+	0x2c8a,
+	0x2c8c,
+	0x2c8e,
+	0x2c90,
+	0x2c92,
+	0x2c94,
+	0x2c96,
+	0x2c98,
+	0x2c9a,
+	0x2c9c,
+	0x2c9e,
+	0x2ca0,
+	0x2ca2,
+	0x2ca4,
+	0x2ca6,
+	0x2ca8,
+	0x2caa,
+	0x2cac,
+	0x2cae,
+	0x2cb0,
+	0x2cb2,
+	0x2cb4,
+	0x2cb6,
+	0x2cb8,
+	0x2cba,
+	0x2cbc,
+	0x2cbe,
+	0x2cc0,
+	0x2cc2,
+	0x2cc4,
+	0x2cc6,
+	0x2cc8,
+	0x2cca,
+	0x2ccc,
+	0x2cce,
+	0x2cd0,
+	0x2cd2,
+	0x2cd4,
+	0x2cd6,
+	0x2cd8,
+	0x2cda,
+	0x2cdc,
+	0x2cde,
+	0x2ce0,
+	0x2ce2,
+	0x2ceb,
+	0x2ced,
+	0x2cf2,
+	0xa640,
+	0xa642,
+	0xa644,
+	0xa646,
+	0xa648,
+	0xa64a,
+	0xa64c,
+	0xa64e,
+	0xa650,
+	0xa652,
+	0xa654,
+	0xa656,
+	0xa658,
+	0xa65a,
+	0xa65c,
+	0xa65e,
+	0xa660,
+	0xa662,
+	0xa664,
+	0xa666,
+	0xa668,
+	0xa66a,
+	0xa66c,
+	0xa680,
+	0xa682,
+	0xa684,
+	0xa686,
+	0xa688,
+	0xa68a,
+	0xa68c,
+	0xa68e,
+	0xa690,
+	0xa692,
+	0xa694,
+	0xa696,
+	0xa698,
+	0xa69a,
+	0xa722,
+	0xa724,
+	0xa726,
+	0xa728,
+	0xa72a,
+	0xa72c,
+	0xa72e,
+	0xa732,
+	0xa734,
+	0xa736,
+	0xa738,
+	0xa73a,
+	0xa73c,
+	0xa73e,
+	0xa740,
+	0xa742,
+	0xa744,
+	0xa746,
+	0xa748,
+	0xa74a,
+	0xa74c,
+	0xa74e,
+	0xa750,
+	0xa752,
+	0xa754,
+	0xa756,
+	0xa758,
+	0xa75a,
+	0xa75c,
+	0xa75e,
+	0xa760,
+	0xa762,
+	0xa764,
+	0xa766,
+	0xa768,
+	0xa76a,
+	0xa76c,
+	0xa76e,
+	0xa779,
+	0xa77b,
+	0xa780,
+	0xa782,
+	0xa784,
+	0xa786,
+	0xa78b,
+	0xa78d,
+	0xa790,
+	0xa792,
+	0xa796,
+	0xa798,
+	0xa79a,
+	0xa79c,
+	0xa79e,
+	0xa7a0,
+	0xa7a2,
+	0xa7a4,
+	0xa7a6,
+	0xa7a8,
+	0x1d49c,
+	0x1d4a2,
+	0x1d546,
+	0x1d7ca,
 };
 
 } // !namespace
 
-bool isupper(char32_t c) noexcept
+auto isupper(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, isupperr, nelem (isupperr)/2, 2);
+	p = search(c, isupperr, nelem (isupperr) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
- p = rbsearch(c, isuppers, nelem (isuppers), 1);
+	p = search(c, isuppers, nelem (isuppers), 1);
 
-   if (p && c == p[0])
-       return true;
+	if (p && c == p[0])
+		return true;
 
- return false;
+	return false;
 }
 
 namespace {
 
 const char32_t islowerr[] = {
-    0x0061, 0x007a,
-    0x00df, 0x00f6,
-    0x00f8, 0x00ff,
-    0x0137, 0x0138,
-    0x0148, 0x0149,
-    0x017e, 0x0180,
-    0x018c, 0x018d,
-    0x0199, 0x019b,
-    0x01aa, 0x01ab,
-    0x01b9, 0x01ba,
-    0x01bd, 0x01bf,
-    0x01dc, 0x01dd,
-    0x01ef, 0x01f0,
-    0x0233, 0x0239,
-    0x023f, 0x0240,
-    0x024f, 0x0293,
-    0x0295, 0x02af,
-    0x037b, 0x037d,
-    0x03ac, 0x03ce,
-    0x03d0, 0x03d1,
-    0x03d5, 0x03d7,
-    0x03ef, 0x03f3,
-    0x03fb, 0x03fc,
-    0x0430, 0x045f,
-    0x04ce, 0x04cf,
-    0x0561, 0x0587,
-    0x1d00, 0x1d2b,
-    0x1d6b, 0x1d77,
-    0x1d79, 0x1d9a,
-    0x1e95, 0x1e9d,
-    0x1eff, 0x1f07,
-    0x1f10, 0x1f15,
-    0x1f20, 0x1f27,
-    0x1f30, 0x1f37,
-    0x1f40, 0x1f45,
-    0x1f50, 0x1f57,
-    0x1f60, 0x1f67,
-    0x1f70, 0x1f7d,
-    0x1f80, 0x1f87,
-    0x1f90, 0x1f97,
-    0x1fa0, 0x1fa7,
-    0x1fb0, 0x1fb4,
-    0x1fb6, 0x1fb7,
-    0x1fc2, 0x1fc4,
-    0x1fc6, 0x1fc7,
-    0x1fd0, 0x1fd3,
-    0x1fd6, 0x1fd7,
-    0x1fe0, 0x1fe7,
-    0x1ff2, 0x1ff4,
-    0x1ff6, 0x1ff7,
-    0x210e, 0x210f,
-    0x213c, 0x213d,
-    0x2146, 0x2149,
-    0x2170, 0x217f,
-    0x24d0, 0x24e9,
-    0x2c30, 0x2c5e,
-    0x2c65, 0x2c66,
-    0x2c73, 0x2c74,
-    0x2c76, 0x2c7b,
-    0x2ce3, 0x2ce4,
-    0x2d00, 0x2d25,
-    0xa72f, 0xa731,
-    0xa771, 0xa778,
-    0xa793, 0xa795,
-    0xab30, 0xab5a,
-    0xab64, 0xab65,
-    0xfb00, 0xfb06,
-    0xfb13, 0xfb17,
-    0xff41, 0xff5a,
-    0x10428, 0x1044f,
-    0x118c0, 0x118df,
-    0x1d41a, 0x1d433,
-    0x1d44e, 0x1d454,
-    0x1d456, 0x1d467,
-    0x1d482, 0x1d49b,
-    0x1d4b6, 0x1d4b9,
-    0x1d4bd, 0x1d4c3,
-    0x1d4c5, 0x1d4cf,
-    0x1d4ea, 0x1d503,
-    0x1d51e, 0x1d537,
-    0x1d552, 0x1d56b,
-    0x1d586, 0x1d59f,
-    0x1d5ba, 0x1d5d3,
-    0x1d5ee, 0x1d607,
-    0x1d622, 0x1d63b,
-    0x1d656, 0x1d66f,
-    0x1d68a, 0x1d6a5,
-    0x1d6c2, 0x1d6da,
-    0x1d6dc, 0x1d6e1,
-    0x1d6fc, 0x1d714,
-    0x1d716, 0x1d71b,
-    0x1d736, 0x1d74e,
-    0x1d750, 0x1d755,
-    0x1d770, 0x1d788,
-    0x1d78a, 0x1d78f,
-    0x1d7aa, 0x1d7c2,
-    0x1d7c4, 0x1d7c9,
+	0x0061, 0x007a,
+	0x00df, 0x00f6,
+	0x00f8, 0x00ff,
+	0x0137, 0x0138,
+	0x0148, 0x0149,
+	0x017e, 0x0180,
+	0x018c, 0x018d,
+	0x0199, 0x019b,
+	0x01aa, 0x01ab,
+	0x01b9, 0x01ba,
+	0x01bd, 0x01bf,
+	0x01dc, 0x01dd,
+	0x01ef, 0x01f0,
+	0x0233, 0x0239,
+	0x023f, 0x0240,
+	0x024f, 0x0293,
+	0x0295, 0x02af,
+	0x037b, 0x037d,
+	0x03ac, 0x03ce,
+	0x03d0, 0x03d1,
+	0x03d5, 0x03d7,
+	0x03ef, 0x03f3,
+	0x03fb, 0x03fc,
+	0x0430, 0x045f,
+	0x04ce, 0x04cf,
+	0x0561, 0x0587,
+	0x1d00, 0x1d2b,
+	0x1d6b, 0x1d77,
+	0x1d79, 0x1d9a,
+	0x1e95, 0x1e9d,
+	0x1eff, 0x1f07,
+	0x1f10, 0x1f15,
+	0x1f20, 0x1f27,
+	0x1f30, 0x1f37,
+	0x1f40, 0x1f45,
+	0x1f50, 0x1f57,
+	0x1f60, 0x1f67,
+	0x1f70, 0x1f7d,
+	0x1f80, 0x1f87,
+	0x1f90, 0x1f97,
+	0x1fa0, 0x1fa7,
+	0x1fb0, 0x1fb4,
+	0x1fb6, 0x1fb7,
+	0x1fc2, 0x1fc4,
+	0x1fc6, 0x1fc7,
+	0x1fd0, 0x1fd3,
+	0x1fd6, 0x1fd7,
+	0x1fe0, 0x1fe7,
+	0x1ff2, 0x1ff4,
+	0x1ff6, 0x1ff7,
+	0x210e, 0x210f,
+	0x213c, 0x213d,
+	0x2146, 0x2149,
+	0x2170, 0x217f,
+	0x24d0, 0x24e9,
+	0x2c30, 0x2c5e,
+	0x2c65, 0x2c66,
+	0x2c73, 0x2c74,
+	0x2c76, 0x2c7b,
+	0x2ce3, 0x2ce4,
+	0x2d00, 0x2d25,
+	0xa72f, 0xa731,
+	0xa771, 0xa778,
+	0xa793, 0xa795,
+	0xab30, 0xab5a,
+	0xab64, 0xab65,
+	0xfb00, 0xfb06,
+	0xfb13, 0xfb17,
+	0xff41, 0xff5a,
+	0x10428, 0x1044f,
+	0x118c0, 0x118df,
+	0x1d41a, 0x1d433,
+	0x1d44e, 0x1d454,
+	0x1d456, 0x1d467,
+	0x1d482, 0x1d49b,
+	0x1d4b6, 0x1d4b9,
+	0x1d4bd, 0x1d4c3,
+	0x1d4c5, 0x1d4cf,
+	0x1d4ea, 0x1d503,
+	0x1d51e, 0x1d537,
+	0x1d552, 0x1d56b,
+	0x1d586, 0x1d59f,
+	0x1d5ba, 0x1d5d3,
+	0x1d5ee, 0x1d607,
+	0x1d622, 0x1d63b,
+	0x1d656, 0x1d66f,
+	0x1d68a, 0x1d6a5,
+	0x1d6c2, 0x1d6da,
+	0x1d6dc, 0x1d6e1,
+	0x1d6fc, 0x1d714,
+	0x1d716, 0x1d71b,
+	0x1d736, 0x1d74e,
+	0x1d750, 0x1d755,
+	0x1d770, 0x1d788,
+	0x1d78a, 0x1d78f,
+	0x1d7aa, 0x1d7c2,
+	0x1d7c4, 0x1d7c9,
 };
 
 } // !namespace
@@ -1487,615 +1485,615 @@
 namespace {
 
 const char32_t islowers[] = {
-    0x00b5,
-    0x0101,
-    0x0103,
-    0x0105,
-    0x0107,
-    0x0109,
-    0x010b,
-    0x010d,
-    0x010f,
-    0x0111,
-    0x0113,
-    0x0115,
-    0x0117,
-    0x0119,
-    0x011b,
-    0x011d,
-    0x011f,
-    0x0121,
-    0x0123,
-    0x0125,
-    0x0127,
-    0x0129,
-    0x012b,
-    0x012d,
-    0x012f,
-    0x0131,
-    0x0133,
-    0x0135,
-    0x013a,
-    0x013c,
-    0x013e,
-    0x0140,
-    0x0142,
-    0x0144,
-    0x0146,
-    0x014b,
-    0x014d,
-    0x014f,
-    0x0151,
-    0x0153,
-    0x0155,
-    0x0157,
-    0x0159,
-    0x015b,
-    0x015d,
-    0x015f,
-    0x0161,
-    0x0163,
-    0x0165,
-    0x0167,
-    0x0169,
-    0x016b,
-    0x016d,
-    0x016f,
-    0x0171,
-    0x0173,
-    0x0175,
-    0x0177,
-    0x017a,
-    0x017c,
-    0x0183,
-    0x0185,
-    0x0188,
-    0x0192,
-    0x0195,
-    0x019e,
-    0x01a1,
-    0x01a3,
-    0x01a5,
-    0x01a8,
-    0x01ad,
-    0x01b0,
-    0x01b4,
-    0x01b6,
-    0x01c6,
-    0x01c9,
-    0x01cc,
-    0x01ce,
-    0x01d0,
-    0x01d2,
-    0x01d4,
-    0x01d6,
-    0x01d8,
-    0x01da,
-    0x01df,
-    0x01e1,
-    0x01e3,
-    0x01e5,
-    0x01e7,
-    0x01e9,
-    0x01eb,
-    0x01ed,
-    0x01f3,
-    0x01f5,
-    0x01f9,
-    0x01fb,
-    0x01fd,
-    0x01ff,
-    0x0201,
-    0x0203,
-    0x0205,
-    0x0207,
-    0x0209,
-    0x020b,
-    0x020d,
-    0x020f,
-    0x0211,
-    0x0213,
-    0x0215,
-    0x0217,
-    0x0219,
-    0x021b,
-    0x021d,
-    0x021f,
-    0x0221,
-    0x0223,
-    0x0225,
-    0x0227,
-    0x0229,
-    0x022b,
-    0x022d,
-    0x022f,
-    0x0231,
-    0x023c,
-    0x0242,
-    0x0247,
-    0x0249,
-    0x024b,
-    0x024d,
-    0x0371,
-    0x0373,
-    0x0377,
-    0x0390,
-    0x03d9,
-    0x03db,
-    0x03dd,
-    0x03df,
-    0x03e1,
-    0x03e3,
-    0x03e5,
-    0x03e7,
-    0x03e9,
-    0x03eb,
-    0x03ed,
-    0x03f5,
-    0x03f8,
-    0x0461,
-    0x0463,
-    0x0465,
-    0x0467,
-    0x0469,
-    0x046b,
-    0x046d,
-    0x046f,
-    0x0471,
-    0x0473,
-    0x0475,
-    0x0477,
-    0x0479,
-    0x047b,
-    0x047d,
-    0x047f,
-    0x0481,
-    0x048b,
-    0x048d,
-    0x048f,
-    0x0491,
-    0x0493,
-    0x0495,
-    0x0497,
-    0x0499,
-    0x049b,
-    0x049d,
-    0x049f,
-    0x04a1,
-    0x04a3,
-    0x04a5,
-    0x04a7,
-    0x04a9,
-    0x04ab,
-    0x04ad,
-    0x04af,
-    0x04b1,
-    0x04b3,
-    0x04b5,
-    0x04b7,
-    0x04b9,
-    0x04bb,
-    0x04bd,
-    0x04bf,
-    0x04c2,
-    0x04c4,
-    0x04c6,
-    0x04c8,
-    0x04ca,
-    0x04cc,
-    0x04d1,
-    0x04d3,
-    0x04d5,
-    0x04d7,
-    0x04d9,
-    0x04db,
-    0x04dd,
-    0x04df,
-    0x04e1,
-    0x04e3,
-    0x04e5,
-    0x04e7,
-    0x04e9,
-    0x04eb,
-    0x04ed,
-    0x04ef,
-    0x04f1,
-    0x04f3,
-    0x04f5,
-    0x04f7,
-    0x04f9,
-    0x04fb,
-    0x04fd,
-    0x04ff,
-    0x0501,
-    0x0503,
-    0x0505,
-    0x0507,
-    0x0509,
-    0x050b,
-    0x050d,
-    0x050f,
-    0x0511,
-    0x0513,
-    0x0515,
-    0x0517,
-    0x0519,
-    0x051b,
-    0x051d,
-    0x051f,
-    0x0521,
-    0x0523,
-    0x0525,
-    0x0527,
-    0x0529,
-    0x052b,
-    0x052d,
-    0x052f,
-    0x1e01,
-    0x1e03,
-    0x1e05,
-    0x1e07,
-    0x1e09,
-    0x1e0b,
-    0x1e0d,
-    0x1e0f,
-    0x1e11,
-    0x1e13,
-    0x1e15,
-    0x1e17,
-    0x1e19,
-    0x1e1b,
-    0x1e1d,
-    0x1e1f,
-    0x1e21,
-    0x1e23,
-    0x1e25,
-    0x1e27,
-    0x1e29,
-    0x1e2b,
-    0x1e2d,
-    0x1e2f,
-    0x1e31,
-    0x1e33,
-    0x1e35,
-    0x1e37,
-    0x1e39,
-    0x1e3b,
-    0x1e3d,
-    0x1e3f,
-    0x1e41,
-    0x1e43,
-    0x1e45,
-    0x1e47,
-    0x1e49,
-    0x1e4b,
-    0x1e4d,
-    0x1e4f,
-    0x1e51,
-    0x1e53,
-    0x1e55,
-    0x1e57,
-    0x1e59,
-    0x1e5b,
-    0x1e5d,
-    0x1e5f,
-    0x1e61,
-    0x1e63,
-    0x1e65,
-    0x1e67,
-    0x1e69,
-    0x1e6b,
-    0x1e6d,
-    0x1e6f,
-    0x1e71,
-    0x1e73,
-    0x1e75,
-    0x1e77,
-    0x1e79,
-    0x1e7b,
-    0x1e7d,
-    0x1e7f,
-    0x1e81,
-    0x1e83,
-    0x1e85,
-    0x1e87,
-    0x1e89,
-    0x1e8b,
-    0x1e8d,
-    0x1e8f,
-    0x1e91,
-    0x1e93,
-    0x1e9f,
-    0x1ea1,
-    0x1ea3,
-    0x1ea5,
-    0x1ea7,
-    0x1ea9,
-    0x1eab,
-    0x1ead,
-    0x1eaf,
-    0x1eb1,
-    0x1eb3,
-    0x1eb5,
-    0x1eb7,
-    0x1eb9,
-    0x1ebb,
-    0x1ebd,
-    0x1ebf,
-    0x1ec1,
-    0x1ec3,
-    0x1ec5,
-    0x1ec7,
-    0x1ec9,
-    0x1ecb,
-    0x1ecd,
-    0x1ecf,
-    0x1ed1,
-    0x1ed3,
-    0x1ed5,
-    0x1ed7,
-    0x1ed9,
-    0x1edb,
-    0x1edd,
-    0x1edf,
-    0x1ee1,
-    0x1ee3,
-    0x1ee5,
-    0x1ee7,
-    0x1ee9,
-    0x1eeb,
-    0x1eed,
-    0x1eef,
-    0x1ef1,
-    0x1ef3,
-    0x1ef5,
-    0x1ef7,
-    0x1ef9,
-    0x1efb,
-    0x1efd,
-    0x1fbe,
-    0x210a,
-    0x2113,
-    0x212f,
-    0x2134,
-    0x2139,
-    0x214e,
-    0x2184,
-    0x2c61,
-    0x2c68,
-    0x2c6a,
-    0x2c6c,
-    0x2c71,
-    0x2c81,
-    0x2c83,
-    0x2c85,
-    0x2c87,
-    0x2c89,
-    0x2c8b,
-    0x2c8d,
-    0x2c8f,
-    0x2c91,
-    0x2c93,
-    0x2c95,
-    0x2c97,
-    0x2c99,
-    0x2c9b,
-    0x2c9d,
-    0x2c9f,
-    0x2ca1,
-    0x2ca3,
-    0x2ca5,
-    0x2ca7,
-    0x2ca9,
-    0x2cab,
-    0x2cad,
-    0x2caf,
-    0x2cb1,
-    0x2cb3,
-    0x2cb5,
-    0x2cb7,
-    0x2cb9,
-    0x2cbb,
-    0x2cbd,
-    0x2cbf,
-    0x2cc1,
-    0x2cc3,
-    0x2cc5,
-    0x2cc7,
-    0x2cc9,
-    0x2ccb,
-    0x2ccd,
-    0x2ccf,
-    0x2cd1,
-    0x2cd3,
-    0x2cd5,
-    0x2cd7,
-    0x2cd9,
-    0x2cdb,
-    0x2cdd,
-    0x2cdf,
-    0x2ce1,
-    0x2cec,
-    0x2cee,
-    0x2cf3,
-    0x2d27,
-    0x2d2d,
-    0xa641,
-    0xa643,
-    0xa645,
-    0xa647,
-    0xa649,
-    0xa64b,
-    0xa64d,
-    0xa64f,
-    0xa651,
-    0xa653,
-    0xa655,
-    0xa657,
-    0xa659,
-    0xa65b,
-    0xa65d,
-    0xa65f,
-    0xa661,
-    0xa663,
-    0xa665,
-    0xa667,
-    0xa669,
-    0xa66b,
-    0xa66d,
-    0xa681,
-    0xa683,
-    0xa685,
-    0xa687,
-    0xa689,
-    0xa68b,
-    0xa68d,
-    0xa68f,
-    0xa691,
-    0xa693,
-    0xa695,
-    0xa697,
-    0xa699,
-    0xa69b,
-    0xa723,
-    0xa725,
-    0xa727,
-    0xa729,
-    0xa72b,
-    0xa72d,
-    0xa733,
-    0xa735,
-    0xa737,
-    0xa739,
-    0xa73b,
-    0xa73d,
-    0xa73f,
-    0xa741,
-    0xa743,
-    0xa745,
-    0xa747,
-    0xa749,
-    0xa74b,
-    0xa74d,
-    0xa74f,
-    0xa751,
-    0xa753,
-    0xa755,
-    0xa757,
-    0xa759,
-    0xa75b,
-    0xa75d,
-    0xa75f,
-    0xa761,
-    0xa763,
-    0xa765,
-    0xa767,
-    0xa769,
-    0xa76b,
-    0xa76d,
-    0xa76f,
-    0xa77a,
-    0xa77c,
-    0xa77f,
-    0xa781,
-    0xa783,
-    0xa785,
-    0xa787,
-    0xa78c,
-    0xa78e,
-    0xa791,
-    0xa797,
-    0xa799,
-    0xa79b,
-    0xa79d,
-    0xa79f,
-    0xa7a1,
-    0xa7a3,
-    0xa7a5,
-    0xa7a7,
-    0xa7a9,
-    0xa7fa,
-    0x1d4bb,
-    0x1d7cb,
+	0x00b5,
+	0x0101,
+	0x0103,
+	0x0105,
+	0x0107,
+	0x0109,
+	0x010b,
+	0x010d,
+	0x010f,
+	0x0111,
+	0x0113,
+	0x0115,
+	0x0117,
+	0x0119,
+	0x011b,
+	0x011d,
+	0x011f,
+	0x0121,
+	0x0123,
+	0x0125,
+	0x0127,
+	0x0129,
+	0x012b,
+	0x012d,
+	0x012f,
+	0x0131,
+	0x0133,
+	0x0135,
+	0x013a,
+	0x013c,
+	0x013e,
+	0x0140,
+	0x0142,
+	0x0144,
+	0x0146,
+	0x014b,
+	0x014d,
+	0x014f,
+	0x0151,
+	0x0153,
+	0x0155,
+	0x0157,
+	0x0159,
+	0x015b,
+	0x015d,
+	0x015f,
+	0x0161,
+	0x0163,
+	0x0165,
+	0x0167,
+	0x0169,
+	0x016b,
+	0x016d,
+	0x016f,
+	0x0171,
+	0x0173,
+	0x0175,
+	0x0177,
+	0x017a,
+	0x017c,
+	0x0183,
+	0x0185,
+	0x0188,
+	0x0192,
+	0x0195,
+	0x019e,
+	0x01a1,
+	0x01a3,
+	0x01a5,
+	0x01a8,
+	0x01ad,
+	0x01b0,
+	0x01b4,
+	0x01b6,
+	0x01c6,
+	0x01c9,
+	0x01cc,
+	0x01ce,
+	0x01d0,
+	0x01d2,
+	0x01d4,
+	0x01d6,
+	0x01d8,
+	0x01da,
+	0x01df,
+	0x01e1,
+	0x01e3,
+	0x01e5,
+	0x01e7,
+	0x01e9,
+	0x01eb,
+	0x01ed,
+	0x01f3,
+	0x01f5,
+	0x01f9,
+	0x01fb,
+	0x01fd,
+	0x01ff,
+	0x0201,
+	0x0203,
+	0x0205,
+	0x0207,
+	0x0209,
+	0x020b,
+	0x020d,
+	0x020f,
+	0x0211,
+	0x0213,
+	0x0215,
+	0x0217,
+	0x0219,
+	0x021b,
+	0x021d,
+	0x021f,
+	0x0221,
+	0x0223,
+	0x0225,
+	0x0227,
+	0x0229,
+	0x022b,
+	0x022d,
+	0x022f,
+	0x0231,
+	0x023c,
+	0x0242,
+	0x0247,
+	0x0249,
+	0x024b,
+	0x024d,
+	0x0371,
+	0x0373,
+	0x0377,
+	0x0390,
+	0x03d9,
+	0x03db,
+	0x03dd,
+	0x03df,
+	0x03e1,
+	0x03e3,
+	0x03e5,
+	0x03e7,
+	0x03e9,
+	0x03eb,
+	0x03ed,
+	0x03f5,
+	0x03f8,
+	0x0461,
+	0x0463,
+	0x0465,
+	0x0467,
+	0x0469,
+	0x046b,
+	0x046d,
+	0x046f,
+	0x0471,
+	0x0473,
+	0x0475,
+	0x0477,
+	0x0479,
+	0x047b,
+	0x047d,
+	0x047f,
+	0x0481,
+	0x048b,
+	0x048d,
+	0x048f,
+	0x0491,
+	0x0493,
+	0x0495,
+	0x0497,
+	0x0499,
+	0x049b,
+	0x049d,
+	0x049f,
+	0x04a1,
+	0x04a3,
+	0x04a5,
+	0x04a7,
+	0x04a9,
+	0x04ab,
+	0x04ad,
+	0x04af,
+	0x04b1,
+	0x04b3,
+	0x04b5,
+	0x04b7,
+	0x04b9,
+	0x04bb,
+	0x04bd,
+	0x04bf,
+	0x04c2,
+	0x04c4,
+	0x04c6,
+	0x04c8,
+	0x04ca,
+	0x04cc,
+	0x04d1,
+	0x04d3,
+	0x04d5,
+	0x04d7,
+	0x04d9,
+	0x04db,
+	0x04dd,
+	0x04df,
+	0x04e1,
+	0x04e3,
+	0x04e5,
+	0x04e7,
+	0x04e9,
+	0x04eb,
+	0x04ed,
+	0x04ef,
+	0x04f1,
+	0x04f3,
+	0x04f5,
+	0x04f7,
+	0x04f9,
+	0x04fb,
+	0x04fd,
+	0x04ff,
+	0x0501,
+	0x0503,
+	0x0505,
+	0x0507,
+	0x0509,
+	0x050b,
+	0x050d,
+	0x050f,
+	0x0511,
+	0x0513,
+	0x0515,
+	0x0517,
+	0x0519,
+	0x051b,
+	0x051d,
+	0x051f,
+	0x0521,
+	0x0523,
+	0x0525,
+	0x0527,
+	0x0529,
+	0x052b,
+	0x052d,
+	0x052f,
+	0x1e01,
+	0x1e03,
+	0x1e05,
+	0x1e07,
+	0x1e09,
+	0x1e0b,
+	0x1e0d,
+	0x1e0f,
+	0x1e11,
+	0x1e13,
+	0x1e15,
+	0x1e17,
+	0x1e19,
+	0x1e1b,
+	0x1e1d,
+	0x1e1f,
+	0x1e21,
+	0x1e23,
+	0x1e25,
+	0x1e27,
+	0x1e29,
+	0x1e2b,
+	0x1e2d,
+	0x1e2f,
+	0x1e31,
+	0x1e33,
+	0x1e35,
+	0x1e37,
+	0x1e39,
+	0x1e3b,
+	0x1e3d,
+	0x1e3f,
+	0x1e41,
+	0x1e43,
+	0x1e45,
+	0x1e47,
+	0x1e49,
+	0x1e4b,
+	0x1e4d,
+	0x1e4f,
+	0x1e51,
+	0x1e53,
+	0x1e55,
+	0x1e57,
+	0x1e59,
+	0x1e5b,
+	0x1e5d,
+	0x1e5f,
+	0x1e61,
+	0x1e63,
+	0x1e65,
+	0x1e67,
+	0x1e69,
+	0x1e6b,
+	0x1e6d,
+	0x1e6f,
+	0x1e71,
+	0x1e73,
+	0x1e75,
+	0x1e77,
+	0x1e79,
+	0x1e7b,
+	0x1e7d,
+	0x1e7f,
+	0x1e81,
+	0x1e83,
+	0x1e85,
+	0x1e87,
+	0x1e89,
+	0x1e8b,
+	0x1e8d,
+	0x1e8f,
+	0x1e91,
+	0x1e93,
+	0x1e9f,
+	0x1ea1,
+	0x1ea3,
+	0x1ea5,
+	0x1ea7,
+	0x1ea9,
+	0x1eab,
+	0x1ead,
+	0x1eaf,
+	0x1eb1,
+	0x1eb3,
+	0x1eb5,
+	0x1eb7,
+	0x1eb9,
+	0x1ebb,
+	0x1ebd,
+	0x1ebf,
+	0x1ec1,
+	0x1ec3,
+	0x1ec5,
+	0x1ec7,
+	0x1ec9,
+	0x1ecb,
+	0x1ecd,
+	0x1ecf,
+	0x1ed1,
+	0x1ed3,
+	0x1ed5,
+	0x1ed7,
+	0x1ed9,
+	0x1edb,
+	0x1edd,
+	0x1edf,
+	0x1ee1,
+	0x1ee3,
+	0x1ee5,
+	0x1ee7,
+	0x1ee9,
+	0x1eeb,
+	0x1eed,
+	0x1eef,
+	0x1ef1,
+	0x1ef3,
+	0x1ef5,
+	0x1ef7,
+	0x1ef9,
+	0x1efb,
+	0x1efd,
+	0x1fbe,
+	0x210a,
+	0x2113,
+	0x212f,
+	0x2134,
+	0x2139,
+	0x214e,
+	0x2184,
+	0x2c61,
+	0x2c68,
+	0x2c6a,
+	0x2c6c,
+	0x2c71,
+	0x2c81,
+	0x2c83,
+	0x2c85,
+	0x2c87,
+	0x2c89,
+	0x2c8b,
+	0x2c8d,
+	0x2c8f,
+	0x2c91,
+	0x2c93,
+	0x2c95,
+	0x2c97,
+	0x2c99,
+	0x2c9b,
+	0x2c9d,
+	0x2c9f,
+	0x2ca1,
+	0x2ca3,
+	0x2ca5,
+	0x2ca7,
+	0x2ca9,
+	0x2cab,
+	0x2cad,
+	0x2caf,
+	0x2cb1,
+	0x2cb3,
+	0x2cb5,
+	0x2cb7,
+	0x2cb9,
+	0x2cbb,
+	0x2cbd,
+	0x2cbf,
+	0x2cc1,
+	0x2cc3,
+	0x2cc5,
+	0x2cc7,
+	0x2cc9,
+	0x2ccb,
+	0x2ccd,
+	0x2ccf,
+	0x2cd1,
+	0x2cd3,
+	0x2cd5,
+	0x2cd7,
+	0x2cd9,
+	0x2cdb,
+	0x2cdd,
+	0x2cdf,
+	0x2ce1,
+	0x2cec,
+	0x2cee,
+	0x2cf3,
+	0x2d27,
+	0x2d2d,
+	0xa641,
+	0xa643,
+	0xa645,
+	0xa647,
+	0xa649,
+	0xa64b,
+	0xa64d,
+	0xa64f,
+	0xa651,
+	0xa653,
+	0xa655,
+	0xa657,
+	0xa659,
+	0xa65b,
+	0xa65d,
+	0xa65f,
+	0xa661,
+	0xa663,
+	0xa665,
+	0xa667,
+	0xa669,
+	0xa66b,
+	0xa66d,
+	0xa681,
+	0xa683,
+	0xa685,
+	0xa687,
+	0xa689,
+	0xa68b,
+	0xa68d,
+	0xa68f,
+	0xa691,
+	0xa693,
+	0xa695,
+	0xa697,
+	0xa699,
+	0xa69b,
+	0xa723,
+	0xa725,
+	0xa727,
+	0xa729,
+	0xa72b,
+	0xa72d,
+	0xa733,
+	0xa735,
+	0xa737,
+	0xa739,
+	0xa73b,
+	0xa73d,
+	0xa73f,
+	0xa741,
+	0xa743,
+	0xa745,
+	0xa747,
+	0xa749,
+	0xa74b,
+	0xa74d,
+	0xa74f,
+	0xa751,
+	0xa753,
+	0xa755,
+	0xa757,
+	0xa759,
+	0xa75b,
+	0xa75d,
+	0xa75f,
+	0xa761,
+	0xa763,
+	0xa765,
+	0xa767,
+	0xa769,
+	0xa76b,
+	0xa76d,
+	0xa76f,
+	0xa77a,
+	0xa77c,
+	0xa77f,
+	0xa781,
+	0xa783,
+	0xa785,
+	0xa787,
+	0xa78c,
+	0xa78e,
+	0xa791,
+	0xa797,
+	0xa799,
+	0xa79b,
+	0xa79d,
+	0xa79f,
+	0xa7a1,
+	0xa7a3,
+	0xa7a5,
+	0xa7a7,
+	0xa7a9,
+	0xa7fa,
+	0x1d4bb,
+	0x1d7cb,
 };
 
 } // !namespace
 
-bool islower(char32_t c) noexcept
+auto islower(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, islowerr, nelem (islowerr)/2, 2);
+	p = search(c, islowerr, nelem (islowerr) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
- p = rbsearch(c, islowers, nelem (islowers), 1);
+	p = search(c, islowers, nelem (islowers), 1);
 
-   if (p && c == p[0])
-       return true;
+	if (p && c == p[0])
+		return true;
 
- return false;
+	return false;
 }
 
 namespace {
 
 const char32_t istitler[] = {
-    0x0041, 0x005a,
-    0x00c0, 0x00d6,
-    0x00d8, 0x00de,
-    0x0178, 0x0179,
-    0x0181, 0x0182,
-    0x0186, 0x0187,
-    0x0189, 0x018b,
-    0x018e, 0x0191,
-    0x0193, 0x0194,
-    0x0196, 0x0198,
-    0x019c, 0x019d,
-    0x019f, 0x01a0,
-    0x01a6, 0x01a7,
-    0x01ae, 0x01af,
-    0x01b1, 0x01b3,
-    0x01b7, 0x01b8,
-    0x01f6, 0x01f8,
-    0x023a, 0x023b,
-    0x023d, 0x023e,
-    0x0243, 0x0246,
-    0x0388, 0x038a,
-    0x038e, 0x038f,
-    0x0391, 0x03a1,
-    0x03a3, 0x03ab,
-    0x03f9, 0x03fa,
-    0x03fd, 0x042f,
-    0x04c0, 0x04c1,
-    0x0531, 0x0556,
-    0x10a0, 0x10c5,
-    0x1f08, 0x1f0f,
-    0x1f18, 0x1f1d,
-    0x1f28, 0x1f2f,
-    0x1f38, 0x1f3f,
-    0x1f48, 0x1f4d,
-    0x1f68, 0x1f6f,
-    0x1f88, 0x1f8f,
-    0x1f98, 0x1f9f,
-    0x1fa8, 0x1faf,
-    0x1fb8, 0x1fbc,
-    0x1fc8, 0x1fcc,
-    0x1fd8, 0x1fdb,
-    0x1fe8, 0x1fec,
-    0x1ff8, 0x1ffc,
-    0x2160, 0x216f,
-    0x24b6, 0x24cf,
-    0x2c00, 0x2c2e,
-    0x2c62, 0x2c64,
-    0x2c6d, 0x2c70,
-    0x2c7e, 0x2c80,
-    0xa77d, 0xa77e,
-    0xa7aa, 0xa7ad,
-    0xa7b0, 0xa7b1,
-    0xff21, 0xff3a,
-    0x10400, 0x10427,
-    0x118a0, 0x118bf,
+	0x0041, 0x005a,
+	0x00c0, 0x00d6,
+	0x00d8, 0x00de,
+	0x0178, 0x0179,
+	0x0181, 0x0182,
+	0x0186, 0x0187,
+	0x0189, 0x018b,
+	0x018e, 0x0191,
+	0x0193, 0x0194,
+	0x0196, 0x0198,
+	0x019c, 0x019d,
+	0x019f, 0x01a0,
+	0x01a6, 0x01a7,
+	0x01ae, 0x01af,
+	0x01b1, 0x01b3,
+	0x01b7, 0x01b8,
+	0x01f6, 0x01f8,
+	0x023a, 0x023b,
+	0x023d, 0x023e,
+	0x0243, 0x0246,
+	0x0388, 0x038a,
+	0x038e, 0x038f,
+	0x0391, 0x03a1,
+	0x03a3, 0x03ab,
+	0x03f9, 0x03fa,
+	0x03fd, 0x042f,
+	0x04c0, 0x04c1,
+	0x0531, 0x0556,
+	0x10a0, 0x10c5,
+	0x1f08, 0x1f0f,
+	0x1f18, 0x1f1d,
+	0x1f28, 0x1f2f,
+	0x1f38, 0x1f3f,
+	0x1f48, 0x1f4d,
+	0x1f68, 0x1f6f,
+	0x1f88, 0x1f8f,
+	0x1f98, 0x1f9f,
+	0x1fa8, 0x1faf,
+	0x1fb8, 0x1fbc,
+	0x1fc8, 0x1fcc,
+	0x1fd8, 0x1fdb,
+	0x1fe8, 0x1fec,
+	0x1ff8, 0x1ffc,
+	0x2160, 0x216f,
+	0x24b6, 0x24cf,
+	0x2c00, 0x2c2e,
+	0x2c62, 0x2c64,
+	0x2c6d, 0x2c70,
+	0x2c7e, 0x2c80,
+	0xa77d, 0xa77e,
+	0xa7aa, 0xa7ad,
+	0xa7b0, 0xa7b1,
+	0xff21, 0xff3a,
+	0x10400, 0x10427,
+	0x118a0, 0x118bf,
 };
 
 } // !namespace
@@ -2103,594 +2101,594 @@
 namespace {
 
 const char32_t istitles[] = {
-    0x0100,
-    0x0102,
-    0x0104,
-    0x0106,
-    0x0108,
-    0x010a,
-    0x010c,
-    0x010e,
-    0x0110,
-    0x0112,
-    0x0114,
-    0x0116,
-    0x0118,
-    0x011a,
-    0x011c,
-    0x011e,
-    0x0120,
-    0x0122,
-    0x0124,
-    0x0126,
-    0x0128,
-    0x012a,
-    0x012c,
-    0x012e,
-    0x0132,
-    0x0134,
-    0x0136,
-    0x0139,
-    0x013b,
-    0x013d,
-    0x013f,
-    0x0141,
-    0x0143,
-    0x0145,
-    0x0147,
-    0x014a,
-    0x014c,
-    0x014e,
-    0x0150,
-    0x0152,
-    0x0154,
-    0x0156,
-    0x0158,
-    0x015a,
-    0x015c,
-    0x015e,
-    0x0160,
-    0x0162,
-    0x0164,
-    0x0166,
-    0x0168,
-    0x016a,
-    0x016c,
-    0x016e,
-    0x0170,
-    0x0172,
-    0x0174,
-    0x0176,
-    0x017b,
-    0x017d,
-    0x0184,
-    0x01a2,
-    0x01a4,
-    0x01a9,
-    0x01ac,
-    0x01b5,
-    0x01bc,
-    0x01c5,
-    0x01c8,
-    0x01cb,
-    0x01cd,
-    0x01cf,
-    0x01d1,
-    0x01d3,
-    0x01d5,
-    0x01d7,
-    0x01d9,
-    0x01db,
-    0x01de,
-    0x01e0,
-    0x01e2,
-    0x01e4,
-    0x01e6,
-    0x01e8,
-    0x01ea,
-    0x01ec,
-    0x01ee,
-    0x01f2,
-    0x01f4,
-    0x01fa,
-    0x01fc,
-    0x01fe,
-    0x0200,
-    0x0202,
-    0x0204,
-    0x0206,
-    0x0208,
-    0x020a,
-    0x020c,
-    0x020e,
-    0x0210,
-    0x0212,
-    0x0214,
-    0x0216,
-    0x0218,
-    0x021a,
-    0x021c,
-    0x021e,
-    0x0220,
-    0x0222,
-    0x0224,
-    0x0226,
-    0x0228,
-    0x022a,
-    0x022c,
-    0x022e,
-    0x0230,
-    0x0232,
-    0x0241,
-    0x0248,
-    0x024a,
-    0x024c,
-    0x024e,
-    0x0370,
-    0x0372,
-    0x0376,
-    0x037f,
-    0x0386,
-    0x038c,
-    0x03cf,
-    0x03d8,
-    0x03da,
-    0x03dc,
-    0x03de,
-    0x03e0,
-    0x03e2,
-    0x03e4,
-    0x03e6,
-    0x03e8,
-    0x03ea,
-    0x03ec,
-    0x03ee,
-    0x03f7,
-    0x0460,
-    0x0462,
-    0x0464,
-    0x0466,
-    0x0468,
-    0x046a,
-    0x046c,
-    0x046e,
-    0x0470,
-    0x0472,
-    0x0474,
-    0x0476,
-    0x0478,
-    0x047a,
-    0x047c,
-    0x047e,
-    0x0480,
-    0x048a,
-    0x048c,
-    0x048e,
-    0x0490,
-    0x0492,
-    0x0494,
-    0x0496,
-    0x0498,
-    0x049a,
-    0x049c,
-    0x049e,
-    0x04a0,
-    0x04a2,
-    0x04a4,
-    0x04a6,
-    0x04a8,
-    0x04aa,
-    0x04ac,
-    0x04ae,
-    0x04b0,
-    0x04b2,
-    0x04b4,
-    0x04b6,
-    0x04b8,
-    0x04ba,
-    0x04bc,
-    0x04be,
-    0x04c3,
-    0x04c5,
-    0x04c7,
-    0x04c9,
-    0x04cb,
-    0x04cd,
-    0x04d0,
-    0x04d2,
-    0x04d4,
-    0x04d6,
-    0x04d8,
-    0x04da,
-    0x04dc,
-    0x04de,
-    0x04e0,
-    0x04e2,
-    0x04e4,
-    0x04e6,
-    0x04e8,
-    0x04ea,
-    0x04ec,
-    0x04ee,
-    0x04f0,
-    0x04f2,
-    0x04f4,
-    0x04f6,
-    0x04f8,
-    0x04fa,
-    0x04fc,
-    0x04fe,
-    0x0500,
-    0x0502,
-    0x0504,
-    0x0506,
-    0x0508,
-    0x050a,
-    0x050c,
-    0x050e,
-    0x0510,
-    0x0512,
-    0x0514,
-    0x0516,
-    0x0518,
-    0x051a,
-    0x051c,
-    0x051e,
-    0x0520,
-    0x0522,
-    0x0524,
-    0x0526,
-    0x0528,
-    0x052a,
-    0x052c,
-    0x052e,
-    0x10c7,
-    0x10cd,
-    0x1e00,
-    0x1e02,
-    0x1e04,
-    0x1e06,
-    0x1e08,
-    0x1e0a,
-    0x1e0c,
-    0x1e0e,
-    0x1e10,
-    0x1e12,
-    0x1e14,
-    0x1e16,
-    0x1e18,
-    0x1e1a,
-    0x1e1c,
-    0x1e1e,
-    0x1e20,
-    0x1e22,
-    0x1e24,
-    0x1e26,
-    0x1e28,
-    0x1e2a,
-    0x1e2c,
-    0x1e2e,
-    0x1e30,
-    0x1e32,
-    0x1e34,
-    0x1e36,
-    0x1e38,
-    0x1e3a,
-    0x1e3c,
-    0x1e3e,
-    0x1e40,
-    0x1e42,
-    0x1e44,
-    0x1e46,
-    0x1e48,
-    0x1e4a,
-    0x1e4c,
-    0x1e4e,
-    0x1e50,
-    0x1e52,
-    0x1e54,
-    0x1e56,
-    0x1e58,
-    0x1e5a,
-    0x1e5c,
-    0x1e5e,
-    0x1e60,
-    0x1e62,
-    0x1e64,
-    0x1e66,
-    0x1e68,
-    0x1e6a,
-    0x1e6c,
-    0x1e6e,
-    0x1e70,
-    0x1e72,
-    0x1e74,
-    0x1e76,
-    0x1e78,
-    0x1e7a,
-    0x1e7c,
-    0x1e7e,
-    0x1e80,
-    0x1e82,
-    0x1e84,
-    0x1e86,
-    0x1e88,
-    0x1e8a,
-    0x1e8c,
-    0x1e8e,
-    0x1e90,
-    0x1e92,
-    0x1e94,
-    0x1ea0,
-    0x1ea2,
-    0x1ea4,
-    0x1ea6,
-    0x1ea8,
-    0x1eaa,
-    0x1eac,
-    0x1eae,
-    0x1eb0,
-    0x1eb2,
-    0x1eb4,
-    0x1eb6,
-    0x1eb8,
-    0x1eba,
-    0x1ebc,
-    0x1ebe,
-    0x1ec0,
-    0x1ec2,
-    0x1ec4,
-    0x1ec6,
-    0x1ec8,
-    0x1eca,
-    0x1ecc,
-    0x1ece,
-    0x1ed0,
-    0x1ed2,
-    0x1ed4,
-    0x1ed6,
-    0x1ed8,
-    0x1eda,
-    0x1edc,
-    0x1ede,
-    0x1ee0,
-    0x1ee2,
-    0x1ee4,
-    0x1ee6,
-    0x1ee8,
-    0x1eea,
-    0x1eec,
-    0x1eee,
-    0x1ef0,
-    0x1ef2,
-    0x1ef4,
-    0x1ef6,
-    0x1ef8,
-    0x1efa,
-    0x1efc,
-    0x1efe,
-    0x1f59,
-    0x1f5b,
-    0x1f5d,
-    0x1f5f,
-    0x2132,
-    0x2183,
-    0x2c60,
-    0x2c67,
-    0x2c69,
-    0x2c6b,
-    0x2c72,
-    0x2c75,
-    0x2c82,
-    0x2c84,
-    0x2c86,
-    0x2c88,
-    0x2c8a,
-    0x2c8c,
-    0x2c8e,
-    0x2c90,
-    0x2c92,
-    0x2c94,
-    0x2c96,
-    0x2c98,
-    0x2c9a,
-    0x2c9c,
-    0x2c9e,
-    0x2ca0,
-    0x2ca2,
-    0x2ca4,
-    0x2ca6,
-    0x2ca8,
-    0x2caa,
-    0x2cac,
-    0x2cae,
-    0x2cb0,
-    0x2cb2,
-    0x2cb4,
-    0x2cb6,
-    0x2cb8,
-    0x2cba,
-    0x2cbc,
-    0x2cbe,
-    0x2cc0,
-    0x2cc2,
-    0x2cc4,
-    0x2cc6,
-    0x2cc8,
-    0x2cca,
-    0x2ccc,
-    0x2cce,
-    0x2cd0,
-    0x2cd2,
-    0x2cd4,
-    0x2cd6,
-    0x2cd8,
-    0x2cda,
-    0x2cdc,
-    0x2cde,
-    0x2ce0,
-    0x2ce2,
-    0x2ceb,
-    0x2ced,
-    0x2cf2,
-    0xa640,
-    0xa642,
-    0xa644,
-    0xa646,
-    0xa648,
-    0xa64a,
-    0xa64c,
-    0xa64e,
-    0xa650,
-    0xa652,
-    0xa654,
-    0xa656,
-    0xa658,
-    0xa65a,
-    0xa65c,
-    0xa65e,
-    0xa660,
-    0xa662,
-    0xa664,
-    0xa666,
-    0xa668,
-    0xa66a,
-    0xa66c,
-    0xa680,
-    0xa682,
-    0xa684,
-    0xa686,
-    0xa688,
-    0xa68a,
-    0xa68c,
-    0xa68e,
-    0xa690,
-    0xa692,
-    0xa694,
-    0xa696,
-    0xa698,
-    0xa69a,
-    0xa722,
-    0xa724,
-    0xa726,
-    0xa728,
-    0xa72a,
-    0xa72c,
-    0xa72e,
-    0xa732,
-    0xa734,
-    0xa736,
-    0xa738,
-    0xa73a,
-    0xa73c,
-    0xa73e,
-    0xa740,
-    0xa742,
-    0xa744,
-    0xa746,
-    0xa748,
-    0xa74a,
-    0xa74c,
-    0xa74e,
-    0xa750,
-    0xa752,
-    0xa754,
-    0xa756,
-    0xa758,
-    0xa75a,
-    0xa75c,
-    0xa75e,
-    0xa760,
-    0xa762,
-    0xa764,
-    0xa766,
-    0xa768,
-    0xa76a,
-    0xa76c,
-    0xa76e,
-    0xa779,
-    0xa77b,
-    0xa780,
-    0xa782,
-    0xa784,
-    0xa786,
-    0xa78b,
-    0xa78d,
-    0xa790,
-    0xa792,
-    0xa796,
-    0xa798,
-    0xa79a,
-    0xa79c,
-    0xa79e,
-    0xa7a0,
-    0xa7a2,
-    0xa7a4,
-    0xa7a6,
-    0xa7a8,
+	0x0100,
+	0x0102,
+	0x0104,
+	0x0106,
+	0x0108,
+	0x010a,
+	0x010c,
+	0x010e,
+	0x0110,
+	0x0112,
+	0x0114,
+	0x0116,
+	0x0118,
+	0x011a,
+	0x011c,
+	0x011e,
+	0x0120,
+	0x0122,
+	0x0124,
+	0x0126,
+	0x0128,
+	0x012a,
+	0x012c,
+	0x012e,
+	0x0132,
+	0x0134,
+	0x0136,
+	0x0139,
+	0x013b,
+	0x013d,
+	0x013f,
+	0x0141,
+	0x0143,
+	0x0145,
+	0x0147,
+	0x014a,
+	0x014c,
+	0x014e,
+	0x0150,
+	0x0152,
+	0x0154,
+	0x0156,
+	0x0158,
+	0x015a,
+	0x015c,
+	0x015e,
+	0x0160,
+	0x0162,
+	0x0164,
+	0x0166,
+	0x0168,
+	0x016a,
+	0x016c,
+	0x016e,
+	0x0170,
+	0x0172,
+	0x0174,
+	0x0176,
+	0x017b,
+	0x017d,
+	0x0184,
+	0x01a2,
+	0x01a4,
+	0x01a9,
+	0x01ac,
+	0x01b5,
+	0x01bc,
+	0x01c5,
+	0x01c8,
+	0x01cb,
+	0x01cd,
+	0x01cf,
+	0x01d1,
+	0x01d3,
+	0x01d5,
+	0x01d7,
+	0x01d9,
+	0x01db,
+	0x01de,
+	0x01e0,
+	0x01e2,
+	0x01e4,
+	0x01e6,
+	0x01e8,
+	0x01ea,
+	0x01ec,
+	0x01ee,
+	0x01f2,
+	0x01f4,
+	0x01fa,
+	0x01fc,
+	0x01fe,
+	0x0200,
+	0x0202,
+	0x0204,
+	0x0206,
+	0x0208,
+	0x020a,
+	0x020c,
+	0x020e,
+	0x0210,
+	0x0212,
+	0x0214,
+	0x0216,
+	0x0218,
+	0x021a,
+	0x021c,
+	0x021e,
+	0x0220,
+	0x0222,
+	0x0224,
+	0x0226,
+	0x0228,
+	0x022a,
+	0x022c,
+	0x022e,
+	0x0230,
+	0x0232,
+	0x0241,
+	0x0248,
+	0x024a,
+	0x024c,
+	0x024e,
+	0x0370,
+	0x0372,
+	0x0376,
+	0x037f,
+	0x0386,
+	0x038c,
+	0x03cf,
+	0x03d8,
+	0x03da,
+	0x03dc,
+	0x03de,
+	0x03e0,
+	0x03e2,
+	0x03e4,
+	0x03e6,
+	0x03e8,
+	0x03ea,
+	0x03ec,
+	0x03ee,
+	0x03f7,
+	0x0460,
+	0x0462,
+	0x0464,
+	0x0466,
+	0x0468,
+	0x046a,
+	0x046c,
+	0x046e,
+	0x0470,
+	0x0472,
+	0x0474,
+	0x0476,
+	0x0478,
+	0x047a,
+	0x047c,
+	0x047e,
+	0x0480,
+	0x048a,
+	0x048c,
+	0x048e,
+	0x0490,
+	0x0492,
+	0x0494,
+	0x0496,
+	0x0498,
+	0x049a,
+	0x049c,
+	0x049e,
+	0x04a0,
+	0x04a2,
+	0x04a4,
+	0x04a6,
+	0x04a8,
+	0x04aa,
+	0x04ac,
+	0x04ae,
+	0x04b0,
+	0x04b2,
+	0x04b4,
+	0x04b6,
+	0x04b8,
+	0x04ba,
+	0x04bc,
+	0x04be,
+	0x04c3,
+	0x04c5,
+	0x04c7,
+	0x04c9,
+	0x04cb,
+	0x04cd,
+	0x04d0,
+	0x04d2,
+	0x04d4,
+	0x04d6,
+	0x04d8,
+	0x04da,
+	0x04dc,
+	0x04de,
+	0x04e0,
+	0x04e2,
+	0x04e4,
+	0x04e6,
+	0x04e8,
+	0x04ea,
+	0x04ec,
+	0x04ee,
+	0x04f0,
+	0x04f2,
+	0x04f4,
+	0x04f6,
+	0x04f8,
+	0x04fa,
+	0x04fc,
+	0x04fe,
+	0x0500,
+	0x0502,
+	0x0504,
+	0x0506,
+	0x0508,
+	0x050a,
+	0x050c,
+	0x050e,
+	0x0510,
+	0x0512,
+	0x0514,
+	0x0516,
+	0x0518,
+	0x051a,
+	0x051c,
+	0x051e,
+	0x0520,
+	0x0522,
+	0x0524,
+	0x0526,
+	0x0528,
+	0x052a,
+	0x052c,
+	0x052e,
+	0x10c7,
+	0x10cd,
+	0x1e00,
+	0x1e02,
+	0x1e04,
+	0x1e06,
+	0x1e08,
+	0x1e0a,
+	0x1e0c,
+	0x1e0e,
+	0x1e10,
+	0x1e12,
+	0x1e14,
+	0x1e16,
+	0x1e18,
+	0x1e1a,
+	0x1e1c,
+	0x1e1e,
+	0x1e20,
+	0x1e22,
+	0x1e24,
+	0x1e26,
+	0x1e28,
+	0x1e2a,
+	0x1e2c,
+	0x1e2e,
+	0x1e30,
+	0x1e32,
+	0x1e34,
+	0x1e36,
+	0x1e38,
+	0x1e3a,
+	0x1e3c,
+	0x1e3e,
+	0x1e40,
+	0x1e42,
+	0x1e44,
+	0x1e46,
+	0x1e48,
+	0x1e4a,
+	0x1e4c,
+	0x1e4e,
+	0x1e50,
+	0x1e52,
+	0x1e54,
+	0x1e56,
+	0x1e58,
+	0x1e5a,
+	0x1e5c,
+	0x1e5e,
+	0x1e60,
+	0x1e62,
+	0x1e64,
+	0x1e66,
+	0x1e68,
+	0x1e6a,
+	0x1e6c,
+	0x1e6e,
+	0x1e70,
+	0x1e72,
+	0x1e74,
+	0x1e76,
+	0x1e78,
+	0x1e7a,
+	0x1e7c,
+	0x1e7e,
+	0x1e80,
+	0x1e82,
+	0x1e84,
+	0x1e86,
+	0x1e88,
+	0x1e8a,
+	0x1e8c,
+	0x1e8e,
+	0x1e90,
+	0x1e92,
+	0x1e94,
+	0x1ea0,
+	0x1ea2,
+	0x1ea4,
+	0x1ea6,
+	0x1ea8,
+	0x1eaa,
+	0x1eac,
+	0x1eae,
+	0x1eb0,
+	0x1eb2,
+	0x1eb4,
+	0x1eb6,
+	0x1eb8,
+	0x1eba,
+	0x1ebc,
+	0x1ebe,
+	0x1ec0,
+	0x1ec2,
+	0x1ec4,
+	0x1ec6,
+	0x1ec8,
+	0x1eca,
+	0x1ecc,
+	0x1ece,
+	0x1ed0,
+	0x1ed2,
+	0x1ed4,
+	0x1ed6,
+	0x1ed8,
+	0x1eda,
+	0x1edc,
+	0x1ede,
+	0x1ee0,
+	0x1ee2,
+	0x1ee4,
+	0x1ee6,
+	0x1ee8,
+	0x1eea,
+	0x1eec,
+	0x1eee,
+	0x1ef0,
+	0x1ef2,
+	0x1ef4,
+	0x1ef6,
+	0x1ef8,
+	0x1efa,
+	0x1efc,
+	0x1efe,
+	0x1f59,
+	0x1f5b,
+	0x1f5d,
+	0x1f5f,
+	0x2132,
+	0x2183,
+	0x2c60,
+	0x2c67,
+	0x2c69,
+	0x2c6b,
+	0x2c72,
+	0x2c75,
+	0x2c82,
+	0x2c84,
+	0x2c86,
+	0x2c88,
+	0x2c8a,
+	0x2c8c,
+	0x2c8e,
+	0x2c90,
+	0x2c92,
+	0x2c94,
+	0x2c96,
+	0x2c98,
+	0x2c9a,
+	0x2c9c,
+	0x2c9e,
+	0x2ca0,
+	0x2ca2,
+	0x2ca4,
+	0x2ca6,
+	0x2ca8,
+	0x2caa,
+	0x2cac,
+	0x2cae,
+	0x2cb0,
+	0x2cb2,
+	0x2cb4,
+	0x2cb6,
+	0x2cb8,
+	0x2cba,
+	0x2cbc,
+	0x2cbe,
+	0x2cc0,
+	0x2cc2,
+	0x2cc4,
+	0x2cc6,
+	0x2cc8,
+	0x2cca,
+	0x2ccc,
+	0x2cce,
+	0x2cd0,
+	0x2cd2,
+	0x2cd4,
+	0x2cd6,
+	0x2cd8,
+	0x2cda,
+	0x2cdc,
+	0x2cde,
+	0x2ce0,
+	0x2ce2,
+	0x2ceb,
+	0x2ced,
+	0x2cf2,
+	0xa640,
+	0xa642,
+	0xa644,
+	0xa646,
+	0xa648,
+	0xa64a,
+	0xa64c,
+	0xa64e,
+	0xa650,
+	0xa652,
+	0xa654,
+	0xa656,
+	0xa658,
+	0xa65a,
+	0xa65c,
+	0xa65e,
+	0xa660,
+	0xa662,
+	0xa664,
+	0xa666,
+	0xa668,
+	0xa66a,
+	0xa66c,
+	0xa680,
+	0xa682,
+	0xa684,
+	0xa686,
+	0xa688,
+	0xa68a,
+	0xa68c,
+	0xa68e,
+	0xa690,
+	0xa692,
+	0xa694,
+	0xa696,
+	0xa698,
+	0xa69a,
+	0xa722,
+	0xa724,
+	0xa726,
+	0xa728,
+	0xa72a,
+	0xa72c,
+	0xa72e,
+	0xa732,
+	0xa734,
+	0xa736,
+	0xa738,
+	0xa73a,
+	0xa73c,
+	0xa73e,
+	0xa740,
+	0xa742,
+	0xa744,
+	0xa746,
+	0xa748,
+	0xa74a,
+	0xa74c,
+	0xa74e,
+	0xa750,
+	0xa752,
+	0xa754,
+	0xa756,
+	0xa758,
+	0xa75a,
+	0xa75c,
+	0xa75e,
+	0xa760,
+	0xa762,
+	0xa764,
+	0xa766,
+	0xa768,
+	0xa76a,
+	0xa76c,
+	0xa76e,
+	0xa779,
+	0xa77b,
+	0xa780,
+	0xa782,
+	0xa784,
+	0xa786,
+	0xa78b,
+	0xa78d,
+	0xa790,
+	0xa792,
+	0xa796,
+	0xa798,
+	0xa79a,
+	0xa79c,
+	0xa79e,
+	0xa7a0,
+	0xa7a2,
+	0xa7a4,
+	0xa7a6,
+	0xa7a8,
 };
 
 } // !namespace
 
-bool istitle(char32_t c) noexcept
+auto istitle(char32_t c) noexcept -> bool
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, istitler, nelem (istitler)/2, 2);
+	p = search(c, istitler, nelem (istitler) / 2, 2);
 
-   if (p && c >= p[0] && c <= p[1])
-       return true;
+	if (p && c >= p[0] && c <= p[1])
+		return true;
 
- p = rbsearch(c, istitles, nelem (istitles), 1);
+	p = search(c, istitles, nelem (istitles), 1);
 
-   if (p && c == p[0])
-       return true;
+	if (p && c == p[0])
+		return true;
 
- return false;
+	return false;
 }
 
 namespace {
 
 const char32_t toupperr[] = {
-    0x0061, 0x007a, 1048544,
-    0x00e0, 0x00f6, 1048544,
-    0x00f8, 0x00fe, 1048544,
-    0x023f, 0x0240, 1059391,
-    0x0256, 0x0257, 1048371,
-    0x028a, 0x028b, 1048359,
-    0x037b, 0x037d, 1048706,
-    0x03ad, 0x03af, 1048539,
-    0x03b1, 0x03c1, 1048544,
-    0x03c3, 0x03cb, 1048544,
-    0x03cd, 0x03ce, 1048513,
-    0x0430, 0x044f, 1048544,
-    0x0450, 0x045f, 1048496,
-    0x0561, 0x0586, 1048528,
-    0x1f00, 0x1f07, 1048584,
-    0x1f10, 0x1f15, 1048584,
-    0x1f20, 0x1f27, 1048584,
-    0x1f30, 0x1f37, 1048584,
-    0x1f40, 0x1f45, 1048584,
-    0x1f60, 0x1f67, 1048584,
-    0x1f70, 0x1f71, 1048650,
-    0x1f72, 0x1f75, 1048662,
-    0x1f76, 0x1f77, 1048676,
-    0x1f78, 0x1f79, 1048704,
-    0x1f7a, 0x1f7b, 1048688,
-    0x1f7c, 0x1f7d, 1048702,
-    0x1f80, 0x1f87, 1048584,
-    0x1f90, 0x1f97, 1048584,
-    0x1fa0, 0x1fa7, 1048584,
-    0x1fb0, 0x1fb1, 1048584,
-    0x1fd0, 0x1fd1, 1048584,
-    0x1fe0, 0x1fe1, 1048584,
-    0x2170, 0x217f, 1048560,
-    0x24d0, 0x24e9, 1048550,
-    0x2c30, 0x2c5e, 1048528,
-    0x2d00, 0x2d25, 1041312,
-    0xff41, 0xff5a, 1048544,
-    0x10428, 0x1044f, 1048536,
-    0x118c0, 0x118df, 1048544,
+	0x0061, 0x007a, 1048544,
+	0x00e0, 0x00f6, 1048544,
+	0x00f8, 0x00fe, 1048544,
+	0x023f, 0x0240, 1059391,
+	0x0256, 0x0257, 1048371,
+	0x028a, 0x028b, 1048359,
+	0x037b, 0x037d, 1048706,
+	0x03ad, 0x03af, 1048539,
+	0x03b1, 0x03c1, 1048544,
+	0x03c3, 0x03cb, 1048544,
+	0x03cd, 0x03ce, 1048513,
+	0x0430, 0x044f, 1048544,
+	0x0450, 0x045f, 1048496,
+	0x0561, 0x0586, 1048528,
+	0x1f00, 0x1f07, 1048584,
+	0x1f10, 0x1f15, 1048584,
+	0x1f20, 0x1f27, 1048584,
+	0x1f30, 0x1f37, 1048584,
+	0x1f40, 0x1f45, 1048584,
+	0x1f60, 0x1f67, 1048584,
+	0x1f70, 0x1f71, 1048650,
+	0x1f72, 0x1f75, 1048662,
+	0x1f76, 0x1f77, 1048676,
+	0x1f78, 0x1f79, 1048704,
+	0x1f7a, 0x1f7b, 1048688,
+	0x1f7c, 0x1f7d, 1048702,
+	0x1f80, 0x1f87, 1048584,
+	0x1f90, 0x1f97, 1048584,
+	0x1fa0, 0x1fa7, 1048584,
+	0x1fb0, 0x1fb1, 1048584,
+	0x1fd0, 0x1fd1, 1048584,
+	0x1fe0, 0x1fe1, 1048584,
+	0x2170, 0x217f, 1048560,
+	0x24d0, 0x24e9, 1048550,
+	0x2c30, 0x2c5e, 1048528,
+	0x2d00, 0x2d25, 1041312,
+	0xff41, 0xff5a, 1048544,
+	0x10428, 0x1044f, 1048536,
+	0x118c0, 0x118df, 1048544,
 };
 
 } // !namespace
@@ -2698,674 +2696,674 @@
 namespace {
 
 const char32_t touppers[] = {
-    0x00b5, 1049319,
-    0x00ff, 1048697,
-    0x0101, 1048575,
-    0x0103, 1048575,
-    0x0105, 1048575,
-    0x0107, 1048575,
-    0x0109, 1048575,
-    0x010b, 1048575,
-    0x010d, 1048575,
-    0x010f, 1048575,
-    0x0111, 1048575,
-    0x0113, 1048575,
-    0x0115, 1048575,
-    0x0117, 1048575,
-    0x0119, 1048575,
-    0x011b, 1048575,
-    0x011d, 1048575,
-    0x011f, 1048575,
-    0x0121, 1048575,
-    0x0123, 1048575,
-    0x0125, 1048575,
-    0x0127, 1048575,
-    0x0129, 1048575,
-    0x012b, 1048575,
-    0x012d, 1048575,
-    0x012f, 1048575,
-    0x0131, 1048344,
-    0x0133, 1048575,
-    0x0135, 1048575,
-    0x0137, 1048575,
-    0x013a, 1048575,
-    0x013c, 1048575,
-    0x013e, 1048575,
-    0x0140, 1048575,
-    0x0142, 1048575,
-    0x0144, 1048575,
-    0x0146, 1048575,
-    0x0148, 1048575,
-    0x014b, 1048575,
-    0x014d, 1048575,
-    0x014f, 1048575,
-    0x0151, 1048575,
-    0x0153, 1048575,
-    0x0155, 1048575,
-    0x0157, 1048575,
-    0x0159, 1048575,
-    0x015b, 1048575,
-    0x015d, 1048575,
-    0x015f, 1048575,
-    0x0161, 1048575,
-    0x0163, 1048575,
-    0x0165, 1048575,
-    0x0167, 1048575,
-    0x0169, 1048575,
-    0x016b, 1048575,
-    0x016d, 1048575,
-    0x016f, 1048575,
-    0x0171, 1048575,
-    0x0173, 1048575,
-    0x0175, 1048575,
-    0x0177, 1048575,
-    0x017a, 1048575,
-    0x017c, 1048575,
-    0x017e, 1048575,
-    0x017f, 1048276,
-    0x0180, 1048771,
-    0x0183, 1048575,
-    0x0185, 1048575,
-    0x0188, 1048575,
-    0x018c, 1048575,
-    0x0192, 1048575,
-    0x0195, 1048673,
-    0x0199, 1048575,
-    0x019a, 1048739,
-    0x019e, 1048706,
-    0x01a1, 1048575,
-    0x01a3, 1048575,
-    0x01a5, 1048575,
-    0x01a8, 1048575,
-    0x01ad, 1048575,
-    0x01b0, 1048575,
-    0x01b4, 1048575,
-    0x01b6, 1048575,
-    0x01b9, 1048575,
-    0x01bd, 1048575,
-    0x01bf, 1048632,
-    0x01c5, 1048575,
-    0x01c6, 1048574,
-    0x01c8, 1048575,
-    0x01c9, 1048574,
-    0x01cb, 1048575,
-    0x01cc, 1048574,
-    0x01ce, 1048575,
-    0x01d0, 1048575,
-    0x01d2, 1048575,
-    0x01d4, 1048575,
-    0x01d6, 1048575,
-    0x01d8, 1048575,
-    0x01da, 1048575,
-    0x01dc, 1048575,
-    0x01dd, 1048497,
-    0x01df, 1048575,
-    0x01e1, 1048575,
-    0x01e3, 1048575,
-    0x01e5, 1048575,
-    0x01e7, 1048575,
-    0x01e9, 1048575,
-    0x01eb, 1048575,
-    0x01ed, 1048575,
-    0x01ef, 1048575,
-    0x01f2, 1048575,
-    0x01f3, 1048574,
-    0x01f5, 1048575,
-    0x01f9, 1048575,
-    0x01fb, 1048575,
-    0x01fd, 1048575,
-    0x01ff, 1048575,
-    0x0201, 1048575,
-    0x0203, 1048575,
-    0x0205, 1048575,
-    0x0207, 1048575,
-    0x0209, 1048575,
-    0x020b, 1048575,
-    0x020d, 1048575,
-    0x020f, 1048575,
-    0x0211, 1048575,
-    0x0213, 1048575,
-    0x0215, 1048575,
-    0x0217, 1048575,
-    0x0219, 1048575,
-    0x021b, 1048575,
-    0x021d, 1048575,
-    0x021f, 1048575,
-    0x0223, 1048575,
-    0x0225, 1048575,
-    0x0227, 1048575,
-    0x0229, 1048575,
-    0x022b, 1048575,
-    0x022d, 1048575,
-    0x022f, 1048575,
-    0x0231, 1048575,
-    0x0233, 1048575,
-    0x023c, 1048575,
-    0x0242, 1048575,
-    0x0247, 1048575,
-    0x0249, 1048575,
-    0x024b, 1048575,
-    0x024d, 1048575,
-    0x024f, 1048575,
-    0x0250, 1059359,
-    0x0251, 1059356,
-    0x0252, 1059358,
-    0x0253, 1048366,
-    0x0254, 1048370,
-    0x0259, 1048374,
-    0x025b, 1048373,
-    0x025c, 1090895,
-    0x0260, 1048371,
-    0x0261, 1090891,
-    0x0263, 1048369,
-    0x0265, 1090856,
-    0x0266, 1090884,
-    0x0268, 1048367,
-    0x0269, 1048365,
-    0x026b, 1059319,
-    0x026c, 1090881,
-    0x026f, 1048365,
-    0x0271, 1059325,
-    0x0272, 1048363,
-    0x0275, 1048362,
-    0x027d, 1059303,
-    0x0280, 1048358,
-    0x0283, 1048358,
-    0x0287, 1090858,
-    0x0288, 1048358,
-    0x0289, 1048507,
-    0x028c, 1048505,
-    0x0292, 1048357,
-    0x029e, 1090834,
-    0x0345, 1048660,
-    0x0371, 1048575,
-    0x0373, 1048575,
-    0x0377, 1048575,
-    0x03ac, 1048538,
-    0x03c2, 1048545,
-    0x03cc, 1048512,
-    0x03d0, 1048514,
-    0x03d1, 1048519,
-    0x03d5, 1048529,
-    0x03d6, 1048522,
-    0x03d7, 1048568,
-    0x03d9, 1048575,
-    0x03db, 1048575,
-    0x03dd, 1048575,
-    0x03df, 1048575,
-    0x03e1, 1048575,
-    0x03e3, 1048575,
-    0x03e5, 1048575,
-    0x03e7, 1048575,
-    0x03e9, 1048575,
-    0x03eb, 1048575,
-    0x03ed, 1048575,
-    0x03ef, 1048575,
-    0x03f0, 1048490,
-    0x03f1, 1048496,
-    0x03f2, 1048583,
-    0x03f3, 1048460,
-    0x03f5, 1048480,
-    0x03f8, 1048575,
-    0x03fb, 1048575,
-    0x0461, 1048575,
-    0x0463, 1048575,
-    0x0465, 1048575,
-    0x0467, 1048575,
-    0x0469, 1048575,
-    0x046b, 1048575,
-    0x046d, 1048575,
-    0x046f, 1048575,
-    0x0471, 1048575,
-    0x0473, 1048575,
-    0x0475, 1048575,
-    0x0477, 1048575,
-    0x0479, 1048575,
-    0x047b, 1048575,
-    0x047d, 1048575,
-    0x047f, 1048575,
-    0x0481, 1048575,
-    0x048b, 1048575,
-    0x048d, 1048575,
-    0x048f, 1048575,
-    0x0491, 1048575,
-    0x0493, 1048575,
-    0x0495, 1048575,
-    0x0497, 1048575,
-    0x0499, 1048575,
-    0x049b, 1048575,
-    0x049d, 1048575,
-    0x049f, 1048575,
-    0x04a1, 1048575,
-    0x04a3, 1048575,
-    0x04a5, 1048575,
-    0x04a7, 1048575,
-    0x04a9, 1048575,
-    0x04ab, 1048575,
-    0x04ad, 1048575,
-    0x04af, 1048575,
-    0x04b1, 1048575,
-    0x04b3, 1048575,
-    0x04b5, 1048575,
-    0x04b7, 1048575,
-    0x04b9, 1048575,
-    0x04bb, 1048575,
-    0x04bd, 1048575,
-    0x04bf, 1048575,
-    0x04c2, 1048575,
-    0x04c4, 1048575,
-    0x04c6, 1048575,
-    0x04c8, 1048575,
-    0x04ca, 1048575,
-    0x04cc, 1048575,
-    0x04ce, 1048575,
-    0x04cf, 1048561,
-    0x04d1, 1048575,
-    0x04d3, 1048575,
-    0x04d5, 1048575,
-    0x04d7, 1048575,
-    0x04d9, 1048575,
-    0x04db, 1048575,
-    0x04dd, 1048575,
-    0x04df, 1048575,
-    0x04e1, 1048575,
-    0x04e3, 1048575,
-    0x04e5, 1048575,
-    0x04e7, 1048575,
-    0x04e9, 1048575,
-    0x04eb, 1048575,
-    0x04ed, 1048575,
-    0x04ef, 1048575,
-    0x04f1, 1048575,
-    0x04f3, 1048575,
-    0x04f5, 1048575,
-    0x04f7, 1048575,
-    0x04f9, 1048575,
-    0x04fb, 1048575,
-    0x04fd, 1048575,
-    0x04ff, 1048575,
-    0x0501, 1048575,
-    0x0503, 1048575,
-    0x0505, 1048575,
-    0x0507, 1048575,
-    0x0509, 1048575,
-    0x050b, 1048575,
-    0x050d, 1048575,
-    0x050f, 1048575,
-    0x0511, 1048575,
-    0x0513, 1048575,
-    0x0515, 1048575,
-    0x0517, 1048575,
-    0x0519, 1048575,
-    0x051b, 1048575,
-    0x051d, 1048575,
-    0x051f, 1048575,
-    0x0521, 1048575,
-    0x0523, 1048575,
-    0x0525, 1048575,
-    0x0527, 1048575,
-    0x0529, 1048575,
-    0x052b, 1048575,
-    0x052d, 1048575,
-    0x052f, 1048575,
-    0x1d79, 1083908,
-    0x1d7d, 1052390,
-    0x1e01, 1048575,
-    0x1e03, 1048575,
-    0x1e05, 1048575,
-    0x1e07, 1048575,
-    0x1e09, 1048575,
-    0x1e0b, 1048575,
-    0x1e0d, 1048575,
-    0x1e0f, 1048575,
-    0x1e11, 1048575,
-    0x1e13, 1048575,
-    0x1e15, 1048575,
-    0x1e17, 1048575,
-    0x1e19, 1048575,
-    0x1e1b, 1048575,
-    0x1e1d, 1048575,
-    0x1e1f, 1048575,
-    0x1e21, 1048575,
-    0x1e23, 1048575,
-    0x1e25, 1048575,
-    0x1e27, 1048575,
-    0x1e29, 1048575,
-    0x1e2b, 1048575,
-    0x1e2d, 1048575,
-    0x1e2f, 1048575,
-    0x1e31, 1048575,
-    0x1e33, 1048575,
-    0x1e35, 1048575,
-    0x1e37, 1048575,
-    0x1e39, 1048575,
-    0x1e3b, 1048575,
-    0x1e3d, 1048575,
-    0x1e3f, 1048575,
-    0x1e41, 1048575,
-    0x1e43, 1048575,
-    0x1e45, 1048575,
-    0x1e47, 1048575,
-    0x1e49, 1048575,
-    0x1e4b, 1048575,
-    0x1e4d, 1048575,
-    0x1e4f, 1048575,
-    0x1e51, 1048575,
-    0x1e53, 1048575,
-    0x1e55, 1048575,
-    0x1e57, 1048575,
-    0x1e59, 1048575,
-    0x1e5b, 1048575,
-    0x1e5d, 1048575,
-    0x1e5f, 1048575,
-    0x1e61, 1048575,
-    0x1e63, 1048575,
-    0x1e65, 1048575,
-    0x1e67, 1048575,
-    0x1e69, 1048575,
-    0x1e6b, 1048575,
-    0x1e6d, 1048575,
-    0x1e6f, 1048575,
-    0x1e71, 1048575,
-    0x1e73, 1048575,
-    0x1e75, 1048575,
-    0x1e77, 1048575,
-    0x1e79, 1048575,
-    0x1e7b, 1048575,
-    0x1e7d, 1048575,
-    0x1e7f, 1048575,
-    0x1e81, 1048575,
-    0x1e83, 1048575,
-    0x1e85, 1048575,
-    0x1e87, 1048575,
-    0x1e89, 1048575,
-    0x1e8b, 1048575,
-    0x1e8d, 1048575,
-    0x1e8f, 1048575,
-    0x1e91, 1048575,
-    0x1e93, 1048575,
-    0x1e95, 1048575,
-    0x1e9b, 1048517,
-    0x1ea1, 1048575,
-    0x1ea3, 1048575,
-    0x1ea5, 1048575,
-    0x1ea7, 1048575,
-    0x1ea9, 1048575,
-    0x1eab, 1048575,
-    0x1ead, 1048575,
-    0x1eaf, 1048575,
-    0x1eb1, 1048575,
-    0x1eb3, 1048575,
-    0x1eb5, 1048575,
-    0x1eb7, 1048575,
-    0x1eb9, 1048575,
-    0x1ebb, 1048575,
-    0x1ebd, 1048575,
-    0x1ebf, 1048575,
-    0x1ec1, 1048575,
-    0x1ec3, 1048575,
-    0x1ec5, 1048575,
-    0x1ec7, 1048575,
-    0x1ec9, 1048575,
-    0x1ecb, 1048575,
-    0x1ecd, 1048575,
-    0x1ecf, 1048575,
-    0x1ed1, 1048575,
-    0x1ed3, 1048575,
-    0x1ed5, 1048575,
-    0x1ed7, 1048575,
-    0x1ed9, 1048575,
-    0x1edb, 1048575,
-    0x1edd, 1048575,
-    0x1edf, 1048575,
-    0x1ee1, 1048575,
-    0x1ee3, 1048575,
-    0x1ee5, 1048575,
-    0x1ee7, 1048575,
-    0x1ee9, 1048575,
-    0x1eeb, 1048575,
-    0x1eed, 1048575,
-    0x1eef, 1048575,
-    0x1ef1, 1048575,
-    0x1ef3, 1048575,
-    0x1ef5, 1048575,
-    0x1ef7, 1048575,
-    0x1ef9, 1048575,
-    0x1efb, 1048575,
-    0x1efd, 1048575,
-    0x1eff, 1048575,
-    0x1f51, 1048584,
-    0x1f53, 1048584,
-    0x1f55, 1048584,
-    0x1f57, 1048584,
-    0x1fb3, 1048585,
-    0x1fbe, 1041371,
-    0x1fc3, 1048585,
-    0x1fe5, 1048583,
-    0x1ff3, 1048585,
-    0x214e, 1048548,
-    0x2184, 1048575,
-    0x2c61, 1048575,
-    0x2c65, 1037781,
-    0x2c66, 1037784,
-    0x2c68, 1048575,
-    0x2c6a, 1048575,
-    0x2c6c, 1048575,
-    0x2c73, 1048575,
-    0x2c76, 1048575,
-    0x2c81, 1048575,
-    0x2c83, 1048575,
-    0x2c85, 1048575,
-    0x2c87, 1048575,
-    0x2c89, 1048575,
-    0x2c8b, 1048575,
-    0x2c8d, 1048575,
-    0x2c8f, 1048575,
-    0x2c91, 1048575,
-    0x2c93, 1048575,
-    0x2c95, 1048575,
-    0x2c97, 1048575,
-    0x2c99, 1048575,
-    0x2c9b, 1048575,
-    0x2c9d, 1048575,
-    0x2c9f, 1048575,
-    0x2ca1, 1048575,
-    0x2ca3, 1048575,
-    0x2ca5, 1048575,
-    0x2ca7, 1048575,
-    0x2ca9, 1048575,
-    0x2cab, 1048575,
-    0x2cad, 1048575,
-    0x2caf, 1048575,
-    0x2cb1, 1048575,
-    0x2cb3, 1048575,
-    0x2cb5, 1048575,
-    0x2cb7, 1048575,
-    0x2cb9, 1048575,
-    0x2cbb, 1048575,
-    0x2cbd, 1048575,
-    0x2cbf, 1048575,
-    0x2cc1, 1048575,
-    0x2cc3, 1048575,
-    0x2cc5, 1048575,
-    0x2cc7, 1048575,
-    0x2cc9, 1048575,
-    0x2ccb, 1048575,
-    0x2ccd, 1048575,
-    0x2ccf, 1048575,
-    0x2cd1, 1048575,
-    0x2cd3, 1048575,
-    0x2cd5, 1048575,
-    0x2cd7, 1048575,
-    0x2cd9, 1048575,
-    0x2cdb, 1048575,
-    0x2cdd, 1048575,
-    0x2cdf, 1048575,
-    0x2ce1, 1048575,
-    0x2ce3, 1048575,
-    0x2cec, 1048575,
-    0x2cee, 1048575,
-    0x2cf3, 1048575,
-    0x2d27, 1041312,
-    0x2d2d, 1041312,
-    0xa641, 1048575,
-    0xa643, 1048575,
-    0xa645, 1048575,
-    0xa647, 1048575,
-    0xa649, 1048575,
-    0xa64b, 1048575,
-    0xa64d, 1048575,
-    0xa64f, 1048575,
-    0xa651, 1048575,
-    0xa653, 1048575,
-    0xa655, 1048575,
-    0xa657, 1048575,
-    0xa659, 1048575,
-    0xa65b, 1048575,
-    0xa65d, 1048575,
-    0xa65f, 1048575,
-    0xa661, 1048575,
-    0xa663, 1048575,
-    0xa665, 1048575,
-    0xa667, 1048575,
-    0xa669, 1048575,
-    0xa66b, 1048575,
-    0xa66d, 1048575,
-    0xa681, 1048575,
-    0xa683, 1048575,
-    0xa685, 1048575,
-    0xa687, 1048575,
-    0xa689, 1048575,
-    0xa68b, 1048575,
-    0xa68d, 1048575,
-    0xa68f, 1048575,
-    0xa691, 1048575,
-    0xa693, 1048575,
-    0xa695, 1048575,
-    0xa697, 1048575,
-    0xa699, 1048575,
-    0xa69b, 1048575,
-    0xa723, 1048575,
-    0xa725, 1048575,
-    0xa727, 1048575,
-    0xa729, 1048575,
-    0xa72b, 1048575,
-    0xa72d, 1048575,
-    0xa72f, 1048575,
-    0xa733, 1048575,
-    0xa735, 1048575,
-    0xa737, 1048575,
-    0xa739, 1048575,
-    0xa73b, 1048575,
-    0xa73d, 1048575,
-    0xa73f, 1048575,
-    0xa741, 1048575,
-    0xa743, 1048575,
-    0xa745, 1048575,
-    0xa747, 1048575,
-    0xa749, 1048575,
-    0xa74b, 1048575,
-    0xa74d, 1048575,
-    0xa74f, 1048575,
-    0xa751, 1048575,
-    0xa753, 1048575,
-    0xa755, 1048575,
-    0xa757, 1048575,
-    0xa759, 1048575,
-    0xa75b, 1048575,
-    0xa75d, 1048575,
-    0xa75f, 1048575,
-    0xa761, 1048575,
-    0xa763, 1048575,
-    0xa765, 1048575,
-    0xa767, 1048575,
-    0xa769, 1048575,
-    0xa76b, 1048575,
-    0xa76d, 1048575,
-    0xa76f, 1048575,
-    0xa77a, 1048575,
-    0xa77c, 1048575,
-    0xa77f, 1048575,
-    0xa781, 1048575,
-    0xa783, 1048575,
-    0xa785, 1048575,
-    0xa787, 1048575,
-    0xa78c, 1048575,
-    0xa791, 1048575,
-    0xa793, 1048575,
-    0xa797, 1048575,
-    0xa799, 1048575,
-    0xa79b, 1048575,
-    0xa79d, 1048575,
-    0xa79f, 1048575,
-    0xa7a1, 1048575,
-    0xa7a3, 1048575,
-    0xa7a5, 1048575,
-    0xa7a7, 1048575,
-    0xa7a9, 1048575,
+	0x00b5, 1049319,
+	0x00ff, 1048697,
+	0x0101, 1048575,
+	0x0103, 1048575,
+	0x0105, 1048575,
+	0x0107, 1048575,
+	0x0109, 1048575,
+	0x010b, 1048575,
+	0x010d, 1048575,
+	0x010f, 1048575,
+	0x0111, 1048575,
+	0x0113, 1048575,
+	0x0115, 1048575,
+	0x0117, 1048575,
+	0x0119, 1048575,
+	0x011b, 1048575,
+	0x011d, 1048575,
+	0x011f, 1048575,
+	0x0121, 1048575,
+	0x0123, 1048575,
+	0x0125, 1048575,
+	0x0127, 1048575,
+	0x0129, 1048575,
+	0x012b, 1048575,
+	0x012d, 1048575,
+	0x012f, 1048575,
+	0x0131, 1048344,
+	0x0133, 1048575,
+	0x0135, 1048575,
+	0x0137, 1048575,
+	0x013a, 1048575,
+	0x013c, 1048575,
+	0x013e, 1048575,
+	0x0140, 1048575,
+	0x0142, 1048575,
+	0x0144, 1048575,
+	0x0146, 1048575,
+	0x0148, 1048575,
+	0x014b, 1048575,
+	0x014d, 1048575,
+	0x014f, 1048575,
+	0x0151, 1048575,
+	0x0153, 1048575,
+	0x0155, 1048575,
+	0x0157, 1048575,
+	0x0159, 1048575,
+	0x015b, 1048575,
+	0x015d, 1048575,
+	0x015f, 1048575,
+	0x0161, 1048575,
+	0x0163, 1048575,
+	0x0165, 1048575,
+	0x0167, 1048575,
+	0x0169, 1048575,
+	0x016b, 1048575,
+	0x016d, 1048575,
+	0x016f, 1048575,
+	0x0171, 1048575,
+	0x0173, 1048575,
+	0x0175, 1048575,
+	0x0177, 1048575,
+	0x017a, 1048575,
+	0x017c, 1048575,
+	0x017e, 1048575,
+	0x017f, 1048276,
+	0x0180, 1048771,
+	0x0183, 1048575,
+	0x0185, 1048575,
+	0x0188, 1048575,
+	0x018c, 1048575,
+	0x0192, 1048575,
+	0x0195, 1048673,
+	0x0199, 1048575,
+	0x019a, 1048739,
+	0x019e, 1048706,
+	0x01a1, 1048575,
+	0x01a3, 1048575,
+	0x01a5, 1048575,
+	0x01a8, 1048575,
+	0x01ad, 1048575,
+	0x01b0, 1048575,
+	0x01b4, 1048575,
+	0x01b6, 1048575,
+	0x01b9, 1048575,
+	0x01bd, 1048575,
+	0x01bf, 1048632,
+	0x01c5, 1048575,
+	0x01c6, 1048574,
+	0x01c8, 1048575,
+	0x01c9, 1048574,
+	0x01cb, 1048575,
+	0x01cc, 1048574,
+	0x01ce, 1048575,
+	0x01d0, 1048575,
+	0x01d2, 1048575,
+	0x01d4, 1048575,
+	0x01d6, 1048575,
+	0x01d8, 1048575,
+	0x01da, 1048575,
+	0x01dc, 1048575,
+	0x01dd, 1048497,
+	0x01df, 1048575,
+	0x01e1, 1048575,
+	0x01e3, 1048575,
+	0x01e5, 1048575,
+	0x01e7, 1048575,
+	0x01e9, 1048575,
+	0x01eb, 1048575,
+	0x01ed, 1048575,
+	0x01ef, 1048575,
+	0x01f2, 1048575,
+	0x01f3, 1048574,
+	0x01f5, 1048575,
+	0x01f9, 1048575,
+	0x01fb, 1048575,
+	0x01fd, 1048575,
+	0x01ff, 1048575,
+	0x0201, 1048575,
+	0x0203, 1048575,
+	0x0205, 1048575,
+	0x0207, 1048575,
+	0x0209, 1048575,
+	0x020b, 1048575,
+	0x020d, 1048575,
+	0x020f, 1048575,
+	0x0211, 1048575,
+	0x0213, 1048575,
+	0x0215, 1048575,
+	0x0217, 1048575,
+	0x0219, 1048575,
+	0x021b, 1048575,
+	0x021d, 1048575,
+	0x021f, 1048575,
+	0x0223, 1048575,
+	0x0225, 1048575,
+	0x0227, 1048575,
+	0x0229, 1048575,
+	0x022b, 1048575,
+	0x022d, 1048575,
+	0x022f, 1048575,
+	0x0231, 1048575,
+	0x0233, 1048575,
+	0x023c, 1048575,
+	0x0242, 1048575,
+	0x0247, 1048575,
+	0x0249, 1048575,
+	0x024b, 1048575,
+	0x024d, 1048575,
+	0x024f, 1048575,
+	0x0250, 1059359,
+	0x0251, 1059356,
+	0x0252, 1059358,
+	0x0253, 1048366,
+	0x0254, 1048370,
+	0x0259, 1048374,
+	0x025b, 1048373,
+	0x025c, 1090895,
+	0x0260, 1048371,
+	0x0261, 1090891,
+	0x0263, 1048369,
+	0x0265, 1090856,
+	0x0266, 1090884,
+	0x0268, 1048367,
+	0x0269, 1048365,
+	0x026b, 1059319,
+	0x026c, 1090881,
+	0x026f, 1048365,
+	0x0271, 1059325,
+	0x0272, 1048363,
+	0x0275, 1048362,
+	0x027d, 1059303,
+	0x0280, 1048358,
+	0x0283, 1048358,
+	0x0287, 1090858,
+	0x0288, 1048358,
+	0x0289, 1048507,
+	0x028c, 1048505,
+	0x0292, 1048357,
+	0x029e, 1090834,
+	0x0345, 1048660,
+	0x0371, 1048575,
+	0x0373, 1048575,
+	0x0377, 1048575,
+	0x03ac, 1048538,
+	0x03c2, 1048545,
+	0x03cc, 1048512,
+	0x03d0, 1048514,
+	0x03d1, 1048519,
+	0x03d5, 1048529,
+	0x03d6, 1048522,
+	0x03d7, 1048568,
+	0x03d9, 1048575,
+	0x03db, 1048575,
+	0x03dd, 1048575,
+	0x03df, 1048575,
+	0x03e1, 1048575,
+	0x03e3, 1048575,
+	0x03e5, 1048575,
+	0x03e7, 1048575,
+	0x03e9, 1048575,
+	0x03eb, 1048575,
+	0x03ed, 1048575,
+	0x03ef, 1048575,
+	0x03f0, 1048490,
+	0x03f1, 1048496,
+	0x03f2, 1048583,
+	0x03f3, 1048460,
+	0x03f5, 1048480,
+	0x03f8, 1048575,
+	0x03fb, 1048575,
+	0x0461, 1048575,
+	0x0463, 1048575,
+	0x0465, 1048575,
+	0x0467, 1048575,
+	0x0469, 1048575,
+	0x046b, 1048575,
+	0x046d, 1048575,
+	0x046f, 1048575,
+	0x0471, 1048575,
+	0x0473, 1048575,
+	0x0475, 1048575,
+	0x0477, 1048575,
+	0x0479, 1048575,
+	0x047b, 1048575,
+	0x047d, 1048575,
+	0x047f, 1048575,
+	0x0481, 1048575,
+	0x048b, 1048575,
+	0x048d, 1048575,
+	0x048f, 1048575,
+	0x0491, 1048575,
+	0x0493, 1048575,
+	0x0495, 1048575,
+	0x0497, 1048575,
+	0x0499, 1048575,
+	0x049b, 1048575,
+	0x049d, 1048575,
+	0x049f, 1048575,
+	0x04a1, 1048575,
+	0x04a3, 1048575,
+	0x04a5, 1048575,
+	0x04a7, 1048575,
+	0x04a9, 1048575,
+	0x04ab, 1048575,
+	0x04ad, 1048575,
+	0x04af, 1048575,
+	0x04b1, 1048575,
+	0x04b3, 1048575,
+	0x04b5, 1048575,
+	0x04b7, 1048575,
+	0x04b9, 1048575,
+	0x04bb, 1048575,
+	0x04bd, 1048575,
+	0x04bf, 1048575,
+	0x04c2, 1048575,
+	0x04c4, 1048575,
+	0x04c6, 1048575,
+	0x04c8, 1048575,
+	0x04ca, 1048575,
+	0x04cc, 1048575,
+	0x04ce, 1048575,
+	0x04cf, 1048561,
+	0x04d1, 1048575,
+	0x04d3, 1048575,
+	0x04d5, 1048575,
+	0x04d7, 1048575,
+	0x04d9, 1048575,
+	0x04db, 1048575,
+	0x04dd, 1048575,
+	0x04df, 1048575,
+	0x04e1, 1048575,
+	0x04e3, 1048575,
+	0x04e5, 1048575,
+	0x04e7, 1048575,
+	0x04e9, 1048575,
+	0x04eb, 1048575,
+	0x04ed, 1048575,
+	0x04ef, 1048575,
+	0x04f1, 1048575,
+	0x04f3, 1048575,
+	0x04f5, 1048575,
+	0x04f7, 1048575,
+	0x04f9, 1048575,
+	0x04fb, 1048575,
+	0x04fd, 1048575,
+	0x04ff, 1048575,
+	0x0501, 1048575,
+	0x0503, 1048575,
+	0x0505, 1048575,
+	0x0507, 1048575,
+	0x0509, 1048575,
+	0x050b, 1048575,
+	0x050d, 1048575,
+	0x050f, 1048575,
+	0x0511, 1048575,
+	0x0513, 1048575,
+	0x0515, 1048575,
+	0x0517, 1048575,
+	0x0519, 1048575,
+	0x051b, 1048575,
+	0x051d, 1048575,
+	0x051f, 1048575,
+	0x0521, 1048575,
+	0x0523, 1048575,
+	0x0525, 1048575,
+	0x0527, 1048575,
+	0x0529, 1048575,
+	0x052b, 1048575,
+	0x052d, 1048575,
+	0x052f, 1048575,
+	0x1d79, 1083908,
+	0x1d7d, 1052390,
+	0x1e01, 1048575,
+	0x1e03, 1048575,
+	0x1e05, 1048575,
+	0x1e07, 1048575,
+	0x1e09, 1048575,
+	0x1e0b, 1048575,
+	0x1e0d, 1048575,
+	0x1e0f, 1048575,
+	0x1e11, 1048575,
+	0x1e13, 1048575,
+	0x1e15, 1048575,
+	0x1e17, 1048575,
+	0x1e19, 1048575,
+	0x1e1b, 1048575,
+	0x1e1d, 1048575,
+	0x1e1f, 1048575,
+	0x1e21, 1048575,
+	0x1e23, 1048575,
+	0x1e25, 1048575,
+	0x1e27, 1048575,
+	0x1e29, 1048575,
+	0x1e2b, 1048575,
+	0x1e2d, 1048575,
+	0x1e2f, 1048575,
+	0x1e31, 1048575,
+	0x1e33, 1048575,
+	0x1e35, 1048575,
+	0x1e37, 1048575,
+	0x1e39, 1048575,
+	0x1e3b, 1048575,
+	0x1e3d, 1048575,
+	0x1e3f, 1048575,
+	0x1e41, 1048575,
+	0x1e43, 1048575,
+	0x1e45, 1048575,
+	0x1e47, 1048575,
+	0x1e49, 1048575,
+	0x1e4b, 1048575,
+	0x1e4d, 1048575,
+	0x1e4f, 1048575,
+	0x1e51, 1048575,
+	0x1e53, 1048575,
+	0x1e55, 1048575,
+	0x1e57, 1048575,
+	0x1e59, 1048575,
+	0x1e5b, 1048575,
+	0x1e5d, 1048575,
+	0x1e5f, 1048575,
+	0x1e61, 1048575,
+	0x1e63, 1048575,
+	0x1e65, 1048575,
+	0x1e67, 1048575,
+	0x1e69, 1048575,
+	0x1e6b, 1048575,
+	0x1e6d, 1048575,
+	0x1e6f, 1048575,
+	0x1e71, 1048575,
+	0x1e73, 1048575,
+	0x1e75, 1048575,
+	0x1e77, 1048575,
+	0x1e79, 1048575,
+	0x1e7b, 1048575,
+	0x1e7d, 1048575,
+	0x1e7f, 1048575,
+	0x1e81, 1048575,
+	0x1e83, 1048575,
+	0x1e85, 1048575,
+	0x1e87, 1048575,
+	0x1e89, 1048575,
+	0x1e8b, 1048575,
+	0x1e8d, 1048575,
+	0x1e8f, 1048575,
+	0x1e91, 1048575,
+	0x1e93, 1048575,
+	0x1e95, 1048575,
+	0x1e9b, 1048517,
+	0x1ea1, 1048575,
+	0x1ea3, 1048575,
+	0x1ea5, 1048575,
+	0x1ea7, 1048575,
+	0x1ea9, 1048575,
+	0x1eab, 1048575,
+	0x1ead, 1048575,
+	0x1eaf, 1048575,
+	0x1eb1, 1048575,
+	0x1eb3, 1048575,
+	0x1eb5, 1048575,
+	0x1eb7, 1048575,
+	0x1eb9, 1048575,
+	0x1ebb, 1048575,
+	0x1ebd, 1048575,
+	0x1ebf, 1048575,
+	0x1ec1, 1048575,
+	0x1ec3, 1048575,
+	0x1ec5, 1048575,
+	0x1ec7, 1048575,
+	0x1ec9, 1048575,
+	0x1ecb, 1048575,
+	0x1ecd, 1048575,
+	0x1ecf, 1048575,
+	0x1ed1, 1048575,
+	0x1ed3, 1048575,
+	0x1ed5, 1048575,
+	0x1ed7, 1048575,
+	0x1ed9, 1048575,
+	0x1edb, 1048575,
+	0x1edd, 1048575,
+	0x1edf, 1048575,
+	0x1ee1, 1048575,
+	0x1ee3, 1048575,
+	0x1ee5, 1048575,
+	0x1ee7, 1048575,
+	0x1ee9, 1048575,
+	0x1eeb, 1048575,
+	0x1eed, 1048575,
+	0x1eef, 1048575,
+	0x1ef1, 1048575,
+	0x1ef3, 1048575,
+	0x1ef5, 1048575,
+	0x1ef7, 1048575,
+	0x1ef9, 1048575,
+	0x1efb, 1048575,
+	0x1efd, 1048575,
+	0x1eff, 1048575,
+	0x1f51, 1048584,
+	0x1f53, 1048584,
+	0x1f55, 1048584,
+	0x1f57, 1048584,
+	0x1fb3, 1048585,
+	0x1fbe, 1041371,
+	0x1fc3, 1048585,
+	0x1fe5, 1048583,
+	0x1ff3, 1048585,
+	0x214e, 1048548,
+	0x2184, 1048575,
+	0x2c61, 1048575,
+	0x2c65, 1037781,
+	0x2c66, 1037784,
+	0x2c68, 1048575,
+	0x2c6a, 1048575,
+	0x2c6c, 1048575,
+	0x2c73, 1048575,
+	0x2c76, 1048575,
+	0x2c81, 1048575,
+	0x2c83, 1048575,
+	0x2c85, 1048575,
+	0x2c87, 1048575,
+	0x2c89, 1048575,
+	0x2c8b, 1048575,
+	0x2c8d, 1048575,
+	0x2c8f, 1048575,
+	0x2c91, 1048575,
+	0x2c93, 1048575,
+	0x2c95, 1048575,
+	0x2c97, 1048575,
+	0x2c99, 1048575,
+	0x2c9b, 1048575,
+	0x2c9d, 1048575,
+	0x2c9f, 1048575,
+	0x2ca1, 1048575,
+	0x2ca3, 1048575,
+	0x2ca5, 1048575,
+	0x2ca7, 1048575,
+	0x2ca9, 1048575,
+	0x2cab, 1048575,
+	0x2cad, 1048575,
+	0x2caf, 1048575,
+	0x2cb1, 1048575,
+	0x2cb3, 1048575,
+	0x2cb5, 1048575,
+	0x2cb7, 1048575,
+	0x2cb9, 1048575,
+	0x2cbb, 1048575,
+	0x2cbd, 1048575,
+	0x2cbf, 1048575,
+	0x2cc1, 1048575,
+	0x2cc3, 1048575,
+	0x2cc5, 1048575,
+	0x2cc7, 1048575,
+	0x2cc9, 1048575,
+	0x2ccb, 1048575,
+	0x2ccd, 1048575,
+	0x2ccf, 1048575,
+	0x2cd1, 1048575,
+	0x2cd3, 1048575,
+	0x2cd5, 1048575,
+	0x2cd7, 1048575,
+	0x2cd9, 1048575,
+	0x2cdb, 1048575,
+	0x2cdd, 1048575,
+	0x2cdf, 1048575,
+	0x2ce1, 1048575,
+	0x2ce3, 1048575,
+	0x2cec, 1048575,
+	0x2cee, 1048575,
+	0x2cf3, 1048575,
+	0x2d27, 1041312,
+	0x2d2d, 1041312,
+	0xa641, 1048575,
+	0xa643, 1048575,
+	0xa645, 1048575,
+	0xa647, 1048575,
+	0xa649, 1048575,
+	0xa64b, 1048575,
+	0xa64d, 1048575,
+	0xa64f, 1048575,
+	0xa651, 1048575,
+	0xa653, 1048575,
+	0xa655, 1048575,
+	0xa657, 1048575,
+	0xa659, 1048575,
+	0xa65b, 1048575,
+	0xa65d, 1048575,
+	0xa65f, 1048575,
+	0xa661, 1048575,
+	0xa663, 1048575,
+	0xa665, 1048575,
+	0xa667, 1048575,
+	0xa669, 1048575,
+	0xa66b, 1048575,
+	0xa66d, 1048575,
+	0xa681, 1048575,
+	0xa683, 1048575,
+	0xa685, 1048575,
+	0xa687, 1048575,
+	0xa689, 1048575,
+	0xa68b, 1048575,
+	0xa68d, 1048575,
+	0xa68f, 1048575,
+	0xa691, 1048575,
+	0xa693, 1048575,
+	0xa695, 1048575,
+	0xa697, 1048575,
+	0xa699, 1048575,
+	0xa69b, 1048575,
+	0xa723, 1048575,
+	0xa725, 1048575,
+	0xa727, 1048575,
+	0xa729, 1048575,
+	0xa72b, 1048575,
+	0xa72d, 1048575,
+	0xa72f, 1048575,
+	0xa733, 1048575,
+	0xa735, 1048575,
+	0xa737, 1048575,
+	0xa739, 1048575,
+	0xa73b, 1048575,
+	0xa73d, 1048575,
+	0xa73f, 1048575,
+	0xa741, 1048575,
+	0xa743, 1048575,
+	0xa745, 1048575,
+	0xa747, 1048575,
+	0xa749, 1048575,
+	0xa74b, 1048575,
+	0xa74d, 1048575,
+	0xa74f, 1048575,
+	0xa751, 1048575,
+	0xa753, 1048575,
+	0xa755, 1048575,
+	0xa757, 1048575,
+	0xa759, 1048575,
+	0xa75b, 1048575,
+	0xa75d, 1048575,
+	0xa75f, 1048575,
+	0xa761, 1048575,
+	0xa763, 1048575,
+	0xa765, 1048575,
+	0xa767, 1048575,
+	0xa769, 1048575,
+	0xa76b, 1048575,
+	0xa76d, 1048575,
+	0xa76f, 1048575,
+	0xa77a, 1048575,
+	0xa77c, 1048575,
+	0xa77f, 1048575,
+	0xa781, 1048575,
+	0xa783, 1048575,
+	0xa785, 1048575,
+	0xa787, 1048575,
+	0xa78c, 1048575,
+	0xa791, 1048575,
+	0xa793, 1048575,
+	0xa797, 1048575,
+	0xa799, 1048575,
+	0xa79b, 1048575,
+	0xa79d, 1048575,
+	0xa79f, 1048575,
+	0xa7a1, 1048575,
+	0xa7a3, 1048575,
+	0xa7a5, 1048575,
+	0xa7a7, 1048575,
+	0xa7a9, 1048575,
 };
 
 } // !namespace
 
-char32_t toupper(char32_t c) noexcept
+auto toupper(char32_t c) noexcept -> char32_t
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, toupperr, nelem (toupperr)/3, 3);
+	p = search(c, toupperr, nelem (toupperr) / 3, 3);
 
-   if (p && c >= p[0] && c <= p[1])
-       return c + p[2] - 1048576;
+	if (p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
 
- p = rbsearch(c, touppers, nelem (touppers)/2, 2);
+	p = search(c, touppers, nelem (touppers) / 2, 2);
 
-   if (p && c == p[0])
-       return c + p[1] - 1048576;
+	if (p && c == p[0])
+		return c + p[1] - 1048576;
 
-   return c;
+	return c;
 }
 
 namespace {
 
 const char32_t tolowerr[] = {
-    0x0041, 0x005a, 1048608,
-    0x00c0, 0x00d6, 1048608,
-    0x00d8, 0x00de, 1048608,
-    0x0189, 0x018a, 1048781,
-    0x01b1, 0x01b2, 1048793,
-    0x0388, 0x038a, 1048613,
-    0x038e, 0x038f, 1048639,
-    0x0391, 0x03a1, 1048608,
-    0x03a3, 0x03ab, 1048608,
-    0x03fd, 0x03ff, 1048446,
-    0x0400, 0x040f, 1048656,
-    0x0410, 0x042f, 1048608,
-    0x0531, 0x0556, 1048624,
-    0x10a0, 0x10c5, 1055840,
-    0x1f08, 0x1f0f, 1048568,
-    0x1f18, 0x1f1d, 1048568,
-    0x1f28, 0x1f2f, 1048568,
-    0x1f38, 0x1f3f, 1048568,
-    0x1f48, 0x1f4d, 1048568,
-    0x1f68, 0x1f6f, 1048568,
-    0x1f88, 0x1f8f, 1048568,
-    0x1f98, 0x1f9f, 1048568,
-    0x1fa8, 0x1faf, 1048568,
-    0x1fb8, 0x1fb9, 1048568,
-    0x1fba, 0x1fbb, 1048502,
-    0x1fc8, 0x1fcb, 1048490,
-    0x1fd8, 0x1fd9, 1048568,
-    0x1fda, 0x1fdb, 1048476,
-    0x1fe8, 0x1fe9, 1048568,
-    0x1fea, 0x1feb, 1048464,
-    0x1ff8, 0x1ff9, 1048448,
-    0x1ffa, 0x1ffb, 1048450,
-    0x2160, 0x216f, 1048592,
-    0x24b6, 0x24cf, 1048602,
-    0x2c00, 0x2c2e, 1048624,
-    0x2c7e, 0x2c7f, 1037761,
-    0xff21, 0xff3a, 1048608,
-    0x10400, 0x10427, 1048616,
-    0x118a0, 0x118bf, 1048608,
+	0x0041, 0x005a, 1048608,
+	0x00c0, 0x00d6, 1048608,
+	0x00d8, 0x00de, 1048608,
+	0x0189, 0x018a, 1048781,
+	0x01b1, 0x01b2, 1048793,
+	0x0388, 0x038a, 1048613,
+	0x038e, 0x038f, 1048639,
+	0x0391, 0x03a1, 1048608,
+	0x03a3, 0x03ab, 1048608,
+	0x03fd, 0x03ff, 1048446,
+	0x0400, 0x040f, 1048656,
+	0x0410, 0x042f, 1048608,
+	0x0531, 0x0556, 1048624,
+	0x10a0, 0x10c5, 1055840,
+	0x1f08, 0x1f0f, 1048568,
+	0x1f18, 0x1f1d, 1048568,
+	0x1f28, 0x1f2f, 1048568,
+	0x1f38, 0x1f3f, 1048568,
+	0x1f48, 0x1f4d, 1048568,
+	0x1f68, 0x1f6f, 1048568,
+	0x1f88, 0x1f8f, 1048568,
+	0x1f98, 0x1f9f, 1048568,
+	0x1fa8, 0x1faf, 1048568,
+	0x1fb8, 0x1fb9, 1048568,
+	0x1fba, 0x1fbb, 1048502,
+	0x1fc8, 0x1fcb, 1048490,
+	0x1fd8, 0x1fd9, 1048568,
+	0x1fda, 0x1fdb, 1048476,
+	0x1fe8, 0x1fe9, 1048568,
+	0x1fea, 0x1feb, 1048464,
+	0x1ff8, 0x1ff9, 1048448,
+	0x1ffa, 0x1ffb, 1048450,
+	0x2160, 0x216f, 1048592,
+	0x24b6, 0x24cf, 1048602,
+	0x2c00, 0x2c2e, 1048624,
+	0x2c7e, 0x2c7f, 1037761,
+	0xff21, 0xff3a, 1048608,
+	0x10400, 0x10427, 1048616,
+	0x118a0, 0x118bf, 1048608,
 };
 
 } // !namespace
@@ -3373,666 +3371,666 @@
 namespace {
 
 const char32_t tolowers[] = {
-    0x0100, 1048577,
-    0x0102, 1048577,
-    0x0104, 1048577,
-    0x0106, 1048577,
-    0x0108, 1048577,
-    0x010a, 1048577,
-    0x010c, 1048577,
-    0x010e, 1048577,
-    0x0110, 1048577,
-    0x0112, 1048577,
-    0x0114, 1048577,
-    0x0116, 1048577,
-    0x0118, 1048577,
-    0x011a, 1048577,
-    0x011c, 1048577,
-    0x011e, 1048577,
-    0x0120, 1048577,
-    0x0122, 1048577,
-    0x0124, 1048577,
-    0x0126, 1048577,
-    0x0128, 1048577,
-    0x012a, 1048577,
-    0x012c, 1048577,
-    0x012e, 1048577,
-    0x0130, 1048377,
-    0x0132, 1048577,
-    0x0134, 1048577,
-    0x0136, 1048577,
-    0x0139, 1048577,
-    0x013b, 1048577,
-    0x013d, 1048577,
-    0x013f, 1048577,
-    0x0141, 1048577,
-    0x0143, 1048577,
-    0x0145, 1048577,
-    0x0147, 1048577,
-    0x014a, 1048577,
-    0x014c, 1048577,
-    0x014e, 1048577,
-    0x0150, 1048577,
-    0x0152, 1048577,
-    0x0154, 1048577,
-    0x0156, 1048577,
-    0x0158, 1048577,
-    0x015a, 1048577,
-    0x015c, 1048577,
-    0x015e, 1048577,
-    0x0160, 1048577,
-    0x0162, 1048577,
-    0x0164, 1048577,
-    0x0166, 1048577,
-    0x0168, 1048577,
-    0x016a, 1048577,
-    0x016c, 1048577,
-    0x016e, 1048577,
-    0x0170, 1048577,
-    0x0172, 1048577,
-    0x0174, 1048577,
-    0x0176, 1048577,
-    0x0178, 1048455,
-    0x0179, 1048577,
-    0x017b, 1048577,
-    0x017d, 1048577,
-    0x0181, 1048786,
-    0x0182, 1048577,
-    0x0184, 1048577,
-    0x0186, 1048782,
-    0x0187, 1048577,
-    0x018b, 1048577,
-    0x018e, 1048655,
-    0x018f, 1048778,
-    0x0190, 1048779,
-    0x0191, 1048577,
-    0x0193, 1048781,
-    0x0194, 1048783,
-    0x0196, 1048787,
-    0x0197, 1048785,
-    0x0198, 1048577,
-    0x019c, 1048787,
-    0x019d, 1048789,
-    0x019f, 1048790,
-    0x01a0, 1048577,
-    0x01a2, 1048577,
-    0x01a4, 1048577,
-    0x01a6, 1048794,
-    0x01a7, 1048577,
-    0x01a9, 1048794,
-    0x01ac, 1048577,
-    0x01ae, 1048794,
-    0x01af, 1048577,
-    0x01b3, 1048577,
-    0x01b5, 1048577,
-    0x01b7, 1048795,
-    0x01b8, 1048577,
-    0x01bc, 1048577,
-    0x01c4, 1048578,
-    0x01c5, 1048577,
-    0x01c7, 1048578,
-    0x01c8, 1048577,
-    0x01ca, 1048578,
-    0x01cb, 1048577,
-    0x01cd, 1048577,
-    0x01cf, 1048577,
-    0x01d1, 1048577,
-    0x01d3, 1048577,
-    0x01d5, 1048577,
-    0x01d7, 1048577,
-    0x01d9, 1048577,
-    0x01db, 1048577,
-    0x01de, 1048577,
-    0x01e0, 1048577,
-    0x01e2, 1048577,
-    0x01e4, 1048577,
-    0x01e6, 1048577,
-    0x01e8, 1048577,
-    0x01ea, 1048577,
-    0x01ec, 1048577,
-    0x01ee, 1048577,
-    0x01f1, 1048578,
-    0x01f2, 1048577,
-    0x01f4, 1048577,
-    0x01f6, 1048479,
-    0x01f7, 1048520,
-    0x01f8, 1048577,
-    0x01fa, 1048577,
-    0x01fc, 1048577,
-    0x01fe, 1048577,
-    0x0200, 1048577,
-    0x0202, 1048577,
-    0x0204, 1048577,
-    0x0206, 1048577,
-    0x0208, 1048577,
-    0x020a, 1048577,
-    0x020c, 1048577,
-    0x020e, 1048577,
-    0x0210, 1048577,
-    0x0212, 1048577,
-    0x0214, 1048577,
-    0x0216, 1048577,
-    0x0218, 1048577,
-    0x021a, 1048577,
-    0x021c, 1048577,
-    0x021e, 1048577,
-    0x0220, 1048446,
-    0x0222, 1048577,
-    0x0224, 1048577,
-    0x0226, 1048577,
-    0x0228, 1048577,
-    0x022a, 1048577,
-    0x022c, 1048577,
-    0x022e, 1048577,
-    0x0230, 1048577,
-    0x0232, 1048577,
-    0x023a, 1059371,
-    0x023b, 1048577,
-    0x023d, 1048413,
-    0x023e, 1059368,
-    0x0241, 1048577,
-    0x0243, 1048381,
-    0x0244, 1048645,
-    0x0245, 1048647,
-    0x0246, 1048577,
-    0x0248, 1048577,
-    0x024a, 1048577,
-    0x024c, 1048577,
-    0x024e, 1048577,
-    0x0370, 1048577,
-    0x0372, 1048577,
-    0x0376, 1048577,
-    0x037f, 1048692,
-    0x0386, 1048614,
-    0x038c, 1048640,
-    0x03cf, 1048584,
-    0x03d8, 1048577,
-    0x03da, 1048577,
-    0x03dc, 1048577,
-    0x03de, 1048577,
-    0x03e0, 1048577,
-    0x03e2, 1048577,
-    0x03e4, 1048577,
-    0x03e6, 1048577,
-    0x03e8, 1048577,
-    0x03ea, 1048577,
-    0x03ec, 1048577,
-    0x03ee, 1048577,
-    0x03f4, 1048516,
-    0x03f7, 1048577,
-    0x03f9, 1048569,
-    0x03fa, 1048577,
-    0x0460, 1048577,
-    0x0462, 1048577,
-    0x0464, 1048577,
-    0x0466, 1048577,
-    0x0468, 1048577,
-    0x046a, 1048577,
-    0x046c, 1048577,
-    0x046e, 1048577,
-    0x0470, 1048577,
-    0x0472, 1048577,
-    0x0474, 1048577,
-    0x0476, 1048577,
-    0x0478, 1048577,
-    0x047a, 1048577,
-    0x047c, 1048577,
-    0x047e, 1048577,
-    0x0480, 1048577,
-    0x048a, 1048577,
-    0x048c, 1048577,
-    0x048e, 1048577,
-    0x0490, 1048577,
-    0x0492, 1048577,
-    0x0494, 1048577,
-    0x0496, 1048577,
-    0x0498, 1048577,
-    0x049a, 1048577,
-    0x049c, 1048577,
-    0x049e, 1048577,
-    0x04a0, 1048577,
-    0x04a2, 1048577,
-    0x04a4, 1048577,
-    0x04a6, 1048577,
-    0x04a8, 1048577,
-    0x04aa, 1048577,
-    0x04ac, 1048577,
-    0x04ae, 1048577,
-    0x04b0, 1048577,
-    0x04b2, 1048577,
-    0x04b4, 1048577,
-    0x04b6, 1048577,
-    0x04b8, 1048577,
-    0x04ba, 1048577,
-    0x04bc, 1048577,
-    0x04be, 1048577,
-    0x04c0, 1048591,
-    0x04c1, 1048577,
-    0x04c3, 1048577,
-    0x04c5, 1048577,
-    0x04c7, 1048577,
-    0x04c9, 1048577,
-    0x04cb, 1048577,
-    0x04cd, 1048577,
-    0x04d0, 1048577,
-    0x04d2, 1048577,
-    0x04d4, 1048577,
-    0x04d6, 1048577,
-    0x04d8, 1048577,
-    0x04da, 1048577,
-    0x04dc, 1048577,
-    0x04de, 1048577,
-    0x04e0, 1048577,
-    0x04e2, 1048577,
-    0x04e4, 1048577,
-    0x04e6, 1048577,
-    0x04e8, 1048577,
-    0x04ea, 1048577,
-    0x04ec, 1048577,
-    0x04ee, 1048577,
-    0x04f0, 1048577,
-    0x04f2, 1048577,
-    0x04f4, 1048577,
-    0x04f6, 1048577,
-    0x04f8, 1048577,
-    0x04fa, 1048577,
-    0x04fc, 1048577,
-    0x04fe, 1048577,
-    0x0500, 1048577,
-    0x0502, 1048577,
-    0x0504, 1048577,
-    0x0506, 1048577,
-    0x0508, 1048577,
-    0x050a, 1048577,
-    0x050c, 1048577,
-    0x050e, 1048577,
-    0x0510, 1048577,
-    0x0512, 1048577,
-    0x0514, 1048577,
-    0x0516, 1048577,
-    0x0518, 1048577,
-    0x051a, 1048577,
-    0x051c, 1048577,
-    0x051e, 1048577,
-    0x0520, 1048577,
-    0x0522, 1048577,
-    0x0524, 1048577,
-    0x0526, 1048577,
-    0x0528, 1048577,
-    0x052a, 1048577,
-    0x052c, 1048577,
-    0x052e, 1048577,
-    0x10c7, 1055840,
-    0x10cd, 1055840,
-    0x1e00, 1048577,
-    0x1e02, 1048577,
-    0x1e04, 1048577,
-    0x1e06, 1048577,
-    0x1e08, 1048577,
-    0x1e0a, 1048577,
-    0x1e0c, 1048577,
-    0x1e0e, 1048577,
-    0x1e10, 1048577,
-    0x1e12, 1048577,
-    0x1e14, 1048577,
-    0x1e16, 1048577,
-    0x1e18, 1048577,
-    0x1e1a, 1048577,
-    0x1e1c, 1048577,
-    0x1e1e, 1048577,
-    0x1e20, 1048577,
-    0x1e22, 1048577,
-    0x1e24, 1048577,
-    0x1e26, 1048577,
-    0x1e28, 1048577,
-    0x1e2a, 1048577,
-    0x1e2c, 1048577,
-    0x1e2e, 1048577,
-    0x1e30, 1048577,
-    0x1e32, 1048577,
-    0x1e34, 1048577,
-    0x1e36, 1048577,
-    0x1e38, 1048577,
-    0x1e3a, 1048577,
-    0x1e3c, 1048577,
-    0x1e3e, 1048577,
-    0x1e40, 1048577,
-    0x1e42, 1048577,
-    0x1e44, 1048577,
-    0x1e46, 1048577,
-    0x1e48, 1048577,
-    0x1e4a, 1048577,
-    0x1e4c, 1048577,
-    0x1e4e, 1048577,
-    0x1e50, 1048577,
-    0x1e52, 1048577,
-    0x1e54, 1048577,
-    0x1e56, 1048577,
-    0x1e58, 1048577,
-    0x1e5a, 1048577,
-    0x1e5c, 1048577,
-    0x1e5e, 1048577,
-    0x1e60, 1048577,
-    0x1e62, 1048577,
-    0x1e64, 1048577,
-    0x1e66, 1048577,
-    0x1e68, 1048577,
-    0x1e6a, 1048577,
-    0x1e6c, 1048577,
-    0x1e6e, 1048577,
-    0x1e70, 1048577,
-    0x1e72, 1048577,
-    0x1e74, 1048577,
-    0x1e76, 1048577,
-    0x1e78, 1048577,
-    0x1e7a, 1048577,
-    0x1e7c, 1048577,
-    0x1e7e, 1048577,
-    0x1e80, 1048577,
-    0x1e82, 1048577,
-    0x1e84, 1048577,
-    0x1e86, 1048577,
-    0x1e88, 1048577,
-    0x1e8a, 1048577,
-    0x1e8c, 1048577,
-    0x1e8e, 1048577,
-    0x1e90, 1048577,
-    0x1e92, 1048577,
-    0x1e94, 1048577,
-    0x1e9e, 1040961,
-    0x1ea0, 1048577,
-    0x1ea2, 1048577,
-    0x1ea4, 1048577,
-    0x1ea6, 1048577,
-    0x1ea8, 1048577,
-    0x1eaa, 1048577,
-    0x1eac, 1048577,
-    0x1eae, 1048577,
-    0x1eb0, 1048577,
-    0x1eb2, 1048577,
-    0x1eb4, 1048577,
-    0x1eb6, 1048577,
-    0x1eb8, 1048577,
-    0x1eba, 1048577,
-    0x1ebc, 1048577,
-    0x1ebe, 1048577,
-    0x1ec0, 1048577,
-    0x1ec2, 1048577,
-    0x1ec4, 1048577,
-    0x1ec6, 1048577,
-    0x1ec8, 1048577,
-    0x1eca, 1048577,
-    0x1ecc, 1048577,
-    0x1ece, 1048577,
-    0x1ed0, 1048577,
-    0x1ed2, 1048577,
-    0x1ed4, 1048577,
-    0x1ed6, 1048577,
-    0x1ed8, 1048577,
-    0x1eda, 1048577,
-    0x1edc, 1048577,
-    0x1ede, 1048577,
-    0x1ee0, 1048577,
-    0x1ee2, 1048577,
-    0x1ee4, 1048577,
-    0x1ee6, 1048577,
-    0x1ee8, 1048577,
-    0x1eea, 1048577,
-    0x1eec, 1048577,
-    0x1eee, 1048577,
-    0x1ef0, 1048577,
-    0x1ef2, 1048577,
-    0x1ef4, 1048577,
-    0x1ef6, 1048577,
-    0x1ef8, 1048577,
-    0x1efa, 1048577,
-    0x1efc, 1048577,
-    0x1efe, 1048577,
-    0x1f59, 1048568,
-    0x1f5b, 1048568,
-    0x1f5d, 1048568,
-    0x1f5f, 1048568,
-    0x1fbc, 1048567,
-    0x1fcc, 1048567,
-    0x1fec, 1048569,
-    0x1ffc, 1048567,
-    0x2126, 1041059,
-    0x212a, 1040193,
-    0x212b, 1040314,
-    0x2132, 1048604,
-    0x2183, 1048577,
-    0x2c60, 1048577,
-    0x2c62, 1037833,
-    0x2c63, 1044762,
-    0x2c64, 1037849,
-    0x2c67, 1048577,
-    0x2c69, 1048577,
-    0x2c6b, 1048577,
-    0x2c6d, 1037796,
-    0x2c6e, 1037827,
-    0x2c6f, 1037793,
-    0x2c70, 1037794,
-    0x2c72, 1048577,
-    0x2c75, 1048577,
-    0x2c80, 1048577,
-    0x2c82, 1048577,
-    0x2c84, 1048577,
-    0x2c86, 1048577,
-    0x2c88, 1048577,
-    0x2c8a, 1048577,
-    0x2c8c, 1048577,
-    0x2c8e, 1048577,
-    0x2c90, 1048577,
-    0x2c92, 1048577,
-    0x2c94, 1048577,
-    0x2c96, 1048577,
-    0x2c98, 1048577,
-    0x2c9a, 1048577,
-    0x2c9c, 1048577,
-    0x2c9e, 1048577,
-    0x2ca0, 1048577,
-    0x2ca2, 1048577,
-    0x2ca4, 1048577,
-    0x2ca6, 1048577,
-    0x2ca8, 1048577,
-    0x2caa, 1048577,
-    0x2cac, 1048577,
-    0x2cae, 1048577,
-    0x2cb0, 1048577,
-    0x2cb2, 1048577,
-    0x2cb4, 1048577,
-    0x2cb6, 1048577,
-    0x2cb8, 1048577,
-    0x2cba, 1048577,
-    0x2cbc, 1048577,
-    0x2cbe, 1048577,
-    0x2cc0, 1048577,
-    0x2cc2, 1048577,
-    0x2cc4, 1048577,
-    0x2cc6, 1048577,
-    0x2cc8, 1048577,
-    0x2cca, 1048577,
-    0x2ccc, 1048577,
-    0x2cce, 1048577,
-    0x2cd0, 1048577,
-    0x2cd2, 1048577,
-    0x2cd4, 1048577,
-    0x2cd6, 1048577,
-    0x2cd8, 1048577,
-    0x2cda, 1048577,
-    0x2cdc, 1048577,
-    0x2cde, 1048577,
-    0x2ce0, 1048577,
-    0x2ce2, 1048577,
-    0x2ceb, 1048577,
-    0x2ced, 1048577,
-    0x2cf2, 1048577,
-    0xa640, 1048577,
-    0xa642, 1048577,
-    0xa644, 1048577,
-    0xa646, 1048577,
-    0xa648, 1048577,
-    0xa64a, 1048577,
-    0xa64c, 1048577,
-    0xa64e, 1048577,
-    0xa650, 1048577,
-    0xa652, 1048577,
-    0xa654, 1048577,
-    0xa656, 1048577,
-    0xa658, 1048577,
-    0xa65a, 1048577,
-    0xa65c, 1048577,
-    0xa65e, 1048577,
-    0xa660, 1048577,
-    0xa662, 1048577,
-    0xa664, 1048577,
-    0xa666, 1048577,
-    0xa668, 1048577,
-    0xa66a, 1048577,
-    0xa66c, 1048577,
-    0xa680, 1048577,
-    0xa682, 1048577,
-    0xa684, 1048577,
-    0xa686, 1048577,
-    0xa688, 1048577,
-    0xa68a, 1048577,
-    0xa68c, 1048577,
-    0xa68e, 1048577,
-    0xa690, 1048577,
-    0xa692, 1048577,
-    0xa694, 1048577,
-    0xa696, 1048577,
-    0xa698, 1048577,
-    0xa69a, 1048577,
-    0xa722, 1048577,
-    0xa724, 1048577,
-    0xa726, 1048577,
-    0xa728, 1048577,
-    0xa72a, 1048577,
-    0xa72c, 1048577,
-    0xa72e, 1048577,
-    0xa732, 1048577,
-    0xa734, 1048577,
-    0xa736, 1048577,
-    0xa738, 1048577,
-    0xa73a, 1048577,
-    0xa73c, 1048577,
-    0xa73e, 1048577,
-    0xa740, 1048577,
-    0xa742, 1048577,
-    0xa744, 1048577,
-    0xa746, 1048577,
-    0xa748, 1048577,
-    0xa74a, 1048577,
-    0xa74c, 1048577,
-    0xa74e, 1048577,
-    0xa750, 1048577,
-    0xa752, 1048577,
-    0xa754, 1048577,
-    0xa756, 1048577,
-    0xa758, 1048577,
-    0xa75a, 1048577,
-    0xa75c, 1048577,
-    0xa75e, 1048577,
-    0xa760, 1048577,
-    0xa762, 1048577,
-    0xa764, 1048577,
-    0xa766, 1048577,
-    0xa768, 1048577,
-    0xa76a, 1048577,
-    0xa76c, 1048577,
-    0xa76e, 1048577,
-    0xa779, 1048577,
-    0xa77b, 1048577,
-    0xa77d, 1013244,
-    0xa77e, 1048577,
-    0xa780, 1048577,
-    0xa782, 1048577,
-    0xa784, 1048577,
-    0xa786, 1048577,
-    0xa78b, 1048577,
-    0xa78d, 1006296,
-    0xa790, 1048577,
-    0xa792, 1048577,
-    0xa796, 1048577,
-    0xa798, 1048577,
-    0xa79a, 1048577,
-    0xa79c, 1048577,
-    0xa79e, 1048577,
-    0xa7a0, 1048577,
-    0xa7a2, 1048577,
-    0xa7a4, 1048577,
-    0xa7a6, 1048577,
-    0xa7a8, 1048577,
-    0xa7aa, 1006268,
-    0xa7ab, 1006257,
-    0xa7ac, 1006261,
-    0xa7ad, 1006271,
-    0xa7b0, 1006318,
-    0xa7b1, 1006294,
+	0x0100, 1048577,
+	0x0102, 1048577,
+	0x0104, 1048577,
+	0x0106, 1048577,
+	0x0108, 1048577,
+	0x010a, 1048577,
+	0x010c, 1048577,
+	0x010e, 1048577,
+	0x0110, 1048577,
+	0x0112, 1048577,
+	0x0114, 1048577,
+	0x0116, 1048577,
+	0x0118, 1048577,
+	0x011a, 1048577,
+	0x011c, 1048577,
+	0x011e, 1048577,
+	0x0120, 1048577,
+	0x0122, 1048577,
+	0x0124, 1048577,
+	0x0126, 1048577,
+	0x0128, 1048577,
+	0x012a, 1048577,
+	0x012c, 1048577,
+	0x012e, 1048577,
+	0x0130, 1048377,
+	0x0132, 1048577,
+	0x0134, 1048577,
+	0x0136, 1048577,
+	0x0139, 1048577,
+	0x013b, 1048577,
+	0x013d, 1048577,
+	0x013f, 1048577,
+	0x0141, 1048577,
+	0x0143, 1048577,
+	0x0145, 1048577,
+	0x0147, 1048577,
+	0x014a, 1048577,
+	0x014c, 1048577,
+	0x014e, 1048577,
+	0x0150, 1048577,
+	0x0152, 1048577,
+	0x0154, 1048577,
+	0x0156, 1048577,
+	0x0158, 1048577,
+	0x015a, 1048577,
+	0x015c, 1048577,
+	0x015e, 1048577,
+	0x0160, 1048577,
+	0x0162, 1048577,
+	0x0164, 1048577,
+	0x0166, 1048577,
+	0x0168, 1048577,
+	0x016a, 1048577,
+	0x016c, 1048577,
+	0x016e, 1048577,
+	0x0170, 1048577,
+	0x0172, 1048577,
+	0x0174, 1048577,
+	0x0176, 1048577,
+	0x0178, 1048455,
+	0x0179, 1048577,
+	0x017b, 1048577,
+	0x017d, 1048577,
+	0x0181, 1048786,
+	0x0182, 1048577,
+	0x0184, 1048577,
+	0x0186, 1048782,
+	0x0187, 1048577,
+	0x018b, 1048577,
+	0x018e, 1048655,
+	0x018f, 1048778,
+	0x0190, 1048779,
+	0x0191, 1048577,
+	0x0193, 1048781,
+	0x0194, 1048783,
+	0x0196, 1048787,
+	0x0197, 1048785,
+	0x0198, 1048577,
+	0x019c, 1048787,
+	0x019d, 1048789,
+	0x019f, 1048790,
+	0x01a0, 1048577,
+	0x01a2, 1048577,
+	0x01a4, 1048577,
+	0x01a6, 1048794,
+	0x01a7, 1048577,
+	0x01a9, 1048794,
+	0x01ac, 1048577,
+	0x01ae, 1048794,
+	0x01af, 1048577,
+	0x01b3, 1048577,
+	0x01b5, 1048577,
+	0x01b7, 1048795,
+	0x01b8, 1048577,
+	0x01bc, 1048577,
+	0x01c4, 1048578,
+	0x01c5, 1048577,
+	0x01c7, 1048578,
+	0x01c8, 1048577,
+	0x01ca, 1048578,
+	0x01cb, 1048577,
+	0x01cd, 1048577,
+	0x01cf, 1048577,
+	0x01d1, 1048577,
+	0x01d3, 1048577,
+	0x01d5, 1048577,
+	0x01d7, 1048577,
+	0x01d9, 1048577,
+	0x01db, 1048577,
+	0x01de, 1048577,
+	0x01e0, 1048577,
+	0x01e2, 1048577,
+	0x01e4, 1048577,
+	0x01e6, 1048577,
+	0x01e8, 1048577,
+	0x01ea, 1048577,
+	0x01ec, 1048577,
+	0x01ee, 1048577,
+	0x01f1, 1048578,
+	0x01f2, 1048577,
+	0x01f4, 1048577,
+	0x01f6, 1048479,
+	0x01f7, 1048520,
+	0x01f8, 1048577,
+	0x01fa, 1048577,
+	0x01fc, 1048577,
+	0x01fe, 1048577,
+	0x0200, 1048577,
+	0x0202, 1048577,
+	0x0204, 1048577,
+	0x0206, 1048577,
+	0x0208, 1048577,
+	0x020a, 1048577,
+	0x020c, 1048577,
+	0x020e, 1048577,
+	0x0210, 1048577,
+	0x0212, 1048577,
+	0x0214, 1048577,
+	0x0216, 1048577,
+	0x0218, 1048577,
+	0x021a, 1048577,
+	0x021c, 1048577,
+	0x021e, 1048577,
+	0x0220, 1048446,
+	0x0222, 1048577,
+	0x0224, 1048577,
+	0x0226, 1048577,
+	0x0228, 1048577,
+	0x022a, 1048577,
+	0x022c, 1048577,
+	0x022e, 1048577,
+	0x0230, 1048577,
+	0x0232, 1048577,
+	0x023a, 1059371,
+	0x023b, 1048577,
+	0x023d, 1048413,
+	0x023e, 1059368,
+	0x0241, 1048577,
+	0x0243, 1048381,
+	0x0244, 1048645,
+	0x0245, 1048647,
+	0x0246, 1048577,
+	0x0248, 1048577,
+	0x024a, 1048577,
+	0x024c, 1048577,
+	0x024e, 1048577,
+	0x0370, 1048577,
+	0x0372, 1048577,
+	0x0376, 1048577,
+	0x037f, 1048692,
+	0x0386, 1048614,
+	0x038c, 1048640,
+	0x03cf, 1048584,
+	0x03d8, 1048577,
+	0x03da, 1048577,
+	0x03dc, 1048577,
+	0x03de, 1048577,
+	0x03e0, 1048577,
+	0x03e2, 1048577,
+	0x03e4, 1048577,
+	0x03e6, 1048577,
+	0x03e8, 1048577,
+	0x03ea, 1048577,
+	0x03ec, 1048577,
+	0x03ee, 1048577,
+	0x03f4, 1048516,
+	0x03f7, 1048577,
+	0x03f9, 1048569,
+	0x03fa, 1048577,
+	0x0460, 1048577,
+	0x0462, 1048577,
+	0x0464, 1048577,
+	0x0466, 1048577,
+	0x0468, 1048577,
+	0x046a, 1048577,
+	0x046c, 1048577,
+	0x046e, 1048577,
+	0x0470, 1048577,
+	0x0472, 1048577,
+	0x0474, 1048577,
+	0x0476, 1048577,
+	0x0478, 1048577,
+	0x047a, 1048577,
+	0x047c, 1048577,
+	0x047e, 1048577,
+	0x0480, 1048577,
+	0x048a, 1048577,
+	0x048c, 1048577,
+	0x048e, 1048577,
+	0x0490, 1048577,
+	0x0492, 1048577,
+	0x0494, 1048577,
+	0x0496, 1048577,
+	0x0498, 1048577,
+	0x049a, 1048577,
+	0x049c, 1048577,
+	0x049e, 1048577,
+	0x04a0, 1048577,
+	0x04a2, 1048577,
+	0x04a4, 1048577,
+	0x04a6, 1048577,
+	0x04a8, 1048577,
+	0x04aa, 1048577,
+	0x04ac, 1048577,
+	0x04ae, 1048577,
+	0x04b0, 1048577,
+	0x04b2, 1048577,
+	0x04b4, 1048577,
+	0x04b6, 1048577,
+	0x04b8, 1048577,
+	0x04ba, 1048577,
+	0x04bc, 1048577,
+	0x04be, 1048577,
+	0x04c0, 1048591,
+	0x04c1, 1048577,
+	0x04c3, 1048577,
+	0x04c5, 1048577,
+	0x04c7, 1048577,
+	0x04c9, 1048577,
+	0x04cb, 1048577,
+	0x04cd, 1048577,
+	0x04d0, 1048577,
+	0x04d2, 1048577,
+	0x04d4, 1048577,
+	0x04d6, 1048577,
+	0x04d8, 1048577,
+	0x04da, 1048577,
+	0x04dc, 1048577,
+	0x04de, 1048577,
+	0x04e0, 1048577,
+	0x04e2, 1048577,
+	0x04e4, 1048577,
+	0x04e6, 1048577,
+	0x04e8, 1048577,
+	0x04ea, 1048577,
+	0x04ec, 1048577,
+	0x04ee, 1048577,
+	0x04f0, 1048577,
+	0x04f2, 1048577,
+	0x04f4, 1048577,
+	0x04f6, 1048577,
+	0x04f8, 1048577,
+	0x04fa, 1048577,
+	0x04fc, 1048577,
+	0x04fe, 1048577,
+	0x0500, 1048577,
+	0x0502, 1048577,
+	0x0504, 1048577,
+	0x0506, 1048577,
+	0x0508, 1048577,
+	0x050a, 1048577,
+	0x050c, 1048577,
+	0x050e, 1048577,
+	0x0510, 1048577,
+	0x0512, 1048577,
+	0x0514, 1048577,
+	0x0516, 1048577,
+	0x0518, 1048577,
+	0x051a, 1048577,
+	0x051c, 1048577,
+	0x051e, 1048577,
+	0x0520, 1048577,
+	0x0522, 1048577,
+	0x0524, 1048577,
+	0x0526, 1048577,
+	0x0528, 1048577,
+	0x052a, 1048577,
+	0x052c, 1048577,
+	0x052e, 1048577,
+	0x10c7, 1055840,
+	0x10cd, 1055840,
+	0x1e00, 1048577,
+	0x1e02, 1048577,
+	0x1e04, 1048577,
+	0x1e06, 1048577,
+	0x1e08, 1048577,
+	0x1e0a, 1048577,
+	0x1e0c, 1048577,
+	0x1e0e, 1048577,
+	0x1e10, 1048577,
+	0x1e12, 1048577,
+	0x1e14, 1048577,
+	0x1e16, 1048577,
+	0x1e18, 1048577,
+	0x1e1a, 1048577,
+	0x1e1c, 1048577,
+	0x1e1e, 1048577,
+	0x1e20, 1048577,
+	0x1e22, 1048577,
+	0x1e24, 1048577,
+	0x1e26, 1048577,
+	0x1e28, 1048577,
+	0x1e2a, 1048577,
+	0x1e2c, 1048577,
+	0x1e2e, 1048577,
+	0x1e30, 1048577,
+	0x1e32, 1048577,
+	0x1e34, 1048577,
+	0x1e36, 1048577,
+	0x1e38, 1048577,
+	0x1e3a, 1048577,
+	0x1e3c, 1048577,
+	0x1e3e, 1048577,
+	0x1e40, 1048577,
+	0x1e42, 1048577,
+	0x1e44, 1048577,
+	0x1e46, 1048577,
+	0x1e48, 1048577,
+	0x1e4a, 1048577,
+	0x1e4c, 1048577,
+	0x1e4e, 1048577,
+	0x1e50, 1048577,
+	0x1e52, 1048577,
+	0x1e54, 1048577,
+	0x1e56, 1048577,
+	0x1e58, 1048577,
+	0x1e5a, 1048577,
+	0x1e5c, 1048577,
+	0x1e5e, 1048577,
+	0x1e60, 1048577,
+	0x1e62, 1048577,
+	0x1e64, 1048577,
+	0x1e66, 1048577,
+	0x1e68, 1048577,
+	0x1e6a, 1048577,
+	0x1e6c, 1048577,
+	0x1e6e, 1048577,
+	0x1e70, 1048577,
+	0x1e72, 1048577,
+	0x1e74, 1048577,
+	0x1e76, 1048577,
+	0x1e78, 1048577,
+	0x1e7a, 1048577,
+	0x1e7c, 1048577,
+	0x1e7e, 1048577,
+	0x1e80, 1048577,
+	0x1e82, 1048577,
+	0x1e84, 1048577,
+	0x1e86, 1048577,
+	0x1e88, 1048577,
+	0x1e8a, 1048577,
+	0x1e8c, 1048577,
+	0x1e8e, 1048577,
+	0x1e90, 1048577,
+	0x1e92, 1048577,
+	0x1e94, 1048577,
+	0x1e9e, 1040961,
+	0x1ea0, 1048577,
+	0x1ea2, 1048577,
+	0x1ea4, 1048577,
+	0x1ea6, 1048577,
+	0x1ea8, 1048577,
+	0x1eaa, 1048577,
+	0x1eac, 1048577,
+	0x1eae, 1048577,
+	0x1eb0, 1048577,
+	0x1eb2, 1048577,
+	0x1eb4, 1048577,
+	0x1eb6, 1048577,
+	0x1eb8, 1048577,
+	0x1eba, 1048577,
+	0x1ebc, 1048577,
+	0x1ebe, 1048577,
+	0x1ec0, 1048577,
+	0x1ec2, 1048577,
+	0x1ec4, 1048577,
+	0x1ec6, 1048577,
+	0x1ec8, 1048577,
+	0x1eca, 1048577,
+	0x1ecc, 1048577,
+	0x1ece, 1048577,
+	0x1ed0, 1048577,
+	0x1ed2, 1048577,
+	0x1ed4, 1048577,
+	0x1ed6, 1048577,
+	0x1ed8, 1048577,
+	0x1eda, 1048577,
+	0x1edc, 1048577,
+	0x1ede, 1048577,
+	0x1ee0, 1048577,
+	0x1ee2, 1048577,
+	0x1ee4, 1048577,
+	0x1ee6, 1048577,
+	0x1ee8, 1048577,
+	0x1eea, 1048577,
+	0x1eec, 1048577,
+	0x1eee, 1048577,
+	0x1ef0, 1048577,
+	0x1ef2, 1048577,
+	0x1ef4, 1048577,
+	0x1ef6, 1048577,
+	0x1ef8, 1048577,
+	0x1efa, 1048577,
+	0x1efc, 1048577,
+	0x1efe, 1048577,
+	0x1f59, 1048568,
+	0x1f5b, 1048568,
+	0x1f5d, 1048568,
+	0x1f5f, 1048568,
+	0x1fbc, 1048567,
+	0x1fcc, 1048567,
+	0x1fec, 1048569,
+	0x1ffc, 1048567,
+	0x2126, 1041059,
+	0x212a, 1040193,
+	0x212b, 1040314,
+	0x2132, 1048604,
+	0x2183, 1048577,
+	0x2c60, 1048577,
+	0x2c62, 1037833,
+	0x2c63, 1044762,
+	0x2c64, 1037849,
+	0x2c67, 1048577,
+	0x2c69, 1048577,
+	0x2c6b, 1048577,
+	0x2c6d, 1037796,
+	0x2c6e, 1037827,
+	0x2c6f, 1037793,
+	0x2c70, 1037794,
+	0x2c72, 1048577,
+	0x2c75, 1048577,
+	0x2c80, 1048577,
+	0x2c82, 1048577,
+	0x2c84, 1048577,
+	0x2c86, 1048577,
+	0x2c88, 1048577,
+	0x2c8a, 1048577,
+	0x2c8c, 1048577,
+	0x2c8e, 1048577,
+	0x2c90, 1048577,
+	0x2c92, 1048577,
+	0x2c94, 1048577,
+	0x2c96, 1048577,
+	0x2c98, 1048577,
+	0x2c9a, 1048577,
+	0x2c9c, 1048577,
+	0x2c9e, 1048577,
+	0x2ca0, 1048577,
+	0x2ca2, 1048577,
+	0x2ca4, 1048577,
+	0x2ca6, 1048577,
+	0x2ca8, 1048577,
+	0x2caa, 1048577,
+	0x2cac, 1048577,
+	0x2cae, 1048577,
+	0x2cb0, 1048577,
+	0x2cb2, 1048577,
+	0x2cb4, 1048577,
+	0x2cb6, 1048577,
+	0x2cb8, 1048577,
+	0x2cba, 1048577,
+	0x2cbc, 1048577,
+	0x2cbe, 1048577,
+	0x2cc0, 1048577,
+	0x2cc2, 1048577,
+	0x2cc4, 1048577,
+	0x2cc6, 1048577,
+	0x2cc8, 1048577,
+	0x2cca, 1048577,
+	0x2ccc, 1048577,
+	0x2cce, 1048577,
+	0x2cd0, 1048577,
+	0x2cd2, 1048577,
+	0x2cd4, 1048577,
+	0x2cd6, 1048577,
+	0x2cd8, 1048577,
+	0x2cda, 1048577,
+	0x2cdc, 1048577,
+	0x2cde, 1048577,
+	0x2ce0, 1048577,
+	0x2ce2, 1048577,
+	0x2ceb, 1048577,
+	0x2ced, 1048577,
+	0x2cf2, 1048577,
+	0xa640, 1048577,
+	0xa642, 1048577,
+	0xa644, 1048577,
+	0xa646, 1048577,
+	0xa648, 1048577,
+	0xa64a, 1048577,
+	0xa64c, 1048577,
+	0xa64e, 1048577,
+	0xa650, 1048577,
+	0xa652, 1048577,
+	0xa654, 1048577,
+	0xa656, 1048577,
+	0xa658, 1048577,
+	0xa65a, 1048577,
+	0xa65c, 1048577,
+	0xa65e, 1048577,
+	0xa660, 1048577,
+	0xa662, 1048577,
+	0xa664, 1048577,
+	0xa666, 1048577,
+	0xa668, 1048577,
+	0xa66a, 1048577,
+	0xa66c, 1048577,
+	0xa680, 1048577,
+	0xa682, 1048577,
+	0xa684, 1048577,
+	0xa686, 1048577,
+	0xa688, 1048577,
+	0xa68a, 1048577,
+	0xa68c, 1048577,
+	0xa68e, 1048577,
+	0xa690, 1048577,
+	0xa692, 1048577,
+	0xa694, 1048577,
+	0xa696, 1048577,
+	0xa698, 1048577,
+	0xa69a, 1048577,
+	0xa722, 1048577,
+	0xa724, 1048577,
+	0xa726, 1048577,
+	0xa728, 1048577,
+	0xa72a, 1048577,
+	0xa72c, 1048577,
+	0xa72e, 1048577,
+	0xa732, 1048577,
+	0xa734, 1048577,
+	0xa736, 1048577,
+	0xa738, 1048577,
+	0xa73a, 1048577,
+	0xa73c, 1048577,
+	0xa73e, 1048577,
+	0xa740, 1048577,
+	0xa742, 1048577,
+	0xa744, 1048577,
+	0xa746, 1048577,
+	0xa748, 1048577,
+	0xa74a, 1048577,
+	0xa74c, 1048577,
+	0xa74e, 1048577,
+	0xa750, 1048577,
+	0xa752, 1048577,
+	0xa754, 1048577,
+	0xa756, 1048577,
+	0xa758, 1048577,
+	0xa75a, 1048577,
+	0xa75c, 1048577,
+	0xa75e, 1048577,
+	0xa760, 1048577,
+	0xa762, 1048577,
+	0xa764, 1048577,
+	0xa766, 1048577,
+	0xa768, 1048577,
+	0xa76a, 1048577,
+	0xa76c, 1048577,
+	0xa76e, 1048577,
+	0xa779, 1048577,
+	0xa77b, 1048577,
+	0xa77d, 1013244,
+	0xa77e, 1048577,
+	0xa780, 1048577,
+	0xa782, 1048577,
+	0xa784, 1048577,
+	0xa786, 1048577,
+	0xa78b, 1048577,
+	0xa78d, 1006296,
+	0xa790, 1048577,
+	0xa792, 1048577,
+	0xa796, 1048577,
+	0xa798, 1048577,
+	0xa79a, 1048577,
+	0xa79c, 1048577,
+	0xa79e, 1048577,
+	0xa7a0, 1048577,
+	0xa7a2, 1048577,
+	0xa7a4, 1048577,
+	0xa7a6, 1048577,
+	0xa7a8, 1048577,
+	0xa7aa, 1006268,
+	0xa7ab, 1006257,
+	0xa7ac, 1006261,
+	0xa7ad, 1006271,
+	0xa7b0, 1006318,
+	0xa7b1, 1006294,
 };
 
 } // !namespace
 
-char32_t tolower(char32_t c) noexcept
+auto tolower(char32_t c) noexcept -> char32_t
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, tolowerr, nelem (tolowerr)/3, 3);
+	p = search(c, tolowerr, nelem (tolowerr) / 3, 3);
 
-   if (p && c >= p[0] && c <= p[1])
-       return c + p[2] - 1048576;
+	if (p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
 
- p = rbsearch(c, tolowers, nelem (tolowers)/2, 2);
+	p = search(c, tolowers, nelem (tolowers) / 2, 2);
 
-   if (p && c == p[0])
-       return c + p[1] - 1048576;
+	if (p && c == p[0])
+		return c + p[1] - 1048576;
 
-   return c;
+	return c;
 }
 
 namespace {
 
 const char32_t totitler[] = {
-    0x0061, 0x007a, 1048544,
-    0x00e0, 0x00f6, 1048544,
-    0x00f8, 0x00fe, 1048544,
-    0x023f, 0x0240, 1059391,
-    0x0256, 0x0257, 1048371,
-    0x028a, 0x028b, 1048359,
-    0x037b, 0x037d, 1048706,
-    0x03ad, 0x03af, 1048539,
-    0x03b1, 0x03c1, 1048544,
-    0x03c3, 0x03cb, 1048544,
-    0x03cd, 0x03ce, 1048513,
-    0x0430, 0x044f, 1048544,
-    0x0450, 0x045f, 1048496,
-    0x0561, 0x0586, 1048528,
-    0x1f00, 0x1f07, 1048584,
-    0x1f10, 0x1f15, 1048584,
-    0x1f20, 0x1f27, 1048584,
-    0x1f30, 0x1f37, 1048584,
-    0x1f40, 0x1f45, 1048584,
-    0x1f60, 0x1f67, 1048584,
-    0x1f70, 0x1f71, 1048650,
-    0x1f72, 0x1f75, 1048662,
-    0x1f76, 0x1f77, 1048676,
-    0x1f78, 0x1f79, 1048704,
-    0x1f7a, 0x1f7b, 1048688,
-    0x1f7c, 0x1f7d, 1048702,
-    0x1f80, 0x1f87, 1048584,
-    0x1f90, 0x1f97, 1048584,
-    0x1fa0, 0x1fa7, 1048584,
-    0x1fb0, 0x1fb1, 1048584,
-    0x1fd0, 0x1fd1, 1048584,
-    0x1fe0, 0x1fe1, 1048584,
-    0x2170, 0x217f, 1048560,
-    0x24d0, 0x24e9, 1048550,
-    0x2c30, 0x2c5e, 1048528,
-    0x2d00, 0x2d25, 1041312,
-    0xff41, 0xff5a, 1048544,
-    0x10428, 0x1044f, 1048536,
-    0x118c0, 0x118df, 1048544,
+	0x0061, 0x007a, 1048544,
+	0x00e0, 0x00f6, 1048544,
+	0x00f8, 0x00fe, 1048544,
+	0x023f, 0x0240, 1059391,
+	0x0256, 0x0257, 1048371,
+	0x028a, 0x028b, 1048359,
+	0x037b, 0x037d, 1048706,
+	0x03ad, 0x03af, 1048539,
+	0x03b1, 0x03c1, 1048544,
+	0x03c3, 0x03cb, 1048544,
+	0x03cd, 0x03ce, 1048513,
+	0x0430, 0x044f, 1048544,
+	0x0450, 0x045f, 1048496,
+	0x0561, 0x0586, 1048528,
+	0x1f00, 0x1f07, 1048584,
+	0x1f10, 0x1f15, 1048584,
+	0x1f20, 0x1f27, 1048584,
+	0x1f30, 0x1f37, 1048584,
+	0x1f40, 0x1f45, 1048584,
+	0x1f60, 0x1f67, 1048584,
+	0x1f70, 0x1f71, 1048650,
+	0x1f72, 0x1f75, 1048662,
+	0x1f76, 0x1f77, 1048676,
+	0x1f78, 0x1f79, 1048704,
+	0x1f7a, 0x1f7b, 1048688,
+	0x1f7c, 0x1f7d, 1048702,
+	0x1f80, 0x1f87, 1048584,
+	0x1f90, 0x1f97, 1048584,
+	0x1fa0, 0x1fa7, 1048584,
+	0x1fb0, 0x1fb1, 1048584,
+	0x1fd0, 0x1fd1, 1048584,
+	0x1fe0, 0x1fe1, 1048584,
+	0x2170, 0x217f, 1048560,
+	0x24d0, 0x24e9, 1048550,
+	0x2c30, 0x2c5e, 1048528,
+	0x2d00, 0x2d25, 1041312,
+	0xff41, 0xff5a, 1048544,
+	0x10428, 0x1044f, 1048536,
+	0x118c0, 0x118df, 1048544,
 };
 
 } // !namespace
@@ -4040,757 +4038,801 @@
 namespace {
 
 const char32_t totitles[] = {
-    0x00b5, 1049319,
-    0x00ff, 1048697,
-    0x0101, 1048575,
-    0x0103, 1048575,
-    0x0105, 1048575,
-    0x0107, 1048575,
-    0x0109, 1048575,
-    0x010b, 1048575,
-    0x010d, 1048575,
-    0x010f, 1048575,
-    0x0111, 1048575,
-    0x0113, 1048575,
-    0x0115, 1048575,
-    0x0117, 1048575,
-    0x0119, 1048575,
-    0x011b, 1048575,
-    0x011d, 1048575,
-    0x011f, 1048575,
-    0x0121, 1048575,
-    0x0123, 1048575,
-    0x0125, 1048575,
-    0x0127, 1048575,
-    0x0129, 1048575,
-    0x012b, 1048575,
-    0x012d, 1048575,
-    0x012f, 1048575,
-    0x0131, 1048344,
-    0x0133, 1048575,
-    0x0135, 1048575,
-    0x0137, 1048575,
-    0x013a, 1048575,
-    0x013c, 1048575,
-    0x013e, 1048575,
-    0x0140, 1048575,
-    0x0142, 1048575,
-    0x0144, 1048575,
-    0x0146, 1048575,
-    0x0148, 1048575,
-    0x014b, 1048575,
-    0x014d, 1048575,
-    0x014f, 1048575,
-    0x0151, 1048575,
-    0x0153, 1048575,
-    0x0155, 1048575,
-    0x0157, 1048575,
-    0x0159, 1048575,
-    0x015b, 1048575,
-    0x015d, 1048575,
-    0x015f, 1048575,
-    0x0161, 1048575,
-    0x0163, 1048575,
-    0x0165, 1048575,
-    0x0167, 1048575,
-    0x0169, 1048575,
-    0x016b, 1048575,
-    0x016d, 1048575,
-    0x016f, 1048575,
-    0x0171, 1048575,
-    0x0173, 1048575,
-    0x0175, 1048575,
-    0x0177, 1048575,
-    0x017a, 1048575,
-    0x017c, 1048575,
-    0x017e, 1048575,
-    0x017f, 1048276,
-    0x0180, 1048771,
-    0x0183, 1048575,
-    0x0185, 1048575,
-    0x0188, 1048575,
-    0x018c, 1048575,
-    0x0192, 1048575,
-    0x0195, 1048673,
-    0x0199, 1048575,
-    0x019a, 1048739,
-    0x019e, 1048706,
-    0x01a1, 1048575,
-    0x01a3, 1048575,
-    0x01a5, 1048575,
-    0x01a8, 1048575,
-    0x01ad, 1048575,
-    0x01b0, 1048575,
-    0x01b4, 1048575,
-    0x01b6, 1048575,
-    0x01b9, 1048575,
-    0x01bd, 1048575,
-    0x01bf, 1048632,
-    0x01c4, 1048577,
-    0x01c6, 1048575,
-    0x01c7, 1048577,
-    0x01c9, 1048575,
-    0x01ca, 1048577,
-    0x01cc, 1048575,
-    0x01ce, 1048575,
-    0x01d0, 1048575,
-    0x01d2, 1048575,
-    0x01d4, 1048575,
-    0x01d6, 1048575,
-    0x01d8, 1048575,
-    0x01da, 1048575,
-    0x01dc, 1048575,
-    0x01dd, 1048497,
-    0x01df, 1048575,
-    0x01e1, 1048575,
-    0x01e3, 1048575,
-    0x01e5, 1048575,
-    0x01e7, 1048575,
-    0x01e9, 1048575,
-    0x01eb, 1048575,
-    0x01ed, 1048575,
-    0x01ef, 1048575,
-    0x01f1, 1048577,
-    0x01f3, 1048575,
-    0x01f5, 1048575,
-    0x01f9, 1048575,
-    0x01fb, 1048575,
-    0x01fd, 1048575,
-    0x01ff, 1048575,
-    0x0201, 1048575,
-    0x0203, 1048575,
-    0x0205, 1048575,
-    0x0207, 1048575,
-    0x0209, 1048575,
-    0x020b, 1048575,
-    0x020d, 1048575,
-    0x020f, 1048575,
-    0x0211, 1048575,
-    0x0213, 1048575,
-    0x0215, 1048575,
-    0x0217, 1048575,
-    0x0219, 1048575,
-    0x021b, 1048575,
-    0x021d, 1048575,
-    0x021f, 1048575,
-    0x0223, 1048575,
-    0x0225, 1048575,
-    0x0227, 1048575,
-    0x0229, 1048575,
-    0x022b, 1048575,
-    0x022d, 1048575,
-    0x022f, 1048575,
-    0x0231, 1048575,
-    0x0233, 1048575,
-    0x023c, 1048575,
-    0x0242, 1048575,
-    0x0247, 1048575,
-    0x0249, 1048575,
-    0x024b, 1048575,
-    0x024d, 1048575,
-    0x024f, 1048575,
-    0x0250, 1059359,
-    0x0251, 1059356,
-    0x0252, 1059358,
-    0x0253, 1048366,
-    0x0254, 1048370,
-    0x0259, 1048374,
-    0x025b, 1048373,
-    0x025c, 1090895,
-    0x0260, 1048371,
-    0x0261, 1090891,
-    0x0263, 1048369,
-    0x0265, 1090856,
-    0x0266, 1090884,
-    0x0268, 1048367,
-    0x0269, 1048365,
-    0x026b, 1059319,
-    0x026c, 1090881,
-    0x026f, 1048365,
-    0x0271, 1059325,
-    0x0272, 1048363,
-    0x0275, 1048362,
-    0x027d, 1059303,
-    0x0280, 1048358,
-    0x0283, 1048358,
-    0x0287, 1090858,
-    0x0288, 1048358,
-    0x0289, 1048507,
-    0x028c, 1048505,
-    0x0292, 1048357,
-    0x029e, 1090834,
-    0x0345, 1048660,
-    0x0371, 1048575,
-    0x0373, 1048575,
-    0x0377, 1048575,
-    0x03ac, 1048538,
-    0x03c2, 1048545,
-    0x03cc, 1048512,
-    0x03d0, 1048514,
-    0x03d1, 1048519,
-    0x03d5, 1048529,
-    0x03d6, 1048522,
-    0x03d7, 1048568,
-    0x03d9, 1048575,
-    0x03db, 1048575,
-    0x03dd, 1048575,
-    0x03df, 1048575,
-    0x03e1, 1048575,
-    0x03e3, 1048575,
-    0x03e5, 1048575,
-    0x03e7, 1048575,
-    0x03e9, 1048575,
-    0x03eb, 1048575,
-    0x03ed, 1048575,
-    0x03ef, 1048575,
-    0x03f0, 1048490,
-    0x03f1, 1048496,
-    0x03f2, 1048583,
-    0x03f3, 1048460,
-    0x03f5, 1048480,
-    0x03f8, 1048575,
-    0x03fb, 1048575,
-    0x0461, 1048575,
-    0x0463, 1048575,
-    0x0465, 1048575,
-    0x0467, 1048575,
-    0x0469, 1048575,
-    0x046b, 1048575,
-    0x046d, 1048575,
-    0x046f, 1048575,
-    0x0471, 1048575,
-    0x0473, 1048575,
-    0x0475, 1048575,
-    0x0477, 1048575,
-    0x0479, 1048575,
-    0x047b, 1048575,
-    0x047d, 1048575,
-    0x047f, 1048575,
-    0x0481, 1048575,
-    0x048b, 1048575,
-    0x048d, 1048575,
-    0x048f, 1048575,
-    0x0491, 1048575,
-    0x0493, 1048575,
-    0x0495, 1048575,
-    0x0497, 1048575,
-    0x0499, 1048575,
-    0x049b, 1048575,
-    0x049d, 1048575,
-    0x049f, 1048575,
-    0x04a1, 1048575,
-    0x04a3, 1048575,
-    0x04a5, 1048575,
-    0x04a7, 1048575,
-    0x04a9, 1048575,
-    0x04ab, 1048575,
-    0x04ad, 1048575,
-    0x04af, 1048575,
-    0x04b1, 1048575,
-    0x04b3, 1048575,
-    0x04b5, 1048575,
-    0x04b7, 1048575,
-    0x04b9, 1048575,
-    0x04bb, 1048575,
-    0x04bd, 1048575,
-    0x04bf, 1048575,
-    0x04c2, 1048575,
-    0x04c4, 1048575,
-    0x04c6, 1048575,
-    0x04c8, 1048575,
-    0x04ca, 1048575,
-    0x04cc, 1048575,
-    0x04ce, 1048575,
-    0x04cf, 1048561,
-    0x04d1, 1048575,
-    0x04d3, 1048575,
-    0x04d5, 1048575,
-    0x04d7, 1048575,
-    0x04d9, 1048575,
-    0x04db, 1048575,
-    0x04dd, 1048575,
-    0x04df, 1048575,
-    0x04e1, 1048575,
-    0x04e3, 1048575,
-    0x04e5, 1048575,
-    0x04e7, 1048575,
-    0x04e9, 1048575,
-    0x04eb, 1048575,
-    0x04ed, 1048575,
-    0x04ef, 1048575,
-    0x04f1, 1048575,
-    0x04f3, 1048575,
-    0x04f5, 1048575,
-    0x04f7, 1048575,
-    0x04f9, 1048575,
-    0x04fb, 1048575,
-    0x04fd, 1048575,
-    0x04ff, 1048575,
-    0x0501, 1048575,
-    0x0503, 1048575,
-    0x0505, 1048575,
-    0x0507, 1048575,
-    0x0509, 1048575,
-    0x050b, 1048575,
-    0x050d, 1048575,
-    0x050f, 1048575,
-    0x0511, 1048575,
-    0x0513, 1048575,
-    0x0515, 1048575,
-    0x0517, 1048575,
-    0x0519, 1048575,
-    0x051b, 1048575,
-    0x051d, 1048575,
-    0x051f, 1048575,
-    0x0521, 1048575,
-    0x0523, 1048575,
-    0x0525, 1048575,
-    0x0527, 1048575,
-    0x0529, 1048575,
-    0x052b, 1048575,
-    0x052d, 1048575,
-    0x052f, 1048575,
-    0x1d79, 1083908,
-    0x1d7d, 1052390,
-    0x1e01, 1048575,
-    0x1e03, 1048575,
-    0x1e05, 1048575,
-    0x1e07, 1048575,
-    0x1e09, 1048575,
-    0x1e0b, 1048575,
-    0x1e0d, 1048575,
-    0x1e0f, 1048575,
-    0x1e11, 1048575,
-    0x1e13, 1048575,
-    0x1e15, 1048575,
-    0x1e17, 1048575,
-    0x1e19, 1048575,
-    0x1e1b, 1048575,
-    0x1e1d, 1048575,
-    0x1e1f, 1048575,
-    0x1e21, 1048575,
-    0x1e23, 1048575,
-    0x1e25, 1048575,
-    0x1e27, 1048575,
-    0x1e29, 1048575,
-    0x1e2b, 1048575,
-    0x1e2d, 1048575,
-    0x1e2f, 1048575,
-    0x1e31, 1048575,
-    0x1e33, 1048575,
-    0x1e35, 1048575,
-    0x1e37, 1048575,
-    0x1e39, 1048575,
-    0x1e3b, 1048575,
-    0x1e3d, 1048575,
-    0x1e3f, 1048575,
-    0x1e41, 1048575,
-    0x1e43, 1048575,
-    0x1e45, 1048575,
-    0x1e47, 1048575,
-    0x1e49, 1048575,
-    0x1e4b, 1048575,
-    0x1e4d, 1048575,
-    0x1e4f, 1048575,
-    0x1e51, 1048575,
-    0x1e53, 1048575,
-    0x1e55, 1048575,
-    0x1e57, 1048575,
-    0x1e59, 1048575,
-    0x1e5b, 1048575,
-    0x1e5d, 1048575,
-    0x1e5f, 1048575,
-    0x1e61, 1048575,
-    0x1e63, 1048575,
-    0x1e65, 1048575,
-    0x1e67, 1048575,
-    0x1e69, 1048575,
-    0x1e6b, 1048575,
-    0x1e6d, 1048575,
-    0x1e6f, 1048575,
-    0x1e71, 1048575,
-    0x1e73, 1048575,
-    0x1e75, 1048575,
-    0x1e77, 1048575,
-    0x1e79, 1048575,
-    0x1e7b, 1048575,
-    0x1e7d, 1048575,
-    0x1e7f, 1048575,
-    0x1e81, 1048575,
-    0x1e83, 1048575,
-    0x1e85, 1048575,
-    0x1e87, 1048575,
-    0x1e89, 1048575,
-    0x1e8b, 1048575,
-    0x1e8d, 1048575,
-    0x1e8f, 1048575,
-    0x1e91, 1048575,
-    0x1e93, 1048575,
-    0x1e95, 1048575,
-    0x1e9b, 1048517,
-    0x1ea1, 1048575,
-    0x1ea3, 1048575,
-    0x1ea5, 1048575,
-    0x1ea7, 1048575,
-    0x1ea9, 1048575,
-    0x1eab, 1048575,
-    0x1ead, 1048575,
-    0x1eaf, 1048575,
-    0x1eb1, 1048575,
-    0x1eb3, 1048575,
-    0x1eb5, 1048575,
-    0x1eb7, 1048575,
-    0x1eb9, 1048575,
-    0x1ebb, 1048575,
-    0x1ebd, 1048575,
-    0x1ebf, 1048575,
-    0x1ec1, 1048575,
-    0x1ec3, 1048575,
-    0x1ec5, 1048575,
-    0x1ec7, 1048575,
-    0x1ec9, 1048575,
-    0x1ecb, 1048575,
-    0x1ecd, 1048575,
-    0x1ecf, 1048575,
-    0x1ed1, 1048575,
-    0x1ed3, 1048575,
-    0x1ed5, 1048575,
-    0x1ed7, 1048575,
-    0x1ed9, 1048575,
-    0x1edb, 1048575,
-    0x1edd, 1048575,
-    0x1edf, 1048575,
-    0x1ee1, 1048575,
-    0x1ee3, 1048575,
-    0x1ee5, 1048575,
-    0x1ee7, 1048575,
-    0x1ee9, 1048575,
-    0x1eeb, 1048575,
-    0x1eed, 1048575,
-    0x1eef, 1048575,
-    0x1ef1, 1048575,
-    0x1ef3, 1048575,
-    0x1ef5, 1048575,
-    0x1ef7, 1048575,
-    0x1ef9, 1048575,
-    0x1efb, 1048575,
-    0x1efd, 1048575,
-    0x1eff, 1048575,
-    0x1f51, 1048584,
-    0x1f53, 1048584,
-    0x1f55, 1048584,
-    0x1f57, 1048584,
-    0x1fb3, 1048585,
-    0x1fbe, 1041371,
-    0x1fc3, 1048585,
-    0x1fe5, 1048583,
-    0x1ff3, 1048585,
-    0x214e, 1048548,
-    0x2184, 1048575,
-    0x2c61, 1048575,
-    0x2c65, 1037781,
-    0x2c66, 1037784,
-    0x2c68, 1048575,
-    0x2c6a, 1048575,
-    0x2c6c, 1048575,
-    0x2c73, 1048575,
-    0x2c76, 1048575,
-    0x2c81, 1048575,
-    0x2c83, 1048575,
-    0x2c85, 1048575,
-    0x2c87, 1048575,
-    0x2c89, 1048575,
-    0x2c8b, 1048575,
-    0x2c8d, 1048575,
-    0x2c8f, 1048575,
-    0x2c91, 1048575,
-    0x2c93, 1048575,
-    0x2c95, 1048575,
-    0x2c97, 1048575,
-    0x2c99, 1048575,
-    0x2c9b, 1048575,
-    0x2c9d, 1048575,
-    0x2c9f, 1048575,
-    0x2ca1, 1048575,
-    0x2ca3, 1048575,
-    0x2ca5, 1048575,
-    0x2ca7, 1048575,
-    0x2ca9, 1048575,
-    0x2cab, 1048575,
-    0x2cad, 1048575,
-    0x2caf, 1048575,
-    0x2cb1, 1048575,
-    0x2cb3, 1048575,
-    0x2cb5, 1048575,
-    0x2cb7, 1048575,
-    0x2cb9, 1048575,
-    0x2cbb, 1048575,
-    0x2cbd, 1048575,
-    0x2cbf, 1048575,
-    0x2cc1, 1048575,
-    0x2cc3, 1048575,
-    0x2cc5, 1048575,
-    0x2cc7, 1048575,
-    0x2cc9, 1048575,
-    0x2ccb, 1048575,
-    0x2ccd, 1048575,
-    0x2ccf, 1048575,
-    0x2cd1, 1048575,
-    0x2cd3, 1048575,
-    0x2cd5, 1048575,
-    0x2cd7, 1048575,
-    0x2cd9, 1048575,
-    0x2cdb, 1048575,
-    0x2cdd, 1048575,
-    0x2cdf, 1048575,
-    0x2ce1, 1048575,
-    0x2ce3, 1048575,
-    0x2cec, 1048575,
-    0x2cee, 1048575,
-    0x2cf3, 1048575,
-    0x2d27, 1041312,
-    0x2d2d, 1041312,
-    0xa641, 1048575,
-    0xa643, 1048575,
-    0xa645, 1048575,
-    0xa647, 1048575,
-    0xa649, 1048575,
-    0xa64b, 1048575,
-    0xa64d, 1048575,
-    0xa64f, 1048575,
-    0xa651, 1048575,
-    0xa653, 1048575,
-    0xa655, 1048575,
-    0xa657, 1048575,
-    0xa659, 1048575,
-    0xa65b, 1048575,
-    0xa65d, 1048575,
-    0xa65f, 1048575,
-    0xa661, 1048575,
-    0xa663, 1048575,
-    0xa665, 1048575,
-    0xa667, 1048575,
-    0xa669, 1048575,
-    0xa66b, 1048575,
-    0xa66d, 1048575,
-    0xa681, 1048575,
-    0xa683, 1048575,
-    0xa685, 1048575,
-    0xa687, 1048575,
-    0xa689, 1048575,
-    0xa68b, 1048575,
-    0xa68d, 1048575,
-    0xa68f, 1048575,
-    0xa691, 1048575,
-    0xa693, 1048575,
-    0xa695, 1048575,
-    0xa697, 1048575,
-    0xa699, 1048575,
-    0xa69b, 1048575,
-    0xa723, 1048575,
-    0xa725, 1048575,
-    0xa727, 1048575,
-    0xa729, 1048575,
-    0xa72b, 1048575,
-    0xa72d, 1048575,
-    0xa72f, 1048575,
-    0xa733, 1048575,
-    0xa735, 1048575,
-    0xa737, 1048575,
-    0xa739, 1048575,
-    0xa73b, 1048575,
-    0xa73d, 1048575,
-    0xa73f, 1048575,
-    0xa741, 1048575,
-    0xa743, 1048575,
-    0xa745, 1048575,
-    0xa747, 1048575,
-    0xa749, 1048575,
-    0xa74b, 1048575,
-    0xa74d, 1048575,
-    0xa74f, 1048575,
-    0xa751, 1048575,
-    0xa753, 1048575,
-    0xa755, 1048575,
-    0xa757, 1048575,
-    0xa759, 1048575,
-    0xa75b, 1048575,
-    0xa75d, 1048575,
-    0xa75f, 1048575,
-    0xa761, 1048575,
-    0xa763, 1048575,
-    0xa765, 1048575,
-    0xa767, 1048575,
-    0xa769, 1048575,
-    0xa76b, 1048575,
-    0xa76d, 1048575,
-    0xa76f, 1048575,
-    0xa77a, 1048575,
-    0xa77c, 1048575,
-    0xa77f, 1048575,
-    0xa781, 1048575,
-    0xa783, 1048575,
-    0xa785, 1048575,
-    0xa787, 1048575,
-    0xa78c, 1048575,
-    0xa791, 1048575,
-    0xa793, 1048575,
-    0xa797, 1048575,
-    0xa799, 1048575,
-    0xa79b, 1048575,
-    0xa79d, 1048575,
-    0xa79f, 1048575,
-    0xa7a1, 1048575,
-    0xa7a3, 1048575,
-    0xa7a5, 1048575,
-    0xa7a7, 1048575,
-    0xa7a9, 1048575,
+	0x00b5, 1049319,
+	0x00ff, 1048697,
+	0x0101, 1048575,
+	0x0103, 1048575,
+	0x0105, 1048575,
+	0x0107, 1048575,
+	0x0109, 1048575,
+	0x010b, 1048575,
+	0x010d, 1048575,
+	0x010f, 1048575,
+	0x0111, 1048575,
+	0x0113, 1048575,
+	0x0115, 1048575,
+	0x0117, 1048575,
+	0x0119, 1048575,
+	0x011b, 1048575,
+	0x011d, 1048575,
+	0x011f, 1048575,
+	0x0121, 1048575,
+	0x0123, 1048575,
+	0x0125, 1048575,
+	0x0127, 1048575,
+	0x0129, 1048575,
+	0x012b, 1048575,
+	0x012d, 1048575,
+	0x012f, 1048575,
+	0x0131, 1048344,
+	0x0133, 1048575,
+	0x0135, 1048575,
+	0x0137, 1048575,
+	0x013a, 1048575,
+	0x013c, 1048575,
+	0x013e, 1048575,
+	0x0140, 1048575,
+	0x0142, 1048575,
+	0x0144, 1048575,
+	0x0146, 1048575,
+	0x0148, 1048575,
+	0x014b, 1048575,
+	0x014d, 1048575,
+	0x014f, 1048575,
+	0x0151, 1048575,
+	0x0153, 1048575,
+	0x0155, 1048575,
+	0x0157, 1048575,
+	0x0159, 1048575,
+	0x015b, 1048575,
+	0x015d, 1048575,
+	0x015f, 1048575,
+	0x0161, 1048575,
+	0x0163, 1048575,
+	0x0165, 1048575,
+	0x0167, 1048575,
+	0x0169, 1048575,
+	0x016b, 1048575,
+	0x016d, 1048575,
+	0x016f, 1048575,
+	0x0171, 1048575,
+	0x0173, 1048575,
+	0x0175, 1048575,
+	0x0177, 1048575,
+	0x017a, 1048575,
+	0x017c, 1048575,
+	0x017e, 1048575,
+	0x017f, 1048276,
+	0x0180, 1048771,
+	0x0183, 1048575,
+	0x0185, 1048575,
+	0x0188, 1048575,
+	0x018c, 1048575,
+	0x0192, 1048575,
+	0x0195, 1048673,
+	0x0199, 1048575,
+	0x019a, 1048739,
+	0x019e, 1048706,
+	0x01a1, 1048575,
+	0x01a3, 1048575,
+	0x01a5, 1048575,
+	0x01a8, 1048575,
+	0x01ad, 1048575,
+	0x01b0, 1048575,
+	0x01b4, 1048575,
+	0x01b6, 1048575,
+	0x01b9, 1048575,
+	0x01bd, 1048575,
+	0x01bf, 1048632,
+	0x01c4, 1048577,
+	0x01c6, 1048575,
+	0x01c7, 1048577,
+	0x01c9, 1048575,
+	0x01ca, 1048577,
+	0x01cc, 1048575,
+	0x01ce, 1048575,
+	0x01d0, 1048575,
+	0x01d2, 1048575,
+	0x01d4, 1048575,
+	0x01d6, 1048575,
+	0x01d8, 1048575,
+	0x01da, 1048575,
+	0x01dc, 1048575,
+	0x01dd, 1048497,
+	0x01df, 1048575,
+	0x01e1, 1048575,
+	0x01e3, 1048575,
+	0x01e5, 1048575,
+	0x01e7, 1048575,
+	0x01e9, 1048575,
+	0x01eb, 1048575,
+	0x01ed, 1048575,
+	0x01ef, 1048575,
+	0x01f1, 1048577,
+	0x01f3, 1048575,
+	0x01f5, 1048575,
+	0x01f9, 1048575,
+	0x01fb, 1048575,
+	0x01fd, 1048575,
+	0x01ff, 1048575,
+	0x0201, 1048575,
+	0x0203, 1048575,
+	0x0205, 1048575,
+	0x0207, 1048575,
+	0x0209, 1048575,
+	0x020b, 1048575,
+	0x020d, 1048575,
+	0x020f, 1048575,
+	0x0211, 1048575,
+	0x0213, 1048575,
+	0x0215, 1048575,
+	0x0217, 1048575,
+	0x0219, 1048575,
+	0x021b, 1048575,
+	0x021d, 1048575,
+	0x021f, 1048575,
+	0x0223, 1048575,
+	0x0225, 1048575,
+	0x0227, 1048575,
+	0x0229, 1048575,
+	0x022b, 1048575,
+	0x022d, 1048575,
+	0x022f, 1048575,
+	0x0231, 1048575,
+	0x0233, 1048575,
+	0x023c, 1048575,
+	0x0242, 1048575,
+	0x0247, 1048575,
+	0x0249, 1048575,
+	0x024b, 1048575,
+	0x024d, 1048575,
+	0x024f, 1048575,
+	0x0250, 1059359,
+	0x0251, 1059356,
+	0x0252, 1059358,
+	0x0253, 1048366,
+	0x0254, 1048370,
+	0x0259, 1048374,
+	0x025b, 1048373,
+	0x025c, 1090895,
+	0x0260, 1048371,
+	0x0261, 1090891,
+	0x0263, 1048369,
+	0x0265, 1090856,
+	0x0266, 1090884,
+	0x0268, 1048367,
+	0x0269, 1048365,
+	0x026b, 1059319,
+	0x026c, 1090881,
+	0x026f, 1048365,
+	0x0271, 1059325,
+	0x0272, 1048363,
+	0x0275, 1048362,
+	0x027d, 1059303,
+	0x0280, 1048358,
+	0x0283, 1048358,
+	0x0287, 1090858,
+	0x0288, 1048358,
+	0x0289, 1048507,
+	0x028c, 1048505,
+	0x0292, 1048357,
+	0x029e, 1090834,
+	0x0345, 1048660,
+	0x0371, 1048575,
+	0x0373, 1048575,
+	0x0377, 1048575,
+	0x03ac, 1048538,
+	0x03c2, 1048545,
+	0x03cc, 1048512,
+	0x03d0, 1048514,
+	0x03d1, 1048519,
+	0x03d5, 1048529,
+	0x03d6, 1048522,
+	0x03d7, 1048568,
+	0x03d9, 1048575,
+	0x03db, 1048575,
+	0x03dd, 1048575,
+	0x03df, 1048575,
+	0x03e1, 1048575,
+	0x03e3, 1048575,
+	0x03e5, 1048575,
+	0x03e7, 1048575,
+	0x03e9, 1048575,
+	0x03eb, 1048575,
+	0x03ed, 1048575,
+	0x03ef, 1048575,
+	0x03f0, 1048490,
+	0x03f1, 1048496,
+	0x03f2, 1048583,
+	0x03f3, 1048460,
+	0x03f5, 1048480,
+	0x03f8, 1048575,
+	0x03fb, 1048575,
+	0x0461, 1048575,
+	0x0463, 1048575,
+	0x0465, 1048575,
+	0x0467, 1048575,
+	0x0469, 1048575,
+	0x046b, 1048575,
+	0x046d, 1048575,
+	0x046f, 1048575,
+	0x0471, 1048575,
+	0x0473, 1048575,
+	0x0475, 1048575,
+	0x0477, 1048575,
+	0x0479, 1048575,
+	0x047b, 1048575,
+	0x047d, 1048575,
+	0x047f, 1048575,
+	0x0481, 1048575,
+	0x048b, 1048575,
+	0x048d, 1048575,
+	0x048f, 1048575,
+	0x0491, 1048575,
+	0x0493, 1048575,
+	0x0495, 1048575,
+	0x0497, 1048575,
+	0x0499, 1048575,
+	0x049b, 1048575,
+	0x049d, 1048575,
+	0x049f, 1048575,
+	0x04a1, 1048575,
+	0x04a3, 1048575,
+	0x04a5, 1048575,
+	0x04a7, 1048575,
+	0x04a9, 1048575,
+	0x04ab, 1048575,
+	0x04ad, 1048575,
+	0x04af, 1048575,
+	0x04b1, 1048575,
+	0x04b3, 1048575,
+	0x04b5, 1048575,
+	0x04b7, 1048575,
+	0x04b9, 1048575,
+	0x04bb, 1048575,
+	0x04bd, 1048575,
+	0x04bf, 1048575,
+	0x04c2, 1048575,
+	0x04c4, 1048575,
+	0x04c6, 1048575,
+	0x04c8, 1048575,
+	0x04ca, 1048575,
+	0x04cc, 1048575,
+	0x04ce, 1048575,
+	0x04cf, 1048561,
+	0x04d1, 1048575,
+	0x04d3, 1048575,
+	0x04d5, 1048575,
+	0x04d7, 1048575,
+	0x04d9, 1048575,
+	0x04db, 1048575,
+	0x04dd, 1048575,
+	0x04df, 1048575,
+	0x04e1, 1048575,
+	0x04e3, 1048575,
+	0x04e5, 1048575,
+	0x04e7, 1048575,
+	0x04e9, 1048575,
+	0x04eb, 1048575,
+	0x04ed, 1048575,
+	0x04ef, 1048575,
+	0x04f1, 1048575,
+	0x04f3, 1048575,
+	0x04f5, 1048575,
+	0x04f7, 1048575,
+	0x04f9, 1048575,
+	0x04fb, 1048575,
+	0x04fd, 1048575,
+	0x04ff, 1048575,
+	0x0501, 1048575,
+	0x0503, 1048575,
+	0x0505, 1048575,
+	0x0507, 1048575,
+	0x0509, 1048575,
+	0x050b, 1048575,
+	0x050d, 1048575,
+	0x050f, 1048575,
+	0x0511, 1048575,
+	0x0513, 1048575,
+	0x0515, 1048575,
+	0x0517, 1048575,
+	0x0519, 1048575,
+	0x051b, 1048575,
+	0x051d, 1048575,
+	0x051f, 1048575,
+	0x0521, 1048575,
+	0x0523, 1048575,
+	0x0525, 1048575,
+	0x0527, 1048575,
+	0x0529, 1048575,
+	0x052b, 1048575,
+	0x052d, 1048575,
+	0x052f, 1048575,
+	0x1d79, 1083908,
+	0x1d7d, 1052390,
+	0x1e01, 1048575,
+	0x1e03, 1048575,
+	0x1e05, 1048575,
+	0x1e07, 1048575,
+	0x1e09, 1048575,
+	0x1e0b, 1048575,
+	0x1e0d, 1048575,
+	0x1e0f, 1048575,
+	0x1e11, 1048575,
+	0x1e13, 1048575,
+	0x1e15, 1048575,
+	0x1e17, 1048575,
+	0x1e19, 1048575,
+	0x1e1b, 1048575,
+	0x1e1d, 1048575,
+	0x1e1f, 1048575,
+	0x1e21, 1048575,
+	0x1e23, 1048575,
+	0x1e25, 1048575,
+	0x1e27, 1048575,
+	0x1e29, 1048575,
+	0x1e2b, 1048575,
+	0x1e2d, 1048575,
+	0x1e2f, 1048575,
+	0x1e31, 1048575,
+	0x1e33, 1048575,
+	0x1e35, 1048575,
+	0x1e37, 1048575,
+	0x1e39, 1048575,
+	0x1e3b, 1048575,
+	0x1e3d, 1048575,
+	0x1e3f, 1048575,
+	0x1e41, 1048575,
+	0x1e43, 1048575,
+	0x1e45, 1048575,
+	0x1e47, 1048575,
+	0x1e49, 1048575,
+	0x1e4b, 1048575,
+	0x1e4d, 1048575,
+	0x1e4f, 1048575,
+	0x1e51, 1048575,
+	0x1e53, 1048575,
+	0x1e55, 1048575,
+	0x1e57, 1048575,
+	0x1e59, 1048575,
+	0x1e5b, 1048575,
+	0x1e5d, 1048575,
+	0x1e5f, 1048575,
+	0x1e61, 1048575,
+	0x1e63, 1048575,
+	0x1e65, 1048575,
+	0x1e67, 1048575,
+	0x1e69, 1048575,
+	0x1e6b, 1048575,
+	0x1e6d, 1048575,
+	0x1e6f, 1048575,
+	0x1e71, 1048575,
+	0x1e73, 1048575,
+	0x1e75, 1048575,
+	0x1e77, 1048575,
+	0x1e79, 1048575,
+	0x1e7b, 1048575,
+	0x1e7d, 1048575,
+	0x1e7f, 1048575,
+	0x1e81, 1048575,
+	0x1e83, 1048575,
+	0x1e85, 1048575,
+	0x1e87, 1048575,
+	0x1e89, 1048575,
+	0x1e8b, 1048575,
+	0x1e8d, 1048575,
+	0x1e8f, 1048575,
+	0x1e91, 1048575,
+	0x1e93, 1048575,
+	0x1e95, 1048575,
+	0x1e9b, 1048517,
+	0x1ea1, 1048575,
+	0x1ea3, 1048575,
+	0x1ea5, 1048575,
+	0x1ea7, 1048575,
+	0x1ea9, 1048575,
+	0x1eab, 1048575,
+	0x1ead, 1048575,
+	0x1eaf, 1048575,
+	0x1eb1, 1048575,
+	0x1eb3, 1048575,
+	0x1eb5, 1048575,
+	0x1eb7, 1048575,
+	0x1eb9, 1048575,
+	0x1ebb, 1048575,
+	0x1ebd, 1048575,
+	0x1ebf, 1048575,
+	0x1ec1, 1048575,
+	0x1ec3, 1048575,
+	0x1ec5, 1048575,
+	0x1ec7, 1048575,
+	0x1ec9, 1048575,
+	0x1ecb, 1048575,
+	0x1ecd, 1048575,
+	0x1ecf, 1048575,
+	0x1ed1, 1048575,
+	0x1ed3, 1048575,
+	0x1ed5, 1048575,
+	0x1ed7, 1048575,
+	0x1ed9, 1048575,
+	0x1edb, 1048575,
+	0x1edd, 1048575,
+	0x1edf, 1048575,
+	0x1ee1, 1048575,
+	0x1ee3, 1048575,
+	0x1ee5, 1048575,
+	0x1ee7, 1048575,
+	0x1ee9, 1048575,
+	0x1eeb, 1048575,
+	0x1eed, 1048575,
+	0x1eef, 1048575,
+	0x1ef1, 1048575,
+	0x1ef3, 1048575,
+	0x1ef5, 1048575,
+	0x1ef7, 1048575,
+	0x1ef9, 1048575,
+	0x1efb, 1048575,
+	0x1efd, 1048575,
+	0x1eff, 1048575,
+	0x1f51, 1048584,
+	0x1f53, 1048584,
+	0x1f55, 1048584,
+	0x1f57, 1048584,
+	0x1fb3, 1048585,
+	0x1fbe, 1041371,
+	0x1fc3, 1048585,
+	0x1fe5, 1048583,
+	0x1ff3, 1048585,
+	0x214e, 1048548,
+	0x2184, 1048575,
+	0x2c61, 1048575,
+	0x2c65, 1037781,
+	0x2c66, 1037784,
+	0x2c68, 1048575,
+	0x2c6a, 1048575,
+	0x2c6c, 1048575,
+	0x2c73, 1048575,
+	0x2c76, 1048575,
+	0x2c81, 1048575,
+	0x2c83, 1048575,
+	0x2c85, 1048575,
+	0x2c87, 1048575,
+	0x2c89, 1048575,
+	0x2c8b, 1048575,
+	0x2c8d, 1048575,
+	0x2c8f, 1048575,
+	0x2c91, 1048575,
+	0x2c93, 1048575,
+	0x2c95, 1048575,
+	0x2c97, 1048575,
+	0x2c99, 1048575,
+	0x2c9b, 1048575,
+	0x2c9d, 1048575,
+	0x2c9f, 1048575,
+	0x2ca1, 1048575,
+	0x2ca3, 1048575,
+	0x2ca5, 1048575,
+	0x2ca7, 1048575,
+	0x2ca9, 1048575,
+	0x2cab, 1048575,
+	0x2cad, 1048575,
+	0x2caf, 1048575,
+	0x2cb1, 1048575,
+	0x2cb3, 1048575,
+	0x2cb5, 1048575,
+	0x2cb7, 1048575,
+	0x2cb9, 1048575,
+	0x2cbb, 1048575,
+	0x2cbd, 1048575,
+	0x2cbf, 1048575,
+	0x2cc1, 1048575,
+	0x2cc3, 1048575,
+	0x2cc5, 1048575,
+	0x2cc7, 1048575,
+	0x2cc9, 1048575,
+	0x2ccb, 1048575,
+	0x2ccd, 1048575,
+	0x2ccf, 1048575,
+	0x2cd1, 1048575,
+	0x2cd3, 1048575,
+	0x2cd5, 1048575,
+	0x2cd7, 1048575,
+	0x2cd9, 1048575,
+	0x2cdb, 1048575,
+	0x2cdd, 1048575,
+	0x2cdf, 1048575,
+	0x2ce1, 1048575,
+	0x2ce3, 1048575,
+	0x2cec, 1048575,
+	0x2cee, 1048575,
+	0x2cf3, 1048575,
+	0x2d27, 1041312,
+	0x2d2d, 1041312,
+	0xa641, 1048575,
+	0xa643, 1048575,
+	0xa645, 1048575,
+	0xa647, 1048575,
+	0xa649, 1048575,
+	0xa64b, 1048575,
+	0xa64d, 1048575,
+	0xa64f, 1048575,
+	0xa651, 1048575,
+	0xa653, 1048575,
+	0xa655, 1048575,
+	0xa657, 1048575,
+	0xa659, 1048575,
+	0xa65b, 1048575,
+	0xa65d, 1048575,
+	0xa65f, 1048575,
+	0xa661, 1048575,
+	0xa663, 1048575,
+	0xa665, 1048575,
+	0xa667, 1048575,
+	0xa669, 1048575,
+	0xa66b, 1048575,
+	0xa66d, 1048575,
+	0xa681, 1048575,
+	0xa683, 1048575,
+	0xa685, 1048575,
+	0xa687, 1048575,
+	0xa689, 1048575,
+	0xa68b, 1048575,
+	0xa68d, 1048575,
+	0xa68f, 1048575,
+	0xa691, 1048575,
+	0xa693, 1048575,
+	0xa695, 1048575,
+	0xa697, 1048575,
+	0xa699, 1048575,
+	0xa69b, 1048575,
+	0xa723, 1048575,
+	0xa725, 1048575,
+	0xa727, 1048575,
+	0xa729, 1048575,
+	0xa72b, 1048575,
+	0xa72d, 1048575,
+	0xa72f, 1048575,
+	0xa733, 1048575,
+	0xa735, 1048575,
+	0xa737, 1048575,
+	0xa739, 1048575,
+	0xa73b, 1048575,
+	0xa73d, 1048575,
+	0xa73f, 1048575,
+	0xa741, 1048575,
+	0xa743, 1048575,
+	0xa745, 1048575,
+	0xa747, 1048575,
+	0xa749, 1048575,
+	0xa74b, 1048575,
+	0xa74d, 1048575,
+	0xa74f, 1048575,
+	0xa751, 1048575,
+	0xa753, 1048575,
+	0xa755, 1048575,
+	0xa757, 1048575,
+	0xa759, 1048575,
+	0xa75b, 1048575,
+	0xa75d, 1048575,
+	0xa75f, 1048575,
+	0xa761, 1048575,
+	0xa763, 1048575,
+	0xa765, 1048575,
+	0xa767, 1048575,
+	0xa769, 1048575,
+	0xa76b, 1048575,
+	0xa76d, 1048575,
+	0xa76f, 1048575,
+	0xa77a, 1048575,
+	0xa77c, 1048575,
+	0xa77f, 1048575,
+	0xa781, 1048575,
+	0xa783, 1048575,
+	0xa785, 1048575,
+	0xa787, 1048575,
+	0xa78c, 1048575,
+	0xa791, 1048575,
+	0xa793, 1048575,
+	0xa797, 1048575,
+	0xa799, 1048575,
+	0xa79b, 1048575,
+	0xa79d, 1048575,
+	0xa79f, 1048575,
+	0xa7a1, 1048575,
+	0xa7a3, 1048575,
+	0xa7a5, 1048575,
+	0xa7a7, 1048575,
+	0xa7a9, 1048575,
 };
 
 } // !namespace
 
-char32_t totitle(char32_t c) noexcept
+auto totitle(char32_t c) noexcept -> char32_t
 {
-   const char32_t *p;
+	const char32_t* p;
 
-   p = rbsearch(c, totitler, nelem (totitler)/3, 3);
+	p = search(c, totitler, nelem (totitler) / 3, 3);
 
-   if (p && c >= p[0] && c <= p[1])
-       return c + p[2] - 1048576;
+	if (p && c >= p[0] && c <= p[1])
+		return c + p[2] - 1048576;
 
- p = rbsearch(c, totitles, nelem (totitles)/2, 2);
+	p = search(c, totitles, nelem (totitles) / 2, 2);
 
-   if (p && c == p[0])
-       return c + p[1] - 1048576;
+	if (p && c == p[0])
+		return c + p[1] - 1048576;
 
-   return c;
+	return c;
 }
 
 void encode(char32_t c, char res[5]) noexcept
 {
-    switch (nbytesPoint(c)) {
-    case 1:
-        res[0] = static_cast<char>(c);
-        res[1] = '\0';
-        break;
-    case 2:
-        res[0] = 0xC0 | ((c >> 6)  & 0x1F);
-        res[1] = 0x80 | (c & 0x3F);
-        res[2] = '\0';
-        break;
-    case 3:
-        res[0] = 0xE0 | ((c >> 12) & 0xF );
-        res[1] = 0x80 | ((c >> 6)  & 0x3F);
-        res[2] = 0x80 | (c & 0x3F);
-        res[3] = '\0';
-        break;
-    case 4:
-        res[0] = 0xF0 | ((c >> 18) & 0x7 );
-        res[1] = 0x80 | ((c >> 12) & 0x3F);
-        res[2] = 0x80 | ((c >> 6)  & 0x3F);
-        res[3] = 0x80 | (c & 0x3F);
-        res[4] = '\0';
-        break;
-    default:
-        break;
-    }
+	switch (nbytes_point(c)) {
+	case 1:
+		res[0] = static_cast<char>(c);
+		res[1] = '\0';
+		break;
+	case 2:
+		res[0] = 0xC0 | ((c >> 6)  & 0x1F);
+		res[1] = 0x80 | (c & 0x3F);
+		res[2] = '\0';
+		break;
+	case 3:
+		res[0] = 0xE0 | ((c >> 12) & 0xF );
+		res[1] = 0x80 | ((c >> 6)  & 0x3F);
+		res[2] = 0x80 | (c & 0x3F);
+		res[3] = '\0';
+		break;
+	case 4:
+		res[0] = 0xF0 | ((c >> 18) & 0x7 );
+		res[1] = 0x80 | ((c >> 12) & 0x3F);
+		res[2] = 0x80 | ((c >> 6)  & 0x3F);
+		res[3] = 0x80 | (c & 0x3F);
+		res[4] = '\0';
+		break;
+	default:
+		break;
+	}
 }
 
-void decode(char32_t &c, const char *res) noexcept
+void decode(char32_t& c, const char* res) noexcept
 {
-    c = 0;
+	c = 0;
+
+	switch (nbytes_utf8(res[0])) {
+	case 1:
+		c = res[0];
+		break;
+	case 2:
+		c =  (res[0] & 0x1f) << 6;
+		c |= (res[1] & 0x3f);
+		break;
+	case 3:
+		c =  (res[0] & 0x0f) << 12;
+		c |= (res[1] & 0x3f) << 6;
+		c |= (res[2] & 0x3f);
+		break;
+	case 4:
+		c =  (res[0] & 0x07) << 16;
+		c |= (res[1] & 0x3f) << 12;
+		c |= (res[2] & 0x3f) << 6;
+		c |= (res[3] & 0x3f);
+	default:
+		break;
+	}
+}
 
-    switch (nbytesUtf8(res[0])) {
-    case 1:
-        c = res[0];
-        break;
-    case 2:
-        c =  (res[0] & 0x1f) << 6;
-        c |= (res[1] & 0x3f);
-        break;
-    case 3:
-        c =  (res[0] & 0x0f) << 12;
-        c |= (res[1] & 0x3f) << 6;
-        c |= (res[2] & 0x3f);
-        break;
-    case 4:
-        c =  (res[0] & 0x07) << 16;
-        c |= (res[1] & 0x3f) << 12;
-        c |= (res[2] & 0x3f) << 6;
-        c |= (res[3] & 0x3f);
-    default:
-        break;
-    }
+auto nbytes_utf8(char c) noexcept -> int
+{
+	if (static_cast<unsigned char>(c) <= 127)
+		return 1;
+	if ((c & 0xE0) == 0xC0)
+		return 2;
+	if ((c & 0xF0) == 0xE0)
+		return 3;
+	if ((c & 0xF8) == 0xF0)
+		return 4;
+
+	return -1;
+}
+
+auto nbytes_point(char32_t c) noexcept -> int
+{
+	if (c <= 0x7F)
+		return 1;
+	if (c <= 0x7FF)
+		return 2;
+	if (c <= 0xFFFF)
+		return 3;
+	if (c <= 0x1FFFFF)
+		return 4;
+
+	return -1;
 }
 
-int nbytesUtf8(char c) noexcept
+auto length(std::string_view str) -> unsigned
 {
-    if (static_cast<unsigned char>(c) <= 127)
-        return 1;
-    if ((c & 0xE0) == 0xC0)
-        return 2;
-    if ((c & 0xF0) == 0xE0)
-        return 3;
-    if ((c & 0xF8) == 0xF0)
-        return 4;
+	unsigned total = 0;
 
-    return -1;
+	for_each(str, [&] (auto) {
+		++ total;
+	});
+
+	return total;
 }
 
-int nbytesPoint(char32_t c) noexcept
+auto to_utf8(std::u32string_view array) -> std::string
 {
-    if (c <= 0x7F)
-        return 1;
-    if (c <= 0x7FF)
-        return 2;
-    if (c <= 0xFFFF)
-        return 3;
-    if (c <= 0x1FFFFF)
-        return 4;
+	std::string res;
+
+	for (size_t i = 0; i < array.size(); ++i) {
+		char tmp[5];
+		int size = nbytes_point(array[i]);
+
+		if (size < 0)
+			throw std::invalid_argument("invalid sequence");
+
+		encode(array[i], tmp);
+		res.insert(res.length(), tmp);
+	}
 
-    return -1;
+	return res;
+}
+
+auto to_utf32(std::string_view str) -> std::u32string
+{
+	std::u32string res;
+
+	for_each(str, [&] (char32_t code) {
+		res.push_back(code);
+	});
+
+	return res;
 }
 
-unsigned length(const std::string &str)
+auto toupper(std::u32string_view str) -> std::u32string
 {
-    unsigned total = 0;
+	std::u32string res(str);
+
+	for (size_t i = 0; i < str.size(); ++i)
+		res[i] = toupper(str[i]);
+
+	return res;
+}
 
-    forEach(str, [&] (char32_t) {
-        ++ total;
-    });
+auto toupper(std::string_view str) -> std::string
+{
+	std::string res;
+	char buffer[5];
 
-    return total;
+	for_each(str, [&] (auto code) {
+		encode(toupper(code), buffer);
+		res += buffer;
+	});
+
+	return res;
 }
 
-std::string toUtf8(const std::u32string &array)
+auto tolower(std::u32string_view str) -> std::u32string
 {
-    std::string res;
-
-    for (size_t i = 0; i < array.size(); ++i) {
-        char tmp[5];
-        int size = nbytesPoint(array[i]);
+	std::u32string ret(str);
 
-        if (size < 0)
-            throw std::invalid_argument("invalid sequence");
+	for (size_t i = 0; i < str.size(); ++i)
+		ret[i] = tolower(str[i]);
 
-        encode(array[i], tmp);
-        res.insert(res.length(), tmp);
-    }
-
-    return res;
+	return ret;
 }
 
-std::u32string toUtf32(const std::string &str)
+auto tolower(std::string_view str) -> std::string
 {
-    std::u32string res;
+	std::string res;
+	char buffer[5];
 
-    forEach(str, [&] (char32_t code) {
-        res.push_back(code);
-    });
+	for_each(str, [&] (auto code) {
+		encode(tolower(code), buffer);
+		res += buffer;
+	});
 
-    return res;
+	return res;
 }
 
-} // !unicode
-
-} // !irccd
+} // !irccd::unicode
--- a/libirccd-js/irccd/js/unicode.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/unicode.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,13 +28,12 @@
 
 #include <stdexcept>
 #include <string>
-
-namespace irccd {
+#include <string_view>
 
 /**
  * \brief Unicode namespace.
  */
-namespace unicode {
+namespace irccd::unicode {
 
 /**
  * Encode the unicode code point into multibyte string.
@@ -50,7 +49,7 @@
  * \param c the code point destination
  * \param res the multibyte string.
  */
-void decode(char32_t &c, const char *res) noexcept;
+void decode(char32_t& c, const char* res) noexcept;
 
 /**
  * Get the number of bytes for the first multi byte character from a
@@ -62,7 +61,7 @@
  * \param c the first multi byte character
  * \return the number of bytes [1-4] or -1 if invalid
  */
-int nbytesUtf8(char c) noexcept;
+auto nbytes_utf8(char c) noexcept -> int;
 
 /**
  * Get the number of bytes for the unicode point.
@@ -70,7 +69,7 @@
  * \param point the unicode point
  * \return the number of bytes [1-4] or -1 if invalid
  */
-int nbytesPoint(char32_t point) noexcept;
+auto nbytes_point(char32_t point) noexcept -> int;
 
 /**
  * Get real number of character in a string.
@@ -79,7 +78,7 @@
  * \return the length
  * \throw std::invalid_argument on invalid sequence
  */
-unsigned length(const std::string &str);
+auto length(std::string_view str) -> unsigned;
 
 /**
  * Iterate over all real characters in the UTF-8 string.
@@ -92,20 +91,20 @@
  * \throw std::invalid_argument on invalid sequence
  */
 template <typename Func>
-void forEach(const std::string &str, Func function)
+void for_each(std::string_view str, Func function)
 {
-    for (size_t i = 0; i < str.size(); ) {
-        char32_t point = 0;
-        int size = nbytesUtf8(str[i]);
+	for (size_t i = 0; i < str.size(); ) {
+		char32_t point = 0;
+		int size = nbytes_utf8(str[i]);
 
-        if (size < 0)
-            throw std::invalid_argument("invalid sequence");
+		if (size < 0)
+			throw std::invalid_argument("invalid sequence");
 
-        decode(point, str.data() + i);
-        function(point);
+		decode(point, str.data() + i);
+		function(point);
 
-        i += size;
-    }
+		i += size;
+	}
 }
 
 /**
@@ -115,7 +114,7 @@
  * \return the UTF-8 string
  * \throw std::invalid_argument on invalid sequence
  */
-std::string toUtf8(const std::u32string &array);
+auto to_utf8(std::u32string_view array) -> std::string;
 
 /**
  * Convert a UTF-8 string to UTF-32 string.
@@ -124,7 +123,7 @@
  * \return the UTF-32 string
  * \throw std::invalid_argument on invalid sequence
  */
-std::u32string toUtf32(const std::string &str);
+auto to_utf32(std::string_view str) -> std::u32string;
 
 /**
  * Check if the unicode character is space.
@@ -132,7 +131,7 @@
  * \param c the character
  * \return true if space
  */
-bool isspace(char32_t c) noexcept;
+auto isspace(char32_t c) noexcept -> bool;
 
 /**
  * Check if the unicode character is digit.
@@ -140,7 +139,7 @@
  * \param c the character
  * \return true if digit
  */
-bool isdigit(char32_t c) noexcept;
+auto isdigit(char32_t c) noexcept -> bool;
 
 /**
  * Check if the unicode character is alpha category.
@@ -148,7 +147,7 @@
  * \param c the character
  * \return true if alpha
  */
-bool isalpha(char32_t c) noexcept;
+auto isalpha(char32_t c) noexcept -> bool;
 
 /**
  * Check if the unicode character is upper case.
@@ -156,7 +155,7 @@
  * \param c the character
  * \return true if upper case
  */
-bool isupper(char32_t c) noexcept;
+auto isupper(char32_t c) noexcept -> bool;
 
 /**
  * Check if the unicode character is lower case.
@@ -164,7 +163,7 @@
  * \param c the character
  * \return true if lower case
  */
-bool islower(char32_t c) noexcept;
+auto islower(char32_t c) noexcept -> bool;
 
 /**
  * Check if the unicode character is title case.
@@ -172,7 +171,7 @@
  * \param c the character
  * \return true if title case
  */
-bool istitle(char32_t c) noexcept;
+auto istitle(char32_t c) noexcept -> bool;
 
 /**
  * Convert to upper case.
@@ -180,7 +179,7 @@
  * \param c the character
  * \return the upper case character
  */
-char32_t toupper(char32_t c) noexcept;
+auto toupper(char32_t c) noexcept -> char32_t;
 
 /**
  * Convert to lower case.
@@ -188,7 +187,7 @@
  * \param c the character
  * \return the lower case character
  */
-char32_t tolower(char32_t c) noexcept;
+auto tolower(char32_t c) noexcept -> char32_t;
 
 /**
  * Convert to title case.
@@ -196,78 +195,42 @@
  * \param c the character
  * \return the title case character
  */
-char32_t totitle(char32_t c) noexcept;
+auto totitle(char32_t c) noexcept -> char32_t;
 
 /**
  * Convert the UTF-32 string to upper case.
  *
- * \param str the str
+ * \param str the string
  * \return the upper case string
  */
-inline std::u32string toupper(std::u32string str)
-{
-    for (size_t i = 0; i < str.size(); ++i)
-        str[i] = toupper(str[i]);
-
-    return str;
-}
+auto toupper(std::u32string_view str) -> std::u32string;
 
 /**
  * Convert the UTF-8 string to upper case.
  *
- * \param str the str
+ * \param str the string
  * \return the upper case string
  * \warning very slow at the moment
  */
-inline std::string toupper(const std::string &str)
-{
-    std::string result;
-    char buffer[5];
-
-    forEach(str, [&] (char32_t code) {
-        encode(toupper(code), buffer);
-        result += buffer;
-    });
-
-    return result;
-}
+auto toupper(std::string_view str) -> std::string;
 
 /**
  * Convert the UTF-32 string to lower case.
  *
- * \param str the str
+ * \param str the string
  * \return the lower case string
  */
-inline std::u32string tolower(std::u32string str)
-{
-    for (size_t i = 0; i < str.size(); ++i)
-        str[i] = tolower(str[i]);
-
-    return str;
-}
+auto tolower(std::u32string_view str) -> std::u32string;
 
 /**
  * Convert the UTF-8 string to lower case.
  *
- * \param str the str
+ * \param str the string
  * \return the lower case string
  * \warning very slow at the moment
  */
-inline std::string tolower(const std::string &str)
-{
-    std::string result;
-    char buffer[5];
+auto tolower(std::string_view str) -> std::string;
 
-    forEach(str, [&] (char32_t code) {
-        encode(tolower(code), buffer);
-        result += buffer;
-    });
-
-    return result;
-}
-
-} // !unicode
-
-} // !irccd
+} // !irccd::unicode
 
 #endif // !IRCCD_JS_UNICODE_HPP
--- a/libirccd-js/irccd/js/unicode_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/unicode_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -37,7 +37,7 @@
  */
 auto Unicode_isDigit(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::isdigit(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::isdigit(duk_get_int(ctx, 0)));
 }
 
 // }}}
@@ -55,7 +55,7 @@
  */
 auto Unicode_isLetter(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::isalpha(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::isalpha(duk_get_int(ctx, 0)));
 }
 
 // }}}
@@ -73,7 +73,7 @@
  */
 auto Unicode_isLower(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::islower(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::islower(duk_get_int(ctx, 0)));
 }
 
 // }}}
@@ -91,7 +91,7 @@
  */
 auto Unicode_isSpace(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::isspace(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::isspace(duk_get_int(ctx, 0)));
 }
 
 // }}}
@@ -109,7 +109,7 @@
  */
 auto Unicode_isTitle(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::istitle(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::istitle(duk_get_int(ctx, 0)));
 }
 
 // }}}
@@ -127,37 +127,37 @@
  */
 auto Unicode_isUpper(duk_context* ctx) noexcept -> duk_ret_t
 {
-    return duk::push(ctx, unicode::isupper(duk_get_int(ctx, 0)));
+	return duk::push(ctx, unicode::isupper(duk_get_int(ctx, 0)));
 }
 
 // }}}
 
 const duk_function_list_entry functions[] = {
-    { "isDigit",        Unicode_isDigit,    1 },
-    { "isLetter",       Unicode_isLetter,   1 },
-    { "isLower",        Unicode_isLower,    1 },
-    { "isSpace",        Unicode_isSpace,    1 },
-    { "isTitle",        Unicode_isTitle,    1 },
-    { "isUpper",        Unicode_isUpper,    1 },
-    { nullptr,          nullptr,            0 }
+	{ "isDigit",            Unicode_isDigit,        1 },
+	{ "isLetter",           Unicode_isLetter,       1 },
+	{ "isLower",            Unicode_isLower,        1 },
+	{ "isSpace",            Unicode_isSpace,        1 },
+	{ "isTitle",            Unicode_isTitle,        1 },
+	{ "isUpper",            Unicode_isUpper,        1 },
+	{ nullptr,              nullptr,                0 }
 };
 
 } // !namespace
 
 auto unicode_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Unicode";
+	return "Irccd.Unicode";
 }
 
 void unicode_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_put_prop_string(plugin->get_context(), -2, "Unicode");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_put_prop_string(plugin->get_context(), -2, "Unicode");
+	duk_pop(plugin->get_context());
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/unicode_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/unicode_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class unicode_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/util_js_api.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/util_js_api.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -44,26 +44,26 @@
  */
 auto subst(duk_context* ctx, int index) -> string_util::subst
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    if (!duk_is_object(ctx, index))
-        return params;
+	if (!duk_is_object(ctx, index))
+		return params;
 
-    duk_enum(ctx, index, 0);
+	duk_enum(ctx, index, 0);
 
-    while (duk_next(ctx, -1, true)) {
-        if (duk::get<std::string>(ctx, -2) == "date")
-            params.time = static_cast<time_t>(duk_get_number(ctx, -1) / 1000);
-        else
-            params.keywords.insert({
-                duk::get<std::string>(ctx, -2),
-                duk::get<std::string>(ctx, -1)
-            });
+	while (duk_next(ctx, -1, true)) {
+		if (duk::get<std::string>(ctx, -2) == "date")
+			params.time = static_cast<time_t>(duk_get_number(ctx, -1) / 1000);
+		else
+			params.keywords.insert({
+				duk::get<std::string>(ctx, -2),
+				duk::get<std::string>(ctx, -1)
+			});
 
-        duk_pop_n(ctx, 2);
-    }
+		duk_pop_n(ctx, 2);
+	}
 
-    return params;
+	return params;
 }
 
 // }}}
@@ -78,26 +78,26 @@
  */
 auto split(duk_context* ctx) -> std::vector<std::string>
 {
-    duk_require_type_mask(ctx, 0, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_STRING);
+	duk_require_type_mask(ctx, 0, DUK_TYPE_MASK_OBJECT | DUK_TYPE_MASK_STRING);
 
-    std::vector<std::string> result;
-    std::string pattern = " \t\n";
+	std::vector<std::string> result;
+	std::string pattern = " \t\n";
 
-    if (duk_is_string(ctx, 0))
-        result = string_util::split(duk::get<std::string>(ctx, 0), pattern);
-    else if (duk_is_array(ctx, 0)) {
-        duk_enum(ctx, 0, DUK_ENUM_ARRAY_INDICES_ONLY);
+	if (duk_is_string(ctx, 0))
+		result = string_util::split(duk::get<std::string>(ctx, 0), pattern);
+	else if (duk_is_array(ctx, 0)) {
+		duk_enum(ctx, 0, DUK_ENUM_ARRAY_INDICES_ONLY);
 
-        while (duk_next(ctx, -1, 1)) {
-            // Split individual tokens as array if spaces are found.
-            const auto tmp = string_util::split(duk_to_string(ctx, -1), pattern);
+		while (duk_next(ctx, -1, 1)) {
+			// Split individual tokens as array if spaces are found.
+			const auto tmp = string_util::split(duk_to_string(ctx, -1), pattern);
 
-            result.insert(result.end(), tmp.begin(), tmp.end());
-            duk_pop_2(ctx);
-        }
-    }
+			result.insert(result.end(), tmp.begin(), tmp.end());
+			duk_pop_2(ctx);
+		}
+	}
 
-    return result;
+	return result;
 }
 
 // }}}
@@ -114,15 +114,15 @@
  */
 auto limit(duk_context* ctx, int index, const char* name, int value) -> int
 {
-    if (duk_get_top(ctx) < index || !duk_is_number(ctx, index))
-        return value;
+	if (duk_get_top(ctx) < index || !duk_is_number(ctx, index))
+		return value;
 
-    value = duk_to_int(ctx, index);
+	value = duk_to_int(ctx, index);
 
-    if (value <= 0)
-        duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument %d (%s) must be positive", index, name);
+	if (value <= 0)
+		duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument %d (%s) must be positive", index, name);
 
-    return value;
+	return value;
 }
 
 // }}}
@@ -140,37 +140,37 @@
  *   - s is the current line
  *   - abc is the token to add
  *
- * s   = ""                 (new line)
+ * s   = ""				 (new line)
  * s  -> "abc"
  *
- * s   = "hello world"      (enough room)
+ * s   = "hello world"	  (enough room)
  * s  -> "hello world abc"
  *
- * s   = "hello world"      (not enough room: maxc is smaller)
+ * s   = "hello world"	  (not enough room: maxc is smaller)
  * s+1 = "abc"
  */
 auto lines(duk_context* ctx, const std::vector<std::string>& tokens, int maxc) -> std::vector<std::string>
 {
-    std::vector<std::string> result{""};
+	std::vector<std::string> result{""};
 
-    for (const auto& s : tokens) {
-        if (s.length() > static_cast<std::size_t>(maxc))
-            duk_error(ctx, DUK_ERR_RANGE_ERROR, "word '%s' could not fit in maxc limit (%d)", s.c_str(), maxc);
+	for (const auto& s : tokens) {
+		if (s.length() > static_cast<std::size_t>(maxc))
+			duk_error(ctx, DUK_ERR_RANGE_ERROR, "word '%s' could not fit in maxc limit (%d)", s.c_str(), maxc);
 
-        // Compute the length required (prepend a space if needed)
-        auto required = s.length() + (result.back().empty() ? 0 : 1);
+		// Compute the length required (prepend a space if needed)
+		auto required = s.length() + (result.back().empty() ? 0 : 1);
 
-        if (result.back().length() + required > static_cast<std::size_t>(maxc))
-            result.push_back(s);
-        else {
-            if (!result.back().empty())
-                result.back() += ' ';
+		if (result.back().length() + required > static_cast<std::size_t>(maxc))
+			result.push_back(s);
+		else {
+			if (!result.back().empty())
+				result.back() += ' ';
 
-            result.back() += s;
-        }
-    }
+			result.back() += s;
+		}
+	}
 
-    return result;
+	return result;
 }
 
 // }}}
@@ -180,15 +180,15 @@
 template <typename Handler>
 auto wrap(duk_context* ctx, Handler handler) -> duk_ret_t
 {
-    try {
-        return handler();
-    } catch (const std::system_error& ex) {
-        duk::raise(ctx, ex);
-    } catch (const std::exception& ex) {
-        duk::raise(ctx, ex);
-    }
+	try {
+		return handler();
+	} catch (const std::system_error& ex) {
+		duk::raise(ctx, ex);
+	} catch (const std::exception& ex) {
+		duk::raise(ctx, ex);
+	}
 
-    return 0;
+	return 0;
 }
 
 // }}}
@@ -230,21 +230,21 @@
  */
 auto Util_cut(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        const auto list = lines(ctx, split(ctx), limit(ctx, 1, "maxc", 72));
-        const auto maxl = limit(ctx, 2, "maxl", INT_MAX);
+	return wrap(ctx, [&] {
+		const auto list = lines(ctx, split(ctx), limit(ctx, 1, "maxc", 72));
+		const auto maxl = limit(ctx, 2, "maxl", INT_MAX);
 
-        if (list.size() > static_cast<std::size_t>(maxl))
-            return 0;
+		if (list.size() > static_cast<std::size_t>(maxl))
+			return 0;
 
-        // Empty list but lines() returns at least one.
-        if (list.size() == 1 && list[0].empty()) {
-            duk_push_array(ctx);
-            return 1;
-        }
+		// Empty list but lines() returns at least one.
+		if (list.size() == 1 && list[0].empty()) {
+			duk_push_array(ctx);
+			return 1;
+		}
 
-        return duk::push(ctx, list);
-    });
+		return duk::push(ctx, list);
+	});
 }
 
 // }}}
@@ -267,9 +267,9 @@
  */
 auto Util_format(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, string_util::format(duk::get<std::string>(ctx, 0), subst(ctx, 1)));
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, string_util::format(duk::get<std::string>(ctx, 0), subst(ctx, 1)));
+	});
 }
 
 // }}}
@@ -291,9 +291,9 @@
  */
 auto Util_splituser(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, irc::user::parse(duk::require<std::string>(ctx, 0)).nick);
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, irc::user::parse(duk::require<std::string>(ctx, 0)).nick);
+	});
 }
 
 // }}}
@@ -315,37 +315,37 @@
  */
 auto Util_splithost(duk_context* ctx) -> duk_ret_t
 {
-    return wrap(ctx, [&] {
-        return duk::push(ctx, irc::user::parse(duk::require<std::string>(ctx, 0)).host);
-    });
+	return wrap(ctx, [&] {
+		return duk::push(ctx, irc::user::parse(duk::require<std::string>(ctx, 0)).host);
+	});
 }
 
 // }}}
 
 const duk_function_list_entry functions[] = {
-    { "cut",        Util_cut,       DUK_VARARGS },
-    { "format",     Util_format,    DUK_VARARGS },
-    { "splituser",  Util_splituser, 1           },
-    { "splithost",  Util_splithost, 1           },
-    { nullptr,      nullptr,        0           }
+	{ "cut",        Util_cut,       DUK_VARARGS     },
+	{ "format",     Util_format,    DUK_VARARGS     },
+	{ "splituser",  Util_splituser, 1               },
+	{ "splithost",  Util_splithost, 1               },
+	{ nullptr,      nullptr,        0               }
 };
 
 } // !namespace
 
 auto util_js_api::get_name() const noexcept -> std::string_view
 {
-    return "Irccd.Util";
+	return "Irccd.Util";
 }
 
 void util_js_api::load(irccd&, std::shared_ptr<js_plugin> plugin)
 {
-    duk::stack_guard sa(plugin->get_context());
+	duk::stack_guard sa(plugin->get_context());
 
-    duk_get_global_string(plugin->get_context(), "Irccd");
-    duk_push_object(plugin->get_context());
-    duk_put_function_list(plugin->get_context(), -1, functions);
-    duk_put_prop_string(plugin->get_context(), -2, "Util");
-    duk_pop(plugin->get_context());
+	duk_get_global_string(plugin->get_context(), "Irccd");
+	duk_push_object(plugin->get_context());
+	duk_put_function_list(plugin->get_context(), -1, functions);
+	duk_put_prop_string(plugin->get_context(), -2, "Util");
+	duk_pop(plugin->get_context());
 }
 
 } // !irccd::js
--- a/libirccd-js/irccd/js/util_js_api.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-js/irccd/js/util_js_api.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,15 +34,15 @@
  */
 class util_js_api : public js_api {
 public:
-    /**
-     * \copydoc js_api::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc js_api::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc js_api::load
-     */
-    void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
+	/**
+	 * \copydoc js_api::load
+	 */
+	void load(irccd& irccd, std::shared_ptr<js_plugin> plugin) override;
 };
 
 } // !irccd::js
--- a/libirccd-test/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,50 +19,58 @@
 project(libirccd-test)
 
 set(
-    HEADERS
-    ${libirccd-test_SOURCE_DIR}/irccd/test/cli_fixture.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/command_fixture.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/irccd_fixture.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock_plugin.hpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock_server.hpp
-    $<$<BOOL:${IRCCD_HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/js_fixture.hpp>
-    $<$<BOOL:${IRCCD_HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/js_plugin_fixture.hpp>
+	HEADERS
+	${libirccd-test_SOURCE_DIR}/irccd/test/cli_fixture.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/command_fixture.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/irccd_fixture.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock_plugin.hpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock_server.hpp
 )
 
 set(
-    SOURCES
-    ${libirccd-test_SOURCE_DIR}/irccd/test/cli_fixture.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/command_fixture.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/irccd_fixture.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock_plugin.cpp
-    ${libirccd-test_SOURCE_DIR}/irccd/test/mock_server.cpp
-    $<$<BOOL:${IRCCD_HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/js_fixture.cpp>
-    $<$<BOOL:${IRCCD_HAVE_JS}>:${libirccd-test_SOURCE_DIR}/irccd/test/js_plugin_fixture.cpp>
+	SOURCES
+	${libirccd-test_SOURCE_DIR}/irccd/test/cli_fixture.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/command_fixture.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/debug_server.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/irccd_fixture.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock_plugin.cpp
+	${libirccd-test_SOURCE_DIR}/irccd/test/mock_server.cpp
 )
 
 if (${IRCCD_HAVE_JS})
-    list(APPEND LIBRARIES libirccd-js)
+	list(
+		APPEND
+		HEADERS
+		${libirccd-test_SOURCE_DIR}/irccd/test/js_fixture.hpp
+		${libirccd-test_SOURCE_DIR}/irccd/test/js_plugin_fixture.hpp
+	)
+	list(
+		APPEND
+		SOURCES
+		${libirccd-test_SOURCE_DIR}/irccd/test/js_fixture.cpp
+		${libirccd-test_SOURCE_DIR}/irccd/test/js_plugin_fixture.cpp
+	)
+	list(APPEND LIBRARIES libirccd-js)
 endif ()
 
 irccd_define_library(
-    TARGET libirccd-test
-    EXPORT
-    HEADERS ${HEADERS}
-    HEADERS_DIRECTORY irccd/test
-    SOURCES ${SOURCES}
-    LIBRARIES
-        ${LIBRARIES}
-        libirccd
-        libirccd-ctl
-    PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}>
-    FLAGS
-        $<BUILD_INTERFACE:IRCCD_EXECUTABLE="$<TARGET_FILE:irccd>">
-        $<BUILD_INTERFACE:IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>">
-        $<INSTALL_INTERFACE:IRCCD_EXECUTABLE="$<TARGET_FILE:irccd::irccd>">
-        $<INSTALL_INTERFACE:IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccd::irccdctl>">
+	TARGET libirccd-test
+	EXPORT
+	HEADERS ${HEADERS}
+	HEADERS_DIRECTORY irccd/test
+	SOURCES ${SOURCES}
+	LIBRARIES
+		${LIBRARIES}
+		libirccd
+		libirccd-ctl
+	PUBLIC_INCLUDES
+		$<BUILD_INTERFACE:${libirccd-test_SOURCE_DIR}>
+	FLAGS
+		$<BUILD_INTERFACE:IRCCD_EXECUTABLE="$<TARGET_FILE:irccd>">
+		$<BUILD_INTERFACE:IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccdctl>">
+		$<INSTALL_INTERFACE:IRCCD_EXECUTABLE="$<TARGET_FILE:irccd::irccd>">
+		$<INSTALL_INTERFACE:IRCCDCTL_EXECUTABLE="$<TARGET_FILE:irccd::irccdctl>">
 )
--- a/libirccd-test/irccd/test/cli_fixture.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/cli_fixture.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,64 +35,64 @@
 namespace irccd::test {
 
 cli_fixture::cli_fixture()
-    : server_(new mock_server(irccd_.get_service(), "test", "localhost"))
+	: server_(new mock_server(irccd_.get_service(), "test", "localhost"))
 {
-    std::remove(CMAKE_BINARY_DIR "/tmp/irccd.sock");
+	std::remove(CMAKE_BINARY_DIR "/tmp/irccd.sock");
 
-    io::local_acceptor::endpoint endpoint(CMAKE_BINARY_DIR "/tmp/irccd.sock");
-    io::local_acceptor::acceptor acceptor(service_, std::move(endpoint));
+	local_acceptor::endpoint endpoint(CMAKE_BINARY_DIR "/tmp/irccd.sock");
+	local_acceptor::acceptor acceptor(service_, std::move(endpoint));
 
-    for (const auto& f : command::registry)
-        irccd_.transports().get_commands().push_back(f());
+	for (const auto& f : command::registry)
+		irccd_.transports().get_commands().push_back(f());
 
-    irccd_.servers().add(server_);
-    irccd_.transports().add(std::make_unique<transport_server>(
-        std::make_unique<io::local_acceptor>(std::move(acceptor))));
-    server_->disconnect();
-    server_->clear();
+	irccd_.servers().add(server_);
+	irccd_.transports().add(std::make_unique<transport_server>(
+		std::make_unique<local_acceptor>(std::move(acceptor))));
+	server_->disconnect();
+	server_->clear();
 }
 
 cli_fixture::~cli_fixture()
 {
-    service_.stop();
-    thread_.join();
+	service_.stop();
+	thread_.join();
 }
 
 void cli_fixture::start()
 {
-    thread_ = std::thread([this] { service_.run(); });
+	thread_ = std::thread([this] { service_.run(); });
 
-    // Let irccd bind correctly.
-    std::this_thread::sleep_for(std::chrono::milliseconds(250));
+	// Let irccd bind correctly.
+	std::this_thread::sleep_for(std::chrono::milliseconds(250));
 }
 
 auto cli_fixture::exec(const std::vector<std::string>& args) -> result
 {
-    static const std::string irccdctl = IRCCDCTL_EXECUTABLE;
-    static const std::string conf = CMAKE_BINARY_DIR "/tmp/irccdctl.conf";
+	static const std::string irccdctl = IRCCDCTL_EXECUTABLE;
+	static const std::string conf = CMAKE_BINARY_DIR "/tmp/irccdctl.conf";
 
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    oss << irccdctl << " -c " << conf << " ";
-    oss << string_util::join(args, " ");
+	oss << irccdctl << " -c " << conf << " ";
+	oss << string_util::join(args, " ");
 
-    proc::ipstream stream_out, stream_err;
+	proc::ipstream stream_out, stream_err;
 
-    const auto ret = proc::system(
-        oss.str(),
-        proc::std_in.close(),
-        proc::std_out > stream_out,
-        proc::std_err > stream_err
-    );
+	const auto ret = proc::system(
+		oss.str(),
+		proc::std_in.close(),
+		proc::std_out > stream_out,
+		proc::std_err > stream_err
+	);
 
-    outputs out, err;
+	outputs out, err;
 
-    for (std::string line; stream_out && std::getline(stream_out, line); )
-        out.push_back(line);
-    for (std::string line; stream_err && std::getline(stream_err, line); )
-        err.push_back(line);
+	for (std::string line; stream_out && std::getline(stream_out, line); )
+		out.push_back(line);
+	for (std::string line; stream_err && std::getline(stream_err, line); )
+		err.push_back(line);
 
-    return { ret, out, err };
+	return { ret, out, err };
 }
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/cli_fixture.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/cli_fixture.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -51,60 +51,60 @@
  */
 class cli_fixture {
 private:
-    using io_service = boost::asio::io_service;
+	using io_service = boost::asio::io_service;
 
-    std::thread thread_;
-    io_service service_;
+	std::thread thread_;
+	io_service service_;
 
 protected:
-    /**
-     * Irccd instance.
-     *
-     * \warning Do not modify once `start()` has been called.
-     */
-    irccd irccd_{service_};
+	/**
+	 * Irccd instance.
+	 *
+	 * \warning Do not modify once `start()` has been called.
+	 */
+	irccd irccd_{service_};
 
-    /**
-     * Server automatically added as "test".
-     */
-    std::shared_ptr<mock_server> server_;
+	/**
+	 * Server automatically added as "test".
+	 */
+	std::shared_ptr<mock_server> server_;
 
 public:
-    /**
-     * Type for all lines printed.
-     */
-    using outputs = std::vector<std::string>;
+	/**
+	 * Type for all lines printed.
+	 */
+	using outputs = std::vector<std::string>;
 
-    /**
-     * Collection of output from stdout/stderr respectively.
-     */
-    using result = std::tuple<int, outputs, outputs>;
+	/**
+	 * Collection of output from stdout/stderr respectively.
+	 */
+	using result = std::tuple<int, outputs, outputs>;
 
-    /**
-     * Construct and initialize and irccd daemon running in a thread.
-     */
-    cli_fixture();
+	/**
+	 * Construct and initialize and irccd daemon running in a thread.
+	 */
+	cli_fixture();
 
-    /**
-     * Stop irccd and close everything.
-     */
-    ~cli_fixture();
+	/**
+	 * Stop irccd and close everything.
+	 */
+	~cli_fixture();
 
-    /**
-     * Start irccd daemon.
-     *
-     * A thread will be running and closed when the destructor is called, you
-     * MUST not modify irccd while running.
-     */
-    void start();
+	/**
+	 * Start irccd daemon.
+	 *
+	 * A thread will be running and closed when the destructor is called, you
+	 * MUST not modify irccd while running.
+	 */
+	void start();
 
-    /**
-     * Execute irccdctl.
-     *
-     * \param args the arguments to irccdctl
-     * \return the stdout/stderr and exit code
-     */
-    auto exec(const std::vector<std::string>& args) -> result;
+	/**
+	 * Execute irccdctl.
+	 *
+	 * \param args the arguments to irccdctl
+	 * \return the stdout/stderr and exit code
+	 */
+	auto exec(const std::vector<std::string>& args) -> result;
 };
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/command_fixture.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/command_fixture.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,80 +30,80 @@
 template <typename Condition>
 void command_fixture::wait_for(Condition&& cond)
 {
-    ctx_.reset();
+	ctx_.reset();
 
-    while (!cond())
-        ctx_.poll();
+	while (!cond())
+		ctx_.poll();
 }
 
 auto command_fixture::request(nlohmann::json json) -> result
 {
-    result r;
+	result r;
 
-    ctl_->write(std::move(json));
-    ctl_->read([&] (auto result, auto message) {
-        r.first = message;
-        r.second = result;
-    });
-    wait_for([&] {
-        return r.second || r.first.is_object();
-    });
+	ctl_->write(std::move(json));
+	ctl_->read([&] (auto result, auto message) {
+		r.first = message;
+		r.second = result;
+	});
+	wait_for([&] {
+		return r.second || r.first.is_object();
+	});
 
-    return r;
+	return r;
 }
 
 command_fixture::command_fixture()
-    : server_(new mock_server(ctx_, "test", "localhost"))
-    , plugin_(new mock_plugin("test"))
+	: server_(new mock_server(ctx_, "test", "localhost"))
+	, plugin_(new mock_plugin("test"))
 {
-    using boost::asio::ip::tcp;
+	using boost::asio::ip::tcp;
 
-    // 1. Add all commands.
-    for (const auto& f : command::registry)
-        irccd_.transports().get_commands().push_back(f());
+	// 1. Add all commands.
+	for (const auto& f : command::registry)
+		irccd_.transports().get_commands().push_back(f());
 
-    // 2. Bind to a random port.
-    tcp::endpoint ep(tcp::v4(), 0);
-    tcp::acceptor acc(ctx_, ep);
+	// 2. Bind to a random port.
+	tcp::endpoint ep(tcp::v4(), 0);
+	tcp::acceptor acc(ctx_, ep);
 
-    // 3. Create controller and transport server.
-    ctl_ = std::make_unique<ctl::controller>(
-        std::make_unique<io::ip_connector>(ctx_, acc.local_endpoint()));
-    irccd_.transports().add(std::make_unique<transport_server>(
-        std::make_unique<io::ip_acceptor>(std::move(acc))));
+	// 3. Create controller and transport server.
+	ctl_ = std::make_unique<ctl::controller>(
+		std::make_unique<ip_connector>(ctx_, acc.local_endpoint()));
+	irccd_.transports().add(std::make_unique<transport_server>(
+		std::make_unique<ip_acceptor>(std::move(acc))));
 
-    // Wait for controller to connect.
-    boost::asio::deadline_timer timer(ctx_);
+	// Wait for controller to connect.
+	boost::asio::deadline_timer timer(ctx_);
 
-    timer.expires_from_now(boost::posix_time::seconds(10));
-    timer.async_wait([] (auto code) {
-        if (code && code != boost::asio::error::operation_aborted)
-            throw std::system_error(make_error_code(std::errc::timed_out));
-    });
+	timer.expires_from_now(boost::posix_time::seconds(10));
+	timer.async_wait([] (auto code) {
+		if (code && code != boost::asio::error::operation_aborted)
+			throw std::system_error(make_error_code(std::errc::timed_out));
+	});
 
-    bool connected = false;
+	bool connected = false;
 
-    ctl_->connect([&] (auto code, auto) {
-        timer.cancel();
+	ctl_->connect([&] (auto code, auto) {
+		timer.cancel();
 
-        if (code)
-            throw std::system_error(code);
+		if (code)
+			throw std::system_error(code);
 
-        connected = true;
-    });
+		connected = true;
+	});
 
-    /**
-     * Irccd will block indefinitely since transport_service will wait for any
-     * new client again, so we need to check with a boolean.
-     */
-    while (!connected)
-        ctx_.poll();
+	/**
+	 * Irccd will block indefinitely since transport_service will wait for any
+	 * new client again, so we need to check with a boolean.
+	 */
+	while (!connected)
+		ctx_.poll();
 
-    irccd_.servers().add(server_);
-    irccd_.plugins().add(plugin_);
-    server_->disconnect();
-    server_->clear();
-    plugin_->clear();
+	irccd_.servers().add(server_);
+	irccd_.plugins().add(plugin_);
+	server_->disconnect();
+	server_->clear();
+	plugin_->clear();
 }
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/command_fixture.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/command_fixture.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -44,42 +44,42 @@
  */
 class command_fixture : public irccd_fixture {
 private:
-    template <typename Condition>
-    void wait_for(Condition&&);
+	template <typename Condition>
+	void wait_for(Condition&&);
 
 protected:
-    /**
-     * \brief Result for request function.
-     */
-    using result = std::pair<nlohmann::json, std::error_code>;
+	/**
+	 * \brief Result for request function.
+	 */
+	using result = std::pair<nlohmann::json, std::error_code>;
 
-    /**
-     * \brief Irccd controller
-     */
-    std::unique_ptr<ctl::controller> ctl_;
+	/**
+	 * \brief Irccd controller
+	 */
+	std::unique_ptr<ctl::controller> ctl_;
 
-    /**
-     * \brief Mock server object.
-     */
-    std::shared_ptr<mock_server> server_;
+	/**
+	 * \brief Mock server object.
+	 */
+	std::shared_ptr<mock_server> server_;
 
-    /**
-     * \brief Mock plugin object.
-     */
-    std::shared_ptr<mock_plugin> plugin_;
+	/**
+	 * \brief Mock plugin object.
+	 */
+	std::shared_ptr<mock_plugin> plugin_;
 
-    /**
-     * Constructor.
-     */
-    command_fixture();
+	/**
+	 * Constructor.
+	 */
+	command_fixture();
 
-    /**
-     * Get result from irccd.
-     *
-     * \param json the request
-     * \return the result/error pair
-     */
-    auto request(nlohmann::json json) -> result;
+	/**
+	 * Get result from irccd.
+	 *
+	 * \param json the request
+	 * \return the result/error pair
+	 */
+	auto request(nlohmann::json json) -> result;
 };
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/debug_server.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/debug_server.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -24,37 +24,37 @@
 
 void debug_server::connect(connect_handler) noexcept
 {
-    std::cout << get_id() << ": connect" << std::endl;
+	std::cout << get_id() << ": connect" << std::endl;
 }
 
 void debug_server::disconnect() noexcept
 {
-    std::cout << get_id() << ": disconnect" << std::endl;
+	std::cout << get_id() << ": disconnect" << std::endl;
 }
 
 void debug_server::invite(std::string_view target, std::string_view channel)
 {
-    std::cout << get_id() << ": invite " << target << " " << channel << std::endl;
+	std::cout << get_id() << ": invite " << target << " " << channel << std::endl;
 }
 
 void debug_server::join(std::string_view channel, std::string_view password)
 {
-    std::cout << get_id() << ": join " << channel << " " << password << std::endl;
+	std::cout << get_id() << ": join " << channel << " " << password << std::endl;
 }
 
 void debug_server::kick(std::string_view target, std::string_view channel, std::string_view reason)
 {
-    std::cout << get_id() << ": kick " << target << " " << channel << " " << reason << std::endl;
+	std::cout << get_id() << ": kick " << target << " " << channel << " " << reason << std::endl;
 }
 
 void debug_server::me(std::string_view target, std::string_view message)
 {
-    std::cout << get_id() << ": me " << target << " " << message << std::endl;
+	std::cout << get_id() << ": me " << target << " " << message << std::endl;
 }
 
 void debug_server::message(std::string_view target, std::string_view message)
 {
-    std::cout << get_id() << ": message " << target << " " << message << std::endl;
+	std::cout << get_id() << ": message " << target << " " << message << std::endl;
 }
 
 void debug_server::mode(std::string_view channel,
@@ -63,42 +63,42 @@
                         std::string_view user,
                         std::string_view mask)
 {
-    std::cout << get_id() << ": mode "
-              << channel << " "
-              << mode << " "
-              << limit << " "
-              << user << " "
-              << mask << std::endl;
+	std::cout << get_id() << ": mode "
+	          << channel << " "
+	          << mode << " "
+	          << limit << " "
+	          << user << " "
+	          << mask << std::endl;
 }
 
 void debug_server::names(std::string_view channel)
 {
-    std::cout << get_id() << ": names " << channel << std::endl;
+	std::cout << get_id() << ": names " << channel << std::endl;
 }
 
 void debug_server::notice(std::string_view target, std::string_view message)
 {
-    std::cout << get_id() << ": notice " << target << " " << message << std::endl;
+	std::cout << get_id() << ": notice " << target << " " << message << std::endl;
 }
 
 void debug_server::part(std::string_view channel, std::string_view reason)
 {
-    std::cout << get_id() << ": part " << channel << " " << reason << std::endl;
+	std::cout << get_id() << ": part " << channel << " " << reason << std::endl;
 }
 
 void debug_server::send(std::string_view raw)
 {
-    std::cout << get_id() << ": send " << raw << std::endl;
+	std::cout << get_id() << ": send " << raw << std::endl;
 }
 
 void debug_server::topic(std::string_view channel, std::string_view topic)
 {
-    std::cout << get_id() << ": topic " << channel << " " << topic << std::endl;
+	std::cout << get_id() << ": topic " << channel << " " << topic << std::endl;
 }
 
 void debug_server::whois(std::string_view target)
 {
-    std::cout << get_id() << ": whois " << target << std::endl;
+	std::cout << get_id() << ": whois " << target << std::endl;
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/debug_server.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/debug_server.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,84 +33,84 @@
  */
 class debug_server : public server {
 public:
-    /**
-     * Inherited constructors.
-     */
-    using server::server;
+	/**
+	 * Inherited constructors.
+	 */
+	using server::server;
 
-    /**
-     * \copydoc server::connect
-     */
-    void connect(connect_handler) noexcept override;
+	/**
+	 * \copydoc server::connect
+	 */
+	void connect(connect_handler) noexcept override;
 
-    /**
-     * \copydoc server::connect
-     */
-    void disconnect() noexcept override;
+	/**
+	 * \copydoc server::connect
+	 */
+	void disconnect() noexcept override;
 
-    /**
-     * \copydoc server::invite
-     */
-    void invite(std::string_view target, std::string_view channel) override;
+	/**
+	 * \copydoc server::invite
+	 */
+	void invite(std::string_view target, std::string_view channel) override;
 
-    /**
-     * \copydoc server::join
-     */
-    void join(std::string_view channel, std::string_view password = "") override;
+	/**
+	 * \copydoc server::join
+	 */
+	void join(std::string_view channel, std::string_view password = "") override;
 
-    /**
-     * \copydoc server::kick
-     */
-    void kick(std::string_view target, std::string_view channel, std::string_view reason = "") override;
+	/**
+	 * \copydoc server::kick
+	 */
+	void kick(std::string_view target, std::string_view channel, std::string_view reason = "") override;
 
-    /**
-     * \copydoc server::me
-     */
-    void me(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::me
+	 */
+	void me(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::message
-     */
-    void message(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::message
+	 */
+	void message(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::mode
-     */
-    void mode(std::string_view channel,
-              std::string_view mode,
-              std::string_view limit = "",
-              std::string_view user = "",
-              std::string_view mask = "") override;
+	/**
+	 * \copydoc server::mode
+	 */
+	void mode(std::string_view channel,
+	          std::string_view mode,
+	          std::string_view limit = "",
+	          std::string_view user = "",
+	          std::string_view mask = "") override;
 
-    /**
-     * \copydoc server::names
-     */
-    void names(std::string_view channel) override;
+	/**
+	 * \copydoc server::names
+	 */
+	void names(std::string_view channel) override;
 
-    /**
-     * \copydoc server::notice
-     */
-    void notice(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::notice
+	 */
+	void notice(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::part
-     */
-    void part(std::string_view channel, std::string_view reason = "") override;
+	/**
+	 * \copydoc server::part
+	 */
+	void part(std::string_view channel, std::string_view reason = "") override;
 
-    /**
-     * \copydoc server::send
-     */
-    void send(std::string_view raw) override;
+	/**
+	 * \copydoc server::send
+	 */
+	void send(std::string_view raw) override;
 
-    /**
-     * \copydoc server::topic
-     */
-    void topic(std::string_view channel, std::string_view topic) override;
+	/**
+	 * \copydoc server::topic
+	 */
+	void topic(std::string_view channel, std::string_view topic) override;
 
-    /**
-     * \copydoc server::whois
-     */
-    void whois(std::string_view target) override;
+	/**
+	 * \copydoc server::whois
+	 */
+	void whois(std::string_view target) override;
 };
 
 } // !irccd
--- a/libirccd-test/irccd/test/irccd_fixture.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/irccd_fixture.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -24,7 +24,7 @@
 
 irccd_fixture::irccd_fixture()
 {
-    irccd_.set_log(std::make_unique<logger::silent_sink>());
+	irccd_.set_log(std::make_unique<logger::silent_sink>());
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/irccd_fixture.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/irccd_fixture.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,22 +33,22 @@
  */
 class irccd_fixture {
 protected:
-    /**
-     * \brief Boost.Asio context.
-     */
-    boost::asio::io_context ctx_;
+	/**
+	 * \brief Boost.Asio context.
+	 */
+	boost::asio::io_context ctx_;
 
-    /**
-     * \brief Main irccd daemon.
-     */
-    irccd irccd_{ctx_};
+	/**
+	 * \brief Main irccd daemon.
+	 */
+	irccd irccd_{ctx_};
 
-    /**
-     * Default constructor.
-     *
-     * Initialize the logger with a silent sink.
-     */
-    irccd_fixture();
+	/**
+	 * Default constructor.
+	 *
+	 * Initialize the logger with a silent sink.
+	 */
+	irccd_fixture();
 };
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/js_fixture.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/js_fixture.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -21,13 +21,13 @@
 namespace irccd::test {
 
 js_fixture::js_fixture(const std::string& path)
-    : plugin_(new js::js_plugin("test", path))
+	: plugin_(new js::js_plugin("test", path))
 {
-    for (const auto& f : js::js_api::registry)
-        f()->load(irccd_, plugin_);
+	for (const auto& f : js::js_api::registry)
+		f()->load(irccd_, plugin_);
 
-    if (!path.empty())
-        plugin_->open();
+	if (!path.empty())
+		plugin_->open();
 }
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/js_fixture.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/js_fixture.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,19 +38,19 @@
  */
 class js_fixture : public irccd_fixture {
 protected:
-    /**
-     * \brief Javascript plugin.
-     */
-    std::shared_ptr<js::js_plugin> plugin_;
+	/**
+	 * \brief Javascript plugin.
+	 */
+	std::shared_ptr<js::js_plugin> plugin_;
 
-    /**
-     * Constructor.
-     *
-     * Initialize a Javascript plugin with all Javascript API modules.
-     *
-     * \param path the path to a Javascript file if required
-     */
-    js_fixture(const std::string& path = "");
+	/**
+	 * Constructor.
+	 *
+	 * Initialize a Javascript plugin with all Javascript API modules.
+	 *
+	 * \param path the path to a Javascript file if required
+	 */
+	js_fixture(const std::string& path = "");
 };
 
 } // !irccd::test
--- a/libirccd-test/irccd/test/js_plugin_fixture.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/js_plugin_fixture.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -40,23 +40,23 @@
 namespace irccd {
 
 js_plugin_fixture::js_plugin_fixture(std::string path)
-    : server_(std::make_shared<mock_server>(service_, "test", "local"))
+	: server_(std::make_shared<mock_server>(service_, "test", "local"))
 {
-    plugin_ = std::make_unique<js::js_plugin>("test", std::move(path));
+	plugin_ = std::make_unique<js::js_plugin>("test", std::move(path));
 
-    irccd_.set_log(std::make_unique<logger::silent_sink>());
-    irccd_.get_log().set_verbose(false);
-    irccd_.plugins().add(plugin_);
-    irccd_.servers().add(server_);
+	irccd_.set_log(std::make_unique<logger::silent_sink>());
+	irccd_.get_log().set_verbose(false);
+	irccd_.plugins().add(plugin_);
+	irccd_.servers().add(server_);
 
-    server_->disconnect();
-    server_->set_nickname("irccd");
-    server_->clear();
+	server_->disconnect();
+	server_->set_nickname("irccd");
+	server_->clear();
 
-    for (const auto& f : js::js_api::registry)
-        f()->load(irccd_, plugin_);
+	for (const auto& f : js::js_api::registry)
+		f()->load(irccd_, plugin_);
 
-    plugin_->open();
+	plugin_->open();
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/js_plugin_fixture.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/js_plugin_fixture.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -39,18 +39,18 @@
  */
 class js_plugin_fixture {
 protected:
-    boost::asio::io_service service_;
-    irccd irccd_{service_};
-    std::shared_ptr<js::js_plugin> plugin_;
-    std::shared_ptr<mock_server> server_;
+	boost::asio::io_service service_;
+	irccd irccd_{service_};
+	std::shared_ptr<js::js_plugin> plugin_;
+	std::shared_ptr<mock_server> server_;
 
 public:
-    /**
-     * Construct the fixture test.
-     *
-     * \param path the full plugin path (e.g. /usr/lib64/irccd/ask.js)
-     */
-    js_plugin_fixture(std::string path);
+	/**
+	 * Construct the fixture test.
+	 *
+	 * \param path the full plugin path (e.g. /usr/lib64/irccd/ask.js)
+	 */
+	js_plugin_fixture(std::string path);
 };
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -22,30 +22,30 @@
 
 void mock::push(std::string name, args args) const
 {
-    table_[name].push_back(std::move(args));
+	table_[name].push_back(std::move(args));
 }
 
 auto mock::find(const std::string& name) const -> std::vector<args>
 {
-    if (const auto it = table_.find(name); it != table_.end())
-        return it->second;
+	if (const auto it = table_.find(name); it != table_.end())
+		return it->second;
 
-    return {};
+	return {};
 }
 
 void mock::clear(const std::string& name) const noexcept
 {
-    table_.erase(name);
+	table_.erase(name);
 }
 
 void mock::clear() const noexcept
 {
-    table_.clear();
+	table_.clear();
 }
 
 auto mock::empty() const noexcept -> bool
 {
-    return table_.empty();
+	return table_.empty();
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -37,54 +37,54 @@
  */
 class mock {
 public:
-    /**
-     * \brief Functions arguments.
-     */
-    using args = std::vector<std::any>;
+	/**
+	 * \brief Functions arguments.
+	 */
+	using args = std::vector<std::any>;
 
-    /**
-     * \brief Map of all functions.
-     */
-    using functions = std::unordered_map<std::string, std::vector<args>>;
+	/**
+	 * \brief Map of all functions.
+	 */
+	using functions = std::unordered_map<std::string, std::vector<args>>;
 
 private:
-    mutable functions table_;
+	mutable functions table_;
 
 public:
-    /**
-     * Register a new function invocation.
-     *
-     * \param name the function name
-     * \param args the arguments list
-     */
-    void push(std::string name, args args = {}) const;
+	/**
+	 * Register a new function invocation.
+	 *
+	 * \param name the function name
+	 * \param args the arguments list
+	 */
+	void push(std::string name, args args = {}) const;
 
-    /**
-     * Get all function invocations by name.
-     *
-     * \param name the function name
-     * \return the list of functions and their arguments or empty if not called
-     */
-    auto find(const std::string& name) const -> std::vector<args>;
+	/**
+	 * Get all function invocations by name.
+	 *
+	 * \param name the function name
+	 * \return the list of functions and their arguments or empty if not called
+	 */
+	auto find(const std::string& name) const -> std::vector<args>;
 
-    /**
-     * Clear all function invocations by name.
-     *
-     * \param name the function name
-     */
-    void clear(const std::string& name) const noexcept;
+	/**
+	 * Clear all function invocations by name.
+	 *
+	 * \param name the function name
+	 */
+	void clear(const std::string& name) const noexcept;
 
-    /**
-     * Clear all function invocations.
-     */
-    void clear() const noexcept;
+	/**
+	 * Clear all function invocations.
+	 */
+	void clear() const noexcept;
 
-    /**
-     * Tells if no functions have been called.
-     *
-     * \return true if no functions have been called
-     */
-    auto empty() const noexcept -> bool;
+	/**
+	 * Tells if no functions have been called.
+	 *
+	 * \return true if no functions have been called
+	 */
+	auto empty() const noexcept -> bool;
 };
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock_plugin.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock_plugin.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -24,169 +24,169 @@
 
 auto mock_plugin::get_name() const noexcept -> std::string_view
 {
-    push("get_name");
+	push("get_name");
 
-    return "mock";
+	return "mock";
 }
 
 auto mock_plugin::get_author() const noexcept -> std::string_view
 {
-    push("get_author");
+	push("get_author");
 
-    return "David Demelier <markand@malikania.fr>";
+	return "David Demelier <markand@malikania.fr>";
 }
 
 auto mock_plugin::get_license() const noexcept -> std::string_view
 {
-    push("get_license");
+	push("get_license");
 
-    return "ISC";
+	return "ISC";
 }
 
 auto mock_plugin::get_summary() const noexcept -> std::string_view
 {
-    push("get_summary");
+	push("get_summary");
 
-    return "mock plugin";
+	return "mock plugin";
 }
 
 auto mock_plugin::get_version() const noexcept -> std::string_view
 {
-    push("get_version");
+	push("get_version");
 
-    return "1.0";
+	return "1.0";
 }
 
 auto mock_plugin::get_options() const -> map
 {
-    push("get_options");
+	push("get_options");
 
-    return options_;
+	return options_;
 }
 
 void mock_plugin::set_options(const map& map)
 {
-    push("set_options", { map });
+	push("set_options", { map });
 
-    options_ = map;
+	options_ = map;
 }
 
 auto mock_plugin::get_formats() const -> map
 {
-    push("get_formats");
+	push("get_formats");
 
-    return formats_;
+	return formats_;
 }
 
 void mock_plugin::set_formats(const map& map)
 {
-    push("set_formats", { map });
+	push("set_formats", { map });
 
-    formats_ = map;
+	formats_ = map;
 }
 
 auto mock_plugin::get_paths() const -> map
 {
-    push("get_paths");
+	push("get_paths");
 
-    return paths_;
+	return paths_;
 }
 
 void mock_plugin::set_paths(const map& map)
 {
-    push("set_paths", { map });
+	push("set_paths", { map });
 
-    paths_ = map;
+	paths_ = map;
 }
 
 void mock_plugin::handle_command(irccd&, const message_event& event)
 {
-    push("handle_command", { event });
+	push("handle_command", { event });
 }
 
 void mock_plugin::handle_connect(irccd&, const connect_event& event)
 {
-    push("handle_connect", { event });
+	push("handle_connect", { event });
 }
 
 void mock_plugin::handle_disconnect(irccd&, const disconnect_event& event)
 {
-    push("handle_disconnect", { event });
+	push("handle_disconnect", { event });
 }
 
 void mock_plugin::handle_invite(irccd&, const invite_event& event)
 {
-    push("handle_invite", { event });
+	push("handle_invite", { event });
 }
 
 void mock_plugin::handle_join(irccd&, const join_event& event)
 {
-    push("handle_join", { event });
+	push("handle_join", { event });
 }
 
 void mock_plugin::handle_kick(irccd&, const kick_event& event)
 {
-    push("handle_kick", { event });
+	push("handle_kick", { event });
 }
 
 void mock_plugin::handle_load(irccd&)
 {
-    push("handle_load");
+	push("handle_load");
 }
 
 void mock_plugin::handle_message(irccd&, const message_event& event)
 {
-    push("handle_message", { event });
+	push("handle_message", { event });
 }
 
 void mock_plugin::handle_me(irccd&, const me_event& event)
 {
-    push("handle_me", { event });
+	push("handle_me", { event });
 }
 
 void mock_plugin::handle_mode(irccd&, const mode_event& event)
 {
-    push("handle_mode", { event });
+	push("handle_mode", { event });
 }
 
 void mock_plugin::handle_names(irccd&, const names_event& event)
 {
-    push("handle_names", { event });
+	push("handle_names", { event });
 }
 
 void mock_plugin::handle_nick(irccd&, const nick_event& event)
 {
-    push("handle_nick", { event });
+	push("handle_nick", { event });
 }
 
 void mock_plugin::handle_notice(irccd&, const notice_event& event)
 {
-    push("handle_notice", { event });
+	push("handle_notice", { event });
 }
 
 void mock_plugin::handle_part(irccd&, const part_event& event)
 {
-    push("handle_part", { event });
+	push("handle_part", { event });
 }
 
 void mock_plugin::handle_reload(irccd&)
 {
-    push("handle_reload");
+	push("handle_reload");
 }
 
 void mock_plugin::handle_topic(irccd&, const topic_event& event)
 {
-    push("handle_topic", { event });
+	push("handle_topic", { event });
 }
 
 void mock_plugin::handle_unload(irccd&)
 {
-    push("handle_unload");
+	push("handle_unload");
 }
 
 void mock_plugin::handle_whois(irccd&, const whois_event& event)
 {
-    push("handle_whois", { event });
+	push("handle_whois", { event });
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock_plugin.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock_plugin.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,157 +35,157 @@
  */
 class mock_plugin : public plugin, public mock {
 private:
-    map options_;
-    map formats_;
-    map paths_;
+	map options_;
+	map formats_;
+	map paths_;
 
 public:
-    using plugin::plugin;
+	using plugin::plugin;
 
-    /**
-     * \copydoc plugin::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_author
-     */
-    auto get_author() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_author
+	 */
+	auto get_author() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_license
-     */
-    auto get_license() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_license
+	 */
+	auto get_license() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_summary
-     */
-    auto get_summary() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_summary
+	 */
+	auto get_summary() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_version
-     */
-    auto get_version() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_version
+	 */
+	auto get_version() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_options
-     */
-    auto get_options() const -> map override;
+	/**
+	 * \copydoc plugin::get_options
+	 */
+	auto get_options() const -> map override;
 
-    /**
-     * \copydoc plugin::set_options
-     */
-    void set_options(const map& map) override;
+	/**
+	 * \copydoc plugin::set_options
+	 */
+	void set_options(const map& map) override;
 
-    /**
-     * \copydoc plugin::get_formats
-     */
-    auto get_formats() const -> map override;
+	/**
+	 * \copydoc plugin::get_formats
+	 */
+	auto get_formats() const -> map override;
 
-    /**
-     * \copydoc plugin::set_formats
-     */
-    void set_formats(const map& map) override;
+	/**
+	 * \copydoc plugin::set_formats
+	 */
+	void set_formats(const map& map) override;
 
-    /**
-     * \copydoc plugin::get_paths
-     */
-    auto get_paths() const -> map override;
+	/**
+	 * \copydoc plugin::get_paths
+	 */
+	auto get_paths() const -> map override;
 
-    /**
-     * \copydoc plugin::set_path
-     */
-    void set_paths(const map& map) override;
+	/**
+	 * \copydoc plugin::set_path
+	 */
+	void set_paths(const map& map) override;
 
-    /**
-     * \copydoc plugin::handle_command
-     */
-    void handle_command(irccd& irccd, const message_event& event) override;
+	/**
+	 * \copydoc plugin::handle_command
+	 */
+	void handle_command(irccd& irccd, const message_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_connect
-     */
-    void handle_connect(irccd& irccd, const connect_event& event) override;
+	/**
+	 * \copydoc plugin::handle_connect
+	 */
+	void handle_connect(irccd& irccd, const connect_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_disconnect
-     */
-    void handle_disconnect(irccd& irccd, const disconnect_event& event) override;
+	/**
+	 * \copydoc plugin::handle_disconnect
+	 */
+	void handle_disconnect(irccd& irccd, const disconnect_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_invite
-     */
-    void handle_invite(irccd& irccd, const invite_event& event) override;
+	/**
+	 * \copydoc plugin::handle_invite
+	 */
+	void handle_invite(irccd& irccd, const invite_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_join
-     */
-    void handle_join(irccd& irccd, const join_event& event) override;
+	/**
+	 * \copydoc plugin::handle_join
+	 */
+	void handle_join(irccd& irccd, const join_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_kick
-     */
-    void handle_kick(irccd& irccd, const kick_event& event) override;
+	/**
+	 * \copydoc plugin::handle_kick
+	 */
+	void handle_kick(irccd& irccd, const kick_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_load
-     */
-    void handle_load(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_load
+	 */
+	void handle_load(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_message
-     */
-    void handle_message(irccd& irccd, const message_event& event) override;
+	/**
+	 * \copydoc plugin::handle_message
+	 */
+	void handle_message(irccd& irccd, const message_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_me
-     */
-    void handle_me(irccd& irccd, const me_event& event) override;
+	/**
+	 * \copydoc plugin::handle_me
+	 */
+	void handle_me(irccd& irccd, const me_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_mode
-     */
-    void handle_mode(irccd& irccd, const mode_event& event) override;
+	/**
+	 * \copydoc plugin::handle_mode
+	 */
+	void handle_mode(irccd& irccd, const mode_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_names
-     */
-    void handle_names(irccd& irccd, const names_event& event) override;
+	/**
+	 * \copydoc plugin::handle_names
+	 */
+	void handle_names(irccd& irccd, const names_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_nick
-     */
-    void handle_nick(irccd& irccd, const nick_event& event) override;
+	/**
+	 * \copydoc plugin::handle_nick
+	 */
+	void handle_nick(irccd& irccd, const nick_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_notice
-     */
-    void handle_notice(irccd& irccd, const notice_event& event) override;
+	/**
+	 * \copydoc plugin::handle_notice
+	 */
+	void handle_notice(irccd& irccd, const notice_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_part
-     */
-    void handle_part(irccd& irccd, const part_event& event) override;
+	/**
+	 * \copydoc plugin::handle_part
+	 */
+	void handle_part(irccd& irccd, const part_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_reload
-     */
-    void handle_reload(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_reload
+	 */
+	void handle_reload(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_topic
-     */
-    void handle_topic(irccd& irccd, const topic_event& event) override;
+	/**
+	 * \copydoc plugin::handle_topic
+	 */
+	void handle_topic(irccd& irccd, const topic_event& event) override;
 
-    /**
-     * \copydoc plugin::handle_unload
-     */
-    void handle_unload(irccd& irccd) override;
+	/**
+	 * \copydoc plugin::handle_unload
+	 */
+	void handle_unload(irccd& irccd) override;
 
-    /**
-     * \copydoc plugin::handle_whois
-     */
-    void handle_whois(irccd& irccd, const whois_event& event) override;
+	/**
+	 * \copydoc plugin::handle_whois
+	 */
+	void handle_whois(irccd& irccd, const whois_event& event) override;
 };
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock_server.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock_server.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -22,39 +22,39 @@
 
 void mock_server::connect(connect_handler) noexcept
 {
-    state_ = state::connected;
-    push("connect");
+	state_ = state::connected;
+	push("connect");
 }
 
 void mock_server::disconnect() noexcept
 {
-    state_ = state::disconnected;
-    push("disconnect");
+	state_ = state::disconnected;
+	push("disconnect");
 }
 
 void mock_server::invite(std::string_view target, std::string_view channel)
 {
-    push("invite", { std::string(target), std::string(channel) });
+	push("invite", { std::string(target), std::string(channel) });
 }
 
 void mock_server::join(std::string_view channel, std::string_view password)
 {
-    push("join", { std::string(channel), std::string(password) });
+	push("join", { std::string(channel), std::string(password) });
 }
 
 void mock_server::kick(std::string_view target, std::string_view channel, std::string_view reason)
 {
-    push("kick", { std::string(target), std::string(channel), std::string(reason) });
+	push("kick", { std::string(target), std::string(channel), std::string(reason) });
 }
 
 void mock_server::me(std::string_view target, std::string_view message)
 {
-    push("me", { std::string(target), std::string(message) });
+	push("me", { std::string(target), std::string(message) });
 }
 
 void mock_server::message(std::string_view target, std::string_view message)
 {
-    push("message", { std::string(target), std::string(message) });
+	push("message", { std::string(target), std::string(message) });
 }
 
 void mock_server::mode(std::string_view channel,
@@ -63,43 +63,43 @@
                        std::string_view user,
                        std::string_view mask)
 {
-    push("mode", {
-        std::string(channel),
-        std::string(mode),
-        std::string(limit),
-        std::string(user),
-        std::string(mask)
-    });
+	push("mode", {
+		std::string(channel),
+		std::string(mode),
+		std::string(limit),
+		std::string(user),
+		std::string(mask)
+	});
 }
 
 void mock_server::names(std::string_view channel)
 {
-    push("names", { std::string(channel) });
+	push("names", { std::string(channel) });
 }
 
 void mock_server::notice(std::string_view target, std::string_view message)
 {
-    push("notice", { std::string(target), std::string(message) });
+	push("notice", { std::string(target), std::string(message) });
 }
 
 void mock_server::part(std::string_view channel, std::string_view reason)
 {
-    push("part", { std::string(channel), std::string(reason) });
+	push("part", { std::string(channel), std::string(reason) });
 }
 
 void mock_server::send(std::string_view raw)
 {
-    push("send", { std::string(raw) });
+	push("send", { std::string(raw) });
 }
 
 void mock_server::topic(std::string_view channel, std::string_view topic)
 {
-    push("topic", { std::string(channel), std::string(topic) });
+	push("topic", { std::string(channel), std::string(topic) });
 }
 
 void mock_server::whois(std::string_view target)
 {
-    push("whois", { std::string(target) });
+	push("whois", { std::string(target) });
 }
 
 } // !irccd
--- a/libirccd-test/irccd/test/mock_server.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd-test/irccd/test/mock_server.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,84 +35,84 @@
  */
 class mock_server : public server, public mock {
 public:
-    /**
-     * Inherited constructors.
-     */
-    using server::server;
+	/**
+	 * Inherited constructors.
+	 */
+	using server::server;
 
-    /**
-     * \copydoc server::connect
-     */
-    void connect(connect_handler handler) noexcept override;
+	/**
+	 * \copydoc server::connect
+	 */
+	void connect(connect_handler handler) noexcept override;
 
-    /**
-     * \copydoc server::disconnect
-     */
-    void disconnect() noexcept override;
+	/**
+	 * \copydoc server::disconnect
+	 */
+	void disconnect() noexcept override;
 
-    /**
-     * \copydoc server::invite
-     */
-    void invite(std::string_view target, std::string_view channel) override;
+	/**
+	 * \copydoc server::invite
+	 */
+	void invite(std::string_view target, std::string_view channel) override;
 
-    /**
-     * \copydoc server::join
-     */
-    void join(std::string_view channel, std::string_view password = "") override;
+	/**
+	 * \copydoc server::join
+	 */
+	void join(std::string_view channel, std::string_view password = "") override;
 
-    /**
-     * \copydoc server::kick
-     */
-    void kick(std::string_view target, std::string_view channel, std::string_view reason = "") override;
+	/**
+	 * \copydoc server::kick
+	 */
+	void kick(std::string_view target, std::string_view channel, std::string_view reason = "") override;
 
-    /**
-     * \copydoc server::me
-     */
-    void me(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::me
+	 */
+	void me(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::message
-     */
-    void message(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::message
+	 */
+	void message(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::mode
-     */
-    void mode(std::string_view channel,
-              std::string_view mode,
-              std::string_view limit = "",
-              std::string_view user = "",
-              std::string_view mask = "") override;
+	/**
+	 * \copydoc server::mode
+	 */
+	void mode(std::string_view channel,
+                  std::string_view mode,
+                  std::string_view limit = "",
+                  std::string_view user = "",
+                  std::string_view mask = "") override;
 
-    /**
-     * \copydoc server::names
-     */
-    void names(std::string_view channel) override;
+	/**
+	 * \copydoc server::names
+	 */
+	void names(std::string_view channel) override;
 
-    /**
-     * \copydoc server::notice
-     */
-    void notice(std::string_view target, std::string_view message) override;
+	/**
+	 * \copydoc server::notice
+	 */
+	void notice(std::string_view target, std::string_view message) override;
 
-    /**
-     * \copydoc server::part
-     */
-    void part(std::string_view channel, std::string_view reason = "") override;
+	/**
+	 * \copydoc server::part
+	 */
+	void part(std::string_view channel, std::string_view reason = "") override;
 
-    /**
-     * \copydoc server::send
-     */
-    void send(std::string_view raw) override;
+	/**
+	 * \copydoc server::send
+	 */
+	void send(std::string_view raw) override;
 
-    /**
-     * \copydoc server::topic
-     */
-    void topic(std::string_view channel, std::string_view topic) override;
+	/**
+	 * \copydoc server::topic
+	 */
+	void topic(std::string_view channel, std::string_view topic) override;
 
-    /**
-     * \copydoc server::whois
-     */
-    void whois(std::string_view target) override;
+	/**
+	 * \copydoc server::whois
+	 */
+	void whois(std::string_view target) override;
 };
 
 } // !irccd
--- a/libirccd/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,57 +19,57 @@
 project(libirccd)
 
 set(
-    HEADERS
-    ${libirccd_SOURCE_DIR}/irccd/daemon/command.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/dynlib_plugin.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/irc.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/irccd.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/logger.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/plugin.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/plugin_service.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_service.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server_service.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server_util.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_client.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_server.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_service.hpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_util.hpp
+	HEADERS
+	${libirccd_SOURCE_DIR}/irccd/daemon/command.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/dynlib_plugin.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/irc.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/irccd.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/logger.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/plugin.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/plugin_service.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule_service.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server_service.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server_util.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_client.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_server.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_service.hpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_util.hpp
 )
 
 set(
-    SOURCES
-    ${libirccd_SOURCE_DIR}/irccd/daemon/command.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/dynlib_plugin.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/irc.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/irccd.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/logger.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/plugin.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/plugin_service.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_service.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server_service.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/server_util.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_client.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_server.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_service.cpp
-    ${libirccd_SOURCE_DIR}/irccd/daemon/transport_util.cpp
+	SOURCES
+	${libirccd_SOURCE_DIR}/irccd/daemon/command.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/dynlib_plugin.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/irc.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/irccd.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/logger.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/plugin.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/plugin_service.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule_service.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/rule_util.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server_service.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/server_util.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_client.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_server.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_service.cpp
+	${libirccd_SOURCE_DIR}/irccd/daemon/transport_util.cpp
 )
 
 irccd_define_library(
-    TARGET libirccd
-    EXPORT
-    HEADERS ${HEADERS}
-    HEADERS_DIRECTORY irccd/daemon
-    SOURCES
-        ${libirccd_SOURCE_DIR}/CMakeLists.txt
-        ${SOURCES}
-    LIBRARIES
-        libirccd-core
-    PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libirccd_SOURCE_DIR}>
+	TARGET libirccd
+	EXPORT
+	HEADERS ${HEADERS}
+	HEADERS_DIRECTORY irccd/daemon
+	SOURCES
+		${libirccd_SOURCE_DIR}/CMakeLists.txt
+		${SOURCES}
+	LIBRARIES
+		libirccd-core
+	PUBLIC_INCLUDES
+		$<BUILD_INTERFACE:${libirccd_SOURCE_DIR}>
 )
--- a/libirccd/irccd/daemon/command.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/command.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,107 +38,107 @@
 
 void exec_set(transport_client& client, plugin& plugin, const nlohmann::json& args)
 {
-    assert(args.count("value") > 0);
+	assert(args.count("value") > 0);
 
-    const auto var = args.find("variable");
-    const auto value = args.find("value");
+	const auto var = args.find("variable");
+	const auto value = args.find("value");
 
-    if (var == args.end() || !var->is_string())
-        throw irccd_error(irccd_error::error::incomplete_message);
-    if (value == args.end() || !value->is_string())
-        throw irccd_error(irccd_error::error::incomplete_message);
+	if (var == args.end() || !var->is_string())
+		throw irccd_error(irccd_error::error::incomplete_message);
+	if (value == args.end() || !value->is_string())
+		throw irccd_error(irccd_error::error::incomplete_message);
 
-    auto config = plugin.get_options();
+	auto config = plugin.get_options();
 
-    config[*var] = *value;
-    plugin.set_options(config);
-    client.success("plugin-config");
+	config[*var] = *value;
+	plugin.set_options(config);
+	client.success("plugin-config");
 }
 
 void exec_get(transport_client& client, plugin& plugin, const nlohmann::json& args)
 {
-    auto variables = nlohmann::json::object();
-    auto var = args.find("variable");
+	auto variables = nlohmann::json::object();
+	auto var = args.find("variable");
 
-    if (var != args.end() && var->is_string())
-        variables[var->get<std::string>()] = plugin.get_options()[*var];
-    else
-        for (const auto& pair : plugin.get_options())
-            variables[pair.first] = pair.second;
+	if (var != args.end() && var->is_string())
+		variables[var->get<std::string>()] = plugin.get_options()[*var];
+	else
+		for (const auto& pair : plugin.get_options())
+			variables[pair.first] = pair.second;
 
-    /*
-     * Don't put all variables into the response, put them into a sub property
-     * 'variables' instead.
-     *
-     * It's easier for the client to iterate over all.
-     */
-    client.write({
-        { "command",    "plugin-config" },
-        { "variables",  variables       }
-    });
+	/*
+	 * Don't put all variables into the response, put them into a sub property
+	 * 'variables' instead.
+	 *
+	 * It's easier for the client to iterate over all.
+	 */
+	client.write({
+		{ "command",    "plugin-config" },
+		{ "variables",  variables       }
+	});
 }
 
 template <typename T>
 auto bind() noexcept -> command::constructor
 {
-    return [] () noexcept {
-        return std::make_unique<T>();
-    };
+	return [] () noexcept {
+		return std::make_unique<T>();
+	};
 }
 
 } // !namespace
 
 const std::vector<command::constructor> command::registry{
-    bind<plugin_config_command>(),
-    bind<plugin_info_command>(),
-    bind<plugin_list_command>(),
-    bind<plugin_load_command>(),
-    bind<plugin_reload_command>(),
-    bind<plugin_unload_command>(),
-    bind<rule_add_command>(),
-    bind<rule_edit_command>(),
-    bind<rule_info_command>(),
-    bind<rule_info_command>(),
-    bind<rule_list_command>(),
-    bind<rule_move_command>(),
-    bind<rule_remove_command>(),
-    bind<server_connect_command>(),
-    bind<server_disconnect_command>(),
-    bind<server_info_command>(),
-    bind<server_invite_command>(),
-    bind<server_join_command>(),
-    bind<server_kick_command>(),
-    bind<server_list_command>(),
-    bind<server_me_command>(),
-    bind<server_message_command>(),
-    bind<server_mode_command>(),
-    bind<server_nick_command>(),
-    bind<server_notice_command>(),
-    bind<server_part_command>(),
-    bind<server_reconnect_command>(),
-    bind<server_topic_command>(),
+	bind<plugin_config_command>(),
+	bind<plugin_info_command>(),
+	bind<plugin_list_command>(),
+	bind<plugin_load_command>(),
+	bind<plugin_reload_command>(),
+	bind<plugin_unload_command>(),
+	bind<rule_add_command>(),
+	bind<rule_edit_command>(),
+	bind<rule_info_command>(),
+	bind<rule_info_command>(),
+	bind<rule_list_command>(),
+	bind<rule_move_command>(),
+	bind<rule_remove_command>(),
+	bind<server_connect_command>(),
+	bind<server_disconnect_command>(),
+	bind<server_info_command>(),
+	bind<server_invite_command>(),
+	bind<server_join_command>(),
+	bind<server_kick_command>(),
+	bind<server_list_command>(),
+	bind<server_me_command>(),
+	bind<server_message_command>(),
+	bind<server_mode_command>(),
+	bind<server_nick_command>(),
+	bind<server_notice_command>(),
+	bind<server_part_command>(),
+	bind<server_reconnect_command>(),
+	bind<server_topic_command>(),
 };
 
 // {{{ plugin_config_command
 
 auto plugin_config_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-config";
+	return "plugin-config";
 }
 
 void plugin_config_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("plugin");
+	const auto id = args.get<std::string>("plugin");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw plugin_error(plugin_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw plugin_error(plugin_error::invalid_identifier);
 
-    const auto plugin = irccd.plugins().require(*id);
+	const auto plugin = irccd.plugins().require(*id);
 
-    if (args.count("value") > 0)
-        exec_set(client, *plugin, args);
-    else
-        exec_get(client, *plugin, args);
+	if (args.count("value") > 0)
+		exec_set(client, *plugin, args);
+	else
+		exec_get(client, *plugin, args);
 }
 
 // }}}
@@ -147,25 +147,25 @@
 
 auto plugin_info_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-info";
+	return "plugin-info";
 }
 
 void plugin_info_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("plugin");
+	const auto id = args.get<std::string>("plugin");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw plugin_error(plugin_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw plugin_error(plugin_error::invalid_identifier);
 
-    const auto plugin = irccd.plugins().require(*id);
+	const auto plugin = irccd.plugins().require(*id);
 
-    client.write({
-        { "command",    "plugin-info"                       },
-        { "author",     std::string(plugin->get_author())   },
-        { "license",    std::string(plugin->get_license())  },
-        { "summary",    std::string(plugin->get_summary())  },
-        { "version",    std::string(plugin->get_version())  }
-    });
+	client.write({
+		{ "command",    "plugin-info"                           },
+		{ "author",     std::string(plugin->get_author())       },
+		{ "license",    std::string(plugin->get_license())      },
+		{ "summary",    std::string(plugin->get_summary())      },
+		{ "version",    std::string(plugin->get_version())      }
+	});
 }
 
 // }}}
@@ -174,20 +174,20 @@
 
 auto plugin_list_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-list";
+	return "plugin-list";
 }
 
 void plugin_list_command::exec(irccd& irccd, transport_client& client, const document&)
 {
-    auto list = nlohmann::json::array();
+	auto list = nlohmann::json::array();
 
-    for (const auto& plg : irccd.plugins().all())
-        list += plg->get_id();
+	for (const auto& plg : irccd.plugins().all())
+		list += plg->get_id();
 
-    client.write({
-        { "command",    "plugin-list"   },
-        { "list",       list            }
-    });
+	client.write({
+		{ "command",	"plugin-list"   },
+		{ "list",	   list			}
+	});
 }
 
 // }}}
@@ -196,18 +196,18 @@
 
 auto plugin_load_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-load";
+	return "plugin-load";
 }
 
 void plugin_load_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("plugin");
+	const auto id = args.get<std::string>("plugin");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw plugin_error(plugin_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw plugin_error(plugin_error::invalid_identifier);
 
-    irccd.plugins().load(*id, "");
-    client.success("plugin-load");
+	irccd.plugins().load(*id, "");
+	client.success("plugin-load");
 }
 
 // }}}
@@ -216,18 +216,18 @@
 
 auto plugin_reload_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-reload";
+	return "plugin-reload";
 }
 
 void plugin_reload_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("plugin");
+	const auto id = args.get<std::string>("plugin");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw plugin_error(plugin_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw plugin_error(plugin_error::invalid_identifier);
 
-    irccd.plugins().reload(*id);
-    client.success("plugin-reload");
+	irccd.plugins().reload(*id);
+	client.success("plugin-reload");
 }
 
 // }}}
@@ -236,18 +236,18 @@
 
 auto plugin_unload_command::get_name() const noexcept -> std::string_view
 {
-    return "plugin-unload";
+	return "plugin-unload";
 }
 
 void plugin_unload_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("plugin");
+	const auto id = args.get<std::string>("plugin");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw plugin_error(plugin_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw plugin_error(plugin_error::invalid_identifier);
 
-    irccd.plugins().unload(*id);
-    client.success("plugin-unload");
+	irccd.plugins().unload(*id);
+	client.success("plugin-unload");
 }
 
 // }}}
@@ -256,18 +256,18 @@
 
 auto rule_add_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-add";
+	return "rule-add";
 }
 
 void rule_add_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto index = args.optional<unsigned>("index", irccd.rules().length());
+	const auto index = args.optional<unsigned>("index", irccd.rules().list().size());
 
-    if (!index || *index > irccd.rules().length())
-        throw rule_error(rule_error::error::invalid_index);
+	if (!index || *index > irccd.rules().list().size())
+		throw rule_error(rule_error::error::invalid_index);
 
-    irccd.rules().insert(rule_util::from_json(args), *index);
-    client.success("rule-add");
+	irccd.rules().insert(rule_util::from_json(args), *index);
+	client.success("rule-add");
 }
 
 // }}}
@@ -276,52 +276,52 @@
 
 auto rule_edit_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-edit";
+	return "rule-edit";
 }
 
 void rule_edit_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    static const auto updateset = [] (auto& set, auto args, const auto& key) {
-        for (const auto& v : args["remove-"s + key]) {
-            if (v.is_string())
-                set.erase(v.template get<std::string>());
-        }
-        for (const auto& v : args["add-"s + key]) {
-            if (v.is_string())
-                set.insert(v.template get<std::string>());
-        }
-    };
+	static const auto updateset = [] (auto& set, auto args, const auto& key) {
+		for (const auto& v : args["remove-"s + key]) {
+			if (v.is_string())
+				set.erase(v.template get<std::string>());
+		}
+		for (const auto& v : args["add-"s + key]) {
+			if (v.is_string())
+				set.insert(v.template get<std::string>());
+		}
+	};
 
-    const auto index = args.get<unsigned>("index");
+	const auto index = args.get<unsigned>("index");
 
-    if (!index)
-        throw rule_error(rule_error::invalid_index);
+	if (!index)
+		throw rule_error(rule_error::invalid_index);
 
-    // Create a copy to avoid incomplete edition in case of errors.
-    auto rule = irccd.rules().require(*index);
+	// Create a copy to avoid incomplete edition in case of errors.
+	auto rule = irccd.rules().require(*index);
 
-    updateset(rule.get_channels(), args, "channels");
-    updateset(rule.get_events(), args, "events");
-    updateset(rule.get_plugins(), args, "plugins");
-    updateset(rule.get_servers(), args, "servers");
+	updateset(rule.channels, args, "channels");
+	updateset(rule.events, args, "events");
+	updateset(rule.plugins, args, "plugins");
+	updateset(rule.servers, args, "servers");
 
-    auto action = args.find("action");
+	auto action = args.find("action");
 
-    if (action != args.end()) {
-        if (!action->is_string())
-            throw rule_error(rule_error::error::invalid_action);
+	if (action != args.end()) {
+		if (!action->is_string())
+			throw rule_error(rule_error::error::invalid_action);
 
-        if (action->get<std::string>() == "accept")
-            rule.set_action(rule::action::accept);
-        else if (action->get<std::string>() == "drop")
-            rule.set_action(rule::action::drop);
-        else
-            throw rule_error(rule_error::invalid_action);
-    }
+		if (action->get<std::string>() == "accept")
+			rule.action = rule::action_type::accept;
+		else if (action->get<std::string>() == "drop")
+			rule.action = rule::action_type::drop;
+		else
+			throw rule_error(rule_error::invalid_action);
+	}
 
-    // All done, sync the rule.
-    irccd.rules().require(*index) = rule;
-    client.success("rule-edit");
+	// All done, sync the rule.
+	irccd.rules().require(*index) = rule;
+	client.success("rule-edit");
 }
 
 // }}}
@@ -330,20 +330,20 @@
 
 auto rule_info_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-info";
+	return "rule-info";
 }
 
 void rule_info_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto index = args.get<unsigned>("index");
+	const auto index = args.get<unsigned>("index");
 
-    if (!index)
-        throw rule_error(rule_error::invalid_index);
+	if (!index)
+		throw rule_error(rule_error::invalid_index);
 
-    auto json = rule_util::to_json(irccd.rules().require(*index));
+	auto json = rule_util::to_json(irccd.rules().require(*index));
 
-    json.push_back({"command", "rule-info"});
-    client.write(std::move(json));
+	json.push_back({"command", "rule-info"});
+	client.write(std::move(json));
 }
 
 // }}}
@@ -352,20 +352,20 @@
 
 auto rule_list_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-list";
+	return "rule-list";
 }
 
 void rule_list_command::exec(irccd& irccd, transport_client& client, const document&)
 {
-    auto array = nlohmann::json::array();
+	auto array = nlohmann::json::array();
 
-    for (const auto& rule : irccd.rules().list())
-        array.push_back(rule_util::to_json(rule));
+	for (const auto& rule : irccd.rules().list())
+		array.push_back(rule_util::to_json(rule));
 
-    client.write({
-        { "command",    "rule-list"         },
-        { "list",       std::move(array)    }
-    });
+	client.write({
+		{ "command",    "rule-list"             },
+		{ "list",       std::move(array)        }
+	});
 }
 
 // }}}
@@ -374,61 +374,61 @@
 
 auto rule_move_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-move";
+	return "rule-move";
 }
 
 void rule_move_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto from = args.get<unsigned>("from");
-    const auto to = args.get<unsigned>("to");
+	const auto from = args.get<unsigned>("from");
+	const auto to = args.get<unsigned>("to");
 
-    if (!from || !to)
-        throw rule_error(rule_error::invalid_index);
+	if (!from || !to)
+		throw rule_error(rule_error::invalid_index);
 
-    /*
-     * Examples of moves
-     * --------------------------------------------------------------
-     *
-     * Before: [0] [1] [2]
-     *
-     * from = 0
-     * to   = 2
-     *
-     * After:  [1] [2] [0]
-     *
-     * --------------------------------------------------------------
-     *
-     * Before: [0] [1] [2]
-     *
-     * from = 2
-     * to   = 0
-     *
-     * After:  [2] [0] [1]
-     *
-     * --------------------------------------------------------------
-     *
-     * Before: [0] [1] [2]
-     *
-     * from = 0
-     * to   = 123
-     *
-     * After:  [1] [2] [0]
-     */
+	/*
+	 * Examples of moves
+	 * --------------------------------------------------------------
+	 *
+	 * Before: [0] [1] [2]
+	 *
+	 * from = 0
+	 * to   = 2
+	 *
+	 * After:  [1] [2] [0]
+	 *
+	 * --------------------------------------------------------------
+	 *
+	 * Before: [0] [1] [2]
+	 *
+	 * from = 2
+	 * to   = 0
+	 *
+	 * After:  [2] [0] [1]
+	 *
+	 * --------------------------------------------------------------
+	 *
+	 * Before: [0] [1] [2]
+	 *
+	 * from = 0
+	 * to   = 123
+	 *
+	 * After:  [1] [2] [0]
+	 */
 
-    // Ignore dumb input.
-    if (*from == *to) {
-        client.success("rule-move");
-        return;
-    }
+	// Ignore dumb input.
+	if (*from == *to) {
+		client.success("rule-move");
+		return;
+	}
 
-    if (*from >= irccd.rules().length())
-        throw rule_error(rule_error::error::invalid_index);
+	if (*from >= irccd.rules().list().size())
+		throw rule_error(rule_error::error::invalid_index);
 
-    const auto save = irccd.rules().list()[*from];
+	const auto save = irccd.rules().list()[*from];
 
-    irccd.rules().remove(*from);
-    irccd.rules().insert(save, *to > irccd.rules().length() ? irccd.rules().length() : *to);
-    client.success("rule-move");
+	irccd.rules().remove(*from);
+	irccd.rules().insert(save, *to > irccd.rules().list().size() ? irccd.rules().list().size() : *to);
+	client.success("rule-move");
 }
 
 // }}}
@@ -437,18 +437,18 @@
 
 auto rule_remove_command::get_name() const noexcept -> std::string_view
 {
-    return "rule-remove";
+	return "rule-remove";
 }
 
 void rule_remove_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto index = args.get<unsigned>("index");
+	const auto index = args.get<unsigned>("index");
 
-    if (!index || *index >= irccd.rules().length())
-        throw rule_error(rule_error::invalid_index);
+	if (!index || *index >= irccd.rules().list().size())
+		throw rule_error(rule_error::invalid_index);
 
-    irccd.rules().remove(*index);
-    client.success("rule-remove");
+	irccd.rules().remove(*index);
+	client.success("rule-remove");
 }
 
 // }}}
@@ -457,18 +457,18 @@
 
 auto server_connect_command::get_name() const noexcept -> std::string_view
 {
-    return "server-connect";
+	return "server-connect";
 }
 
 void server_connect_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    auto server = server_util::from_json(irccd.get_service(), args);
+	auto server = server_util::from_json(irccd.get_service(), args);
 
-    if (irccd.servers().has(server->get_id()))
-        throw server_error(server_error::already_exists);
+	if (irccd.servers().has(server->get_id()))
+		throw server_error(server_error::already_exists);
 
-    irccd.servers().add(std::move(server));
-    client.success("server-connect");
+	irccd.servers().add(std::move(server));
+	client.success("server-connect");
 }
 
 // }}}
@@ -477,26 +477,26 @@
 
 auto server_disconnect_command::get_name() const noexcept -> std::string_view
 {
-    return "server-disconnect";
+	return "server-disconnect";
 }
 
 void server_disconnect_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto it = args.find("server");
+	const auto it = args.find("server");
 
-    if (it == args.end())
-        irccd.servers().clear();
-    else {
-        if (!it->is_string() || !string_util::is_identifier(it->get<std::string>()))
-            throw server_error(server_error::invalid_identifier);
+	if (it == args.end())
+		irccd.servers().clear();
+	else {
+		if (!it->is_string() || !string_util::is_identifier(it->get<std::string>()))
+			throw server_error(server_error::invalid_identifier);
 
-        const auto name = it->get<std::string>();
+		const auto name = it->get<std::string>();
 
-        irccd.servers().require(name);
-        irccd.servers().remove(name);
-    }
+		irccd.servers().require(name);
+		irccd.servers().remove(name);
+	}
 
-    client.success("server-disconnect");
+	client.success("server-disconnect");
 }
 
 // }}}
@@ -505,40 +505,40 @@
 
 auto server_info_command::get_name() const noexcept -> std::string_view
 {
-    return "server-info";
+	return "server-info";
 }
 
 void server_info_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
+	const auto id = args.get<std::string>("server");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
 
-    const auto server = irccd.servers().require(*id);
+	const auto server = irccd.servers().require(*id);
 
-    // Construct the JSON response.
-    auto response = document::object();
+	// Construct the JSON response.
+	auto response = document::object();
 
-    // General stuff.
-    response.push_back({"command", "server-info"});
-    response.push_back({"name", server->get_id()});
-    response.push_back({"host", server->get_host()});
-    response.push_back({"port", server->get_port()});
-    response.push_back({"nickname", server->get_nickname()});
-    response.push_back({"username", server->get_username()});
-    response.push_back({"realname", server->get_realname()});
-    response.push_back({"channels", server->get_channels()});
+	// General stuff.
+	response.push_back({"command", "server-info"});
+	response.push_back({"name", server->get_id()});
+	response.push_back({"host", server->get_host()});
+	response.push_back({"port", server->get_port()});
+	response.push_back({"nickname", server->get_nickname()});
+	response.push_back({"username", server->get_username()});
+	response.push_back({"realname", server->get_realname()});
+	response.push_back({"channels", server->get_channels()});
 
-    // Optional stuff.
-    if ((server->get_options() & server::options::ipv6) == server::options::ipv6)
-        response.push_back({"ipv6", true});
-    if ((server->get_options() & server::options::ssl) == server::options::ssl)
-        response.push_back({"ssl", true});
-    if ((server->get_options() & server::options::ssl_verify) == server::options::ssl_verify)
-        response.push_back({"sslVerify", true});
+	// Optional stuff.
+	if ((server->get_options() & server::options::ipv6) == server::options::ipv6)
+		response.push_back({"ipv6", true});
+	if ((server->get_options() & server::options::ssl) == server::options::ssl)
+		response.push_back({"ssl", true});
+	if ((server->get_options() & server::options::ssl_verify) == server::options::ssl_verify)
+		response.push_back({"sslVerify", true});
 
-    client.write(response);
+	client.write(response);
 }
 
 // }}}
@@ -547,24 +547,24 @@
 
 auto server_invite_command::get_name() const noexcept -> std::string_view
 {
-    return "server-invite";
+	return "server-invite";
 }
 
 void server_invite_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto target = args.get<std::string>("target");
-    const auto channel = args.get<std::string>("channel");
+	const auto id = args.get<std::string>("server");
+	const auto target = args.get<std::string>("target");
+	const auto channel = args.get<std::string>("channel");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!target || target->empty())
-        throw server_error(server_error::invalid_nickname);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!target || target->empty())
+		throw server_error(server_error::invalid_nickname);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
 
-    irccd.servers().require(*id)->invite(*target, *channel);
-    client.success("server-invite");
+	irccd.servers().require(*id)->invite(*target, *channel);
+	client.success("server-invite");
 }
 
 // }}}
@@ -573,24 +573,24 @@
 
 auto server_join_command::get_name() const noexcept -> std::string_view
 {
-    return "server-join";
+	return "server-join";
 }
 
 void server_join_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("channel");
-    const auto password = args.optional<std::string>("password", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("channel");
+	const auto password = args.optional<std::string>("password", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!password)
-        throw server_error(server_error::invalid_password);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!password)
+		throw server_error(server_error::invalid_password);
 
-    irccd.servers().require(*id)->join(*channel, *password);
-    client.success("server-join");
+	irccd.servers().require(*id)->join(*channel, *password);
+	client.success("server-join");
 }
 
 // }}}
@@ -599,27 +599,27 @@
 
 auto server_kick_command::get_name() const noexcept -> std::string_view
 {
-    return "server-kick";
+	return "server-kick";
 }
 
 void server_kick_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto target = args.get<std::string>("target");
-    const auto channel = args.get<std::string>("channel");
-    const auto reason = args.optional<std::string>("reason", "");
+	const auto id = args.get<std::string>("server");
+	const auto target = args.get<std::string>("target");
+	const auto channel = args.get<std::string>("channel");
+	const auto reason = args.optional<std::string>("reason", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!target || target->empty())
-        throw server_error(server_error::invalid_nickname);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!reason)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!target || target->empty())
+		throw server_error(server_error::invalid_nickname);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!reason)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->kick(*target, *channel, *reason);
-    client.success("server-kick");
+	irccd.servers().require(*id)->kick(*target, *channel, *reason);
+	client.success("server-kick");
 }
 
 // }}}
@@ -628,21 +628,21 @@
 
 auto server_list_command::get_name() const noexcept -> std::string_view
 {
-    return "server-list";
+	return "server-list";
 }
 
 void server_list_command::exec(irccd& irccd, transport_client& client, const document&)
 {
-    auto json = nlohmann::json::object();
-    auto list = nlohmann::json::array();
+	auto json = nlohmann::json::object();
+	auto list = nlohmann::json::array();
 
-    for (const auto& server : irccd.servers().all())
-        list.push_back(server->get_id());
+	for (const auto& server : irccd.servers().all())
+		list.push_back(server->get_id());
 
-    client.write({
-        { "command",    "server-list"   },
-        { "list",       std::move(list) }
-    });
+	client.write({
+		{ "command",    "server-list"   },
+		{ "list",       std::move(list) }
+	});
 }
 
 // }}}
@@ -651,24 +651,24 @@
 
 auto server_me_command::get_name() const noexcept -> std::string_view
 {
-    return "server-me";
+	return "server-me";
 }
 
 void server_me_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("target");
-    const auto message = args.optional<std::string>("message", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("target");
+	const auto message = args.optional<std::string>("message", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!message)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!message)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->me(*channel, *message);
-    client.success("server-me");
+	irccd.servers().require(*id)->me(*channel, *message);
+	client.success("server-me");
 }
 
 // }}}
@@ -677,24 +677,24 @@
 
 auto server_message_command::get_name() const noexcept -> std::string_view
 {
-    return "server-message";
+	return "server-message";
 }
 
 void server_message_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("target");
-    const auto message = args.optional<std::string>("message", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("target");
+	const auto message = args.optional<std::string>("message", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!message)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!message)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->message(*channel, *message);
-    client.success("server-message");
+	irccd.servers().require(*id)->message(*channel, *message);
+	client.success("server-message");
 }
 
 // }}}
@@ -703,29 +703,29 @@
 
 auto server_mode_command::get_name() const noexcept -> std::string_view
 {
-    return "server-mode";
+	return "server-mode";
 }
 
 void server_mode_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("channel");
-    const auto mode = args.get<std::string>("mode");
-    const auto limit = args.optional<std::string>("limit", "");
-    const auto user = args.optional<std::string>("user", "");
-    const auto mask = args.optional<std::string>("mask", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("channel");
+	const auto mode = args.get<std::string>("mode");
+	const auto limit = args.optional<std::string>("limit", "");
+	const auto user = args.optional<std::string>("user", "");
+	const auto mask = args.optional<std::string>("mask", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!mode || mode->empty())
-        throw server_error(server_error::invalid_mode);
-    if (!limit || !user || !mask)
-        throw server_error(server_error::invalid_mode);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!mode || mode->empty())
+		throw server_error(server_error::invalid_mode);
+	if (!limit || !user || !mask)
+		throw server_error(server_error::invalid_mode);
 
-    irccd.servers().require(*id)->mode(*channel, *mode, *limit, *user, *mask);
-    client.success("server-mode");
+	irccd.servers().require(*id)->mode(*channel, *mode, *limit, *user, *mask);
+	client.success("server-mode");
 }
 
 // }}}
@@ -734,21 +734,21 @@
 
 auto server_nick_command::get_name() const noexcept -> std::string_view
 {
-    return "server-nick";
+	return "server-nick";
 }
 
 void server_nick_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto nick = args.get<std::string>("nickname");
+	const auto id = args.get<std::string>("server");
+	const auto nick = args.get<std::string>("nickname");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!nick || nick->empty())
-        throw server_error(server_error::invalid_nickname);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!nick || nick->empty())
+		throw server_error(server_error::invalid_nickname);
 
-    irccd.servers().require(*id)->set_nickname(*nick);
-    client.success("server-nick");
+	irccd.servers().require(*id)->set_nickname(*nick);
+	client.success("server-nick");
 }
 
 // }}}
@@ -757,24 +757,24 @@
 
 auto server_notice_command::get_name() const noexcept -> std::string_view
 {
-    return "server-notice";
+	return "server-notice";
 }
 
 void server_notice_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("target");
-    const auto message = args.optional<std::string>("message", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("target");
+	const auto message = args.optional<std::string>("message", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!message)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!message)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->notice(*channel, *message);
-    client.success("server-notice");
+	irccd.servers().require(*id)->notice(*channel, *message);
+	client.success("server-notice");
 }
 
 // }}}
@@ -783,24 +783,24 @@
 
 auto server_part_command::get_name() const noexcept -> std::string_view
 {
-    return "server-part";
+	return "server-part";
 }
 
 void server_part_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("channel");
-    const auto reason = args.optional<std::string>("reason", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("channel");
+	const auto reason = args.optional<std::string>("reason", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!reason)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!reason)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->part(*channel, *reason);
-    client.success("server-part");
+	irccd.servers().require(*id)->part(*channel, *reason);
+	client.success("server-part");
 }
 
 // }}}
@@ -809,23 +809,23 @@
 
 auto server_reconnect_command::get_name() const noexcept -> std::string_view
 {
-    return "server-reconnect";
+	return "server-reconnect";
 }
 
 void server_reconnect_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto it = args.find("server");
+	const auto it = args.find("server");
 
-    if (it == args.end())
-        irccd.servers().reconnect();
-    else {
-        if (!it->is_string() || !string_util::is_identifier(it->get<std::string>()))
-            throw server_error(server_error::invalid_identifier);
+	if (it == args.end())
+		irccd.servers().reconnect();
+	else {
+		if (!it->is_string() || !string_util::is_identifier(it->get<std::string>()))
+			throw server_error(server_error::invalid_identifier);
 
-        irccd.servers().reconnect(it->get<std::string>());
-    }
+		irccd.servers().reconnect(it->get<std::string>());
+	}
 
-    client.success("server-reconnect");
+	client.success("server-reconnect");
 }
 
 // }}}
@@ -834,24 +834,24 @@
 
 auto server_topic_command::get_name() const noexcept -> std::string_view
 {
-    return "server-topic";
+	return "server-topic";
 }
 
 void server_topic_command::exec(irccd& irccd, transport_client& client, const document& args)
 {
-    const auto id = args.get<std::string>("server");
-    const auto channel = args.get<std::string>("channel");
-    const auto topic = args.optional<std::string>("topic", "");
+	const auto id = args.get<std::string>("server");
+	const auto channel = args.get<std::string>("channel");
+	const auto topic = args.optional<std::string>("topic", "");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!channel || channel->empty())
-        throw server_error(server_error::invalid_channel);
-    if (!topic)
-        throw server_error(server_error::invalid_message);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!channel || channel->empty())
+		throw server_error(server_error::invalid_channel);
+	if (!topic)
+		throw server_error(server_error::invalid_message);
 
-    irccd.servers().require(*id)->topic(*channel, *topic);
-    client.success("server-topic");
+	irccd.servers().require(*id)->topic(*channel, *topic);
+	client.success("server-topic");
 }
 
 // }}}
--- a/libirccd/irccd/daemon/command.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/command.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -45,47 +45,47 @@
  */
 class command {
 public:
-    /**
-     * \brief Convenient alias.
-     */
-    using document = json_util::document;
+	/**
+	 * \brief Convenient alias.
+	 */
+	using document = json_util::deserializer;
 
-    /**
-     * \brief Command constructor factory.
-     */
-    using constructor = std::function<auto () -> std::unique_ptr<command>>;
+	/**
+	 * \brief Command constructor factory.
+	 */
+	using constructor = std::function<auto () -> std::unique_ptr<command>>;
 
-    /**
-     * \brief Registry of all commands.
-     */
-    static const std::vector<constructor> registry;
+	/**
+	 * \brief Registry of all commands.
+	 */
+	static const std::vector<constructor> registry;
 
-    /**
-     * Default destructor virtual.
-     */
-    virtual ~command() = default;
+	/**
+	 * Default destructor virtual.
+	 */
+	virtual ~command() = default;
 
-    /**
-     * Return the command name, must not have spaces.
-     *
-     * \return the command name
-     */
-    virtual auto get_name() const noexcept -> std::string_view = 0;
+	/**
+	 * Return the command name, must not have spaces.
+	 *
+	 * \return the command name
+	 */
+	virtual auto get_name() const noexcept -> std::string_view = 0;
 
-    /**
-     * Execute the command.
-     *
-     * If the command throw an exception, the error is sent to the client so be
-     * careful about sensitive information.
-     *
-     * The implementation should use client.success() or client.error() to send
-     * some data.
-     *
-     * \param irccd the irccd instance
-     * \param client the client
-     * \param args the client arguments
-     */
-    virtual void exec(irccd& irccd, transport_client& client, const document& args) = 0;
+	/**
+	 * Execute the command.
+	 *
+	 * If the command throw an exception, the error is sent to the client so be
+	 * careful about sensitive information.
+	 *
+	 * The implementation should use client.success() or client.error() to send
+	 * some data.
+	 *
+	 * \param irccd the irccd instance
+	 * \param client the client
+	 * \param args the client arguments
+	 */
+	virtual void exec(irccd& irccd, transport_client& client, const document& args) = 0;
 };
 
 // }}}
@@ -101,15 +101,15 @@
  */
 class plugin_config_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -125,15 +125,15 @@
  */
 class plugin_info_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -145,15 +145,15 @@
  */
 class plugin_list_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -171,15 +171,15 @@
  */
 class plugin_load_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -196,15 +196,15 @@
  */
 class plugin_reload_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -221,15 +221,15 @@
  */
 class plugin_unload_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -245,15 +245,15 @@
  */
 class rule_add_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -270,15 +270,15 @@
  */
 class rule_edit_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -294,15 +294,15 @@
  */
 class rule_info_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -314,15 +314,15 @@
  */
 class rule_list_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -338,15 +338,15 @@
  */
 class rule_move_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -362,15 +362,15 @@
  */
 class rule_remove_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -390,15 +390,15 @@
  */
 class server_connect_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -415,15 +415,15 @@
  */
 class server_disconnect_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -440,15 +440,15 @@
  */
 class server_info_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -467,15 +467,15 @@
  */
 class server_invite_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -493,15 +493,15 @@
  */
 class server_join_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -520,15 +520,15 @@
  */
 class server_kick_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -540,15 +540,15 @@
  */
 class server_list_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -566,15 +566,15 @@
  */
 class server_me_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -592,15 +592,15 @@
  */
 class server_message_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -619,15 +619,15 @@
  */
 class server_mode_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -645,15 +645,15 @@
  */
 class server_nick_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -671,15 +671,15 @@
  */
 class server_notice_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -697,15 +697,15 @@
  */
 class server_part_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -722,15 +722,15 @@
  */
 class server_reconnect_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
@@ -748,15 +748,15 @@
  */
 class server_topic_command : public command {
 public:
-    /**
-     * \copydoc command::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc command::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc command::exec
-     */
-    void exec(irccd& irccd, transport_client& client, const document& args) override;
+	/**
+	 * \copydoc command::exec
+	 */
+	void exec(irccd& irccd, transport_client& client, const document& args) override;
 };
 
 // }}}
--- a/libirccd/irccd/daemon/dynlib_plugin.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -42,62 +42,62 @@
 
 auto symbol(std::string_view path) -> std::pair<std::string, std::string>
 {
-    auto id = boost::filesystem::path(std::string(path)).stem().string();
+	auto id = boost::filesystem::path(std::string(path)).stem().string();
 
-    // Remove forbidden characters.
-    id.erase(std::remove_if(id.begin(), id.end(), [] (auto c) {
-        return !isalnum(c) && c != '-' && c != '_';
-    }), id.end());
+	// Remove forbidden characters.
+	id.erase(std::remove_if(id.begin(), id.end(), [] (auto c) {
+		return !isalnum(c) && c != '-' && c != '_';
+	}), id.end());
 
-    // Transform - to _.
-    std::transform(id.begin(), id.end(), id.begin(), [] (auto c) noexcept {
-        return c == '-' ? '_' : c;
-    });
+	// Transform - to _.
+	std::transform(id.begin(), id.end(), id.begin(), [] (auto c) noexcept {
+		return c == '-' ? '_' : c;
+	});
 
-    return {
-        str(format("irccd_abi_%1%") % id),
-        str(format("irccd_init_%1%") % id)
-    };
+	return {
+		str(format("irccd_abi_%1%") % id),
+		str(format("irccd_init_%1%") % id)
+	};
 }
 
 } // !namespace
 
 dynlib_plugin_loader::dynlib_plugin_loader(std::vector<std::string> directories) noexcept
-    : plugin_loader(std::move(directories), { DYNLIB_EXTENSION })
+	: plugin_loader(std::move(directories), { DYNLIB_EXTENSION })
 {
 }
 
 auto dynlib_plugin_loader::open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>
 {
-    const std::string idstr(id);
-    const std::string pathstr(path);
+	const std::string idstr(id);
+	const std::string pathstr(path);
 
-    const auto [ abisym, initsym ] = symbol(pathstr);
+	const auto [ abisym, initsym ] = symbol(pathstr);
 
-    using abisym_func_type = version ();
-    using initsym_func_type = std::unique_ptr<plugin> (std::string);
+	using abisym_func_type = version ();
+	using initsym_func_type = std::unique_ptr<plugin> (std::string);
 
-    const auto abi = boost::dll::import_alias<abisym_func_type>(pathstr, abisym);
-    const auto init = boost::dll::import_alias<initsym_func_type>(pathstr, initsym);
+	const auto abi = boost::dll::import_alias<abisym_func_type>(pathstr, abisym);
+	const auto init = boost::dll::import_alias<initsym_func_type>(pathstr, initsym);
 
-    // The abi version is reset after new major version, check for both.
-    const version current;
+	// The abi version is reset after new major version, check for both.
+	const version current;
 
-    if (current.major != abi().major || current.abi != abi().abi)
-        throw plugin_error(plugin_error::exec_error, idstr, "incompatible version");
+	if (current.major != abi().major || current.abi != abi().abi)
+		throw plugin_error(plugin_error::exec_error, idstr, "incompatible version");
 
-    auto plg = init(idstr);
+	auto plg = init(idstr);
 
-    if (!plg)
-        throw plugin_error(plugin_error::exec_error, idstr, "invalid plugin");
+	if (!plg)
+		throw plugin_error(plugin_error::exec_error, idstr, "invalid plugin");
 
-    /*
-     * We need to keep a reference to `init' variable for the whole plugin
-     * lifetime.
-     */
-    return std::shared_ptr<plugin>(plg.release(), [init] (auto ptr) mutable {
-        delete ptr;
-    });
+	/*
+	 * We need to keep a reference to `init' variable for the whole plugin
+	 * lifetime.
+	 */
+	return std::shared_ptr<plugin>(plg.release(), [init] (auto ptr) mutable {
+		delete ptr;
+	});
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/dynlib_plugin.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,17 +33,17 @@
  */
 class dynlib_plugin_loader : public plugin_loader {
 public:
-    /**
-     * Constructor.
-     *
-     * \param directories optional directories to search, if empty use defaults.
-     */
-    dynlib_plugin_loader(std::vector<std::string> directories = {}) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \param directories optional directories to search, if empty use defaults.
+	 */
+	dynlib_plugin_loader(std::vector<std::string> directories = {}) noexcept;
 
-    /**
-     * \copydoc plugin_loader::open
-     */
-    auto open(std::string_view id, std::string_view file) -> std::shared_ptr<plugin> override;
+	/**
+	 * \copydoc plugin_loader::open
+	 */
+	auto open(std::string_view id, std::string_view file) -> std::shared_ptr<plugin> override;
 };
 
 } // !irccd
--- a/libirccd/irccd/daemon/irc.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/irc.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,86 +30,86 @@
 
 auto message::get(unsigned short index) const noexcept -> const std::string&
 {
-    static const std::string dummy;
+	static const std::string dummy;
 
-    return (index >= args.size()) ? dummy : args[index];
+	return (index >= args.size()) ? dummy : args[index];
 }
 
 auto message::is_ctcp(unsigned index) const noexcept -> bool
 {
-    const auto a = get(index);
+	const auto a = get(index);
 
-    if (a.empty())
-        return false;
+	if (a.empty())
+		return false;
 
-    return a.front() == 0x01 && a.back() == 0x01;
+	return a.front() == 0x01 && a.back() == 0x01;
 }
 
 auto message::ctcp(unsigned index) const -> std::string
 {
-    assert(is_ctcp(index));
+	assert(is_ctcp(index));
 
-    return args[index].substr(1, args[index].size() - 1);
+	return args[index].substr(1, args[index].size() - 1);
 }
 
 auto message::parse(const std::string& line) -> message
 {
-    std::istringstream iss(line);
-    std::string prefix;
+	std::istringstream iss(line);
+	std::string prefix;
 
-    if (line.empty())
-        return {};
+	if (line.empty())
+		return {};
 
-    // Prefix.
-    if (line[0] == ':') {
-        iss.ignore(1);
-        iss >> prefix;
-        iss.ignore(1);
-    }
+	// Prefix.
+	if (line[0] == ':') {
+		iss.ignore(1);
+		iss >> prefix;
+		iss.ignore(1);
+	}
 
-    // Command.
-    std::string command;
-    iss >> command;
-    iss.ignore(1);
+	// Command.
+	std::string command;
+	iss >> command;
+	iss.ignore(1);
 
-    // Arguments.
-    std::vector<std::string> args;
-    std::istreambuf_iterator<char> it(iss), end;
+	// Arguments.
+	std::vector<std::string> args;
+	std::istreambuf_iterator<char> it(iss), end;
 
-    while (it != end) {
-        std::string arg;
+	while (it != end) {
+		std::string arg;
 
-        if (*it == ':')
-            arg = std::string(++it, end);
-        else {
-            while (!isspace(*it) && it != end)
-                arg.push_back(*it++);
+		if (*it == ':')
+			arg = std::string(++it, end);
+		else {
+			while (!isspace(*it) && it != end)
+				arg.push_back(*it++);
 
-            // Skip space after param.
-            if (it != end)
-                ++it;
-        }
+			// Skip space after param.
+			if (it != end)
+				++it;
+		}
 
-        args.push_back(std::move(arg));
-    }
+		args.push_back(std::move(arg));
+	}
 
-    return { std::move(prefix), std::move(command), std::move(args) };
+	return { std::move(prefix), std::move(command), std::move(args) };
 }
 
 auto user::parse(std::string_view line) -> user
 {
-    if (line.empty())
-        return { "", "" };
+	if (line.empty())
+		return { "", "" };
 
-    const auto pos = line.find("!");
+	const auto pos = line.find("!");
 
-    if (pos == std::string::npos)
-        return { std::string(line), "" };
+	if (pos == std::string::npos)
+		return { std::string(line), "" };
 
-    return {
-        std::string(line.substr(0, pos)),
-        std::string(line.substr(pos + 1))
-    };
+	return {
+		std::string(line.substr(0, pos)),
+		std::string(line.substr(pos + 1))
+	};
 }
 
 template <typename Socket>
@@ -118,56 +118,56 @@
                               const std::string& service,
                               const connect_handler& handler) noexcept
 {
-    using boost::asio::ip::tcp;
+	using boost::asio::ip::tcp;
 
-    tcp::resolver::query query(host, service);
+	tcp::resolver::query query(host, service);
 
-    resolver_.async_resolve(query, [&socket, handler] (auto code, auto it) {
-        if (code) {
-            handler(code);
-        } else {
-            async_connect(socket, it, [handler] (auto code, auto) {
-                handler(code);
-            });
-        }
-    });
+	resolver_.async_resolve(query, [&socket, handler] (auto code, auto it) {
+		if (code) {
+			handler(code);
+		} else {
+			async_connect(socket, it, [handler] (auto code, auto) {
+				handler(code);
+			});
+		}
+	});
 }
 
 template <typename Socket>
 void connection::wrap_recv(Socket& socket, const recv_handler& handler) noexcept
 {
-    async_read_until(socket, input_, "\r\n", [this, handler] (auto code, auto xfer) {
-        if (xfer == 0U)
-            return handler(make_error_code(boost::asio::error::eof), message());
-        else if (code)
-            return handler(std::move(code), message());
+	async_read_until(socket, input_, "\r\n", [this, handler] (auto code, auto xfer) {
+		if (xfer == 0U)
+			return handler(make_error_code(boost::asio::error::eof), message());
+		else if (code)
+			return handler(std::move(code), message());
 
-        std::string data;
+		std::string data;
 
-        try {
-            data = std::string(
-                boost::asio::buffers_begin(input_.data()),
-                boost::asio::buffers_begin(input_.data()) + xfer - 2
-            );
+		try {
+			data = std::string(
+				boost::asio::buffers_begin(input_.data()),
+				boost::asio::buffers_begin(input_.data()) + xfer - 2
+			);
 
-            input_.consume(xfer);
-        } catch (...) {
-            code = make_error_code(boost::system::errc::not_enough_memory);
-        }
+			input_.consume(xfer);
+		} catch (...) {
+			code = make_error_code(boost::system::errc::not_enough_memory);
+		}
 
-        handler(code, code ? message() : message::parse(data));
-    });
+		handler(code, code ? message() : message::parse(data));
+	});
 }
 
 template <typename Socket>
 void connection::wrap_send(Socket& socket, const send_handler& handler) noexcept
 {
-    boost::asio::async_write(socket, output_, [handler] (auto code, auto xfer) {
-        if (xfer == 0U)
-            return handler(make_error_code(boost::asio::error::eof));
+	boost::asio::async_write(socket, output_, [handler] (auto code, auto xfer) {
+		if (xfer == 0U)
+			return handler(make_error_code(boost::asio::error::eof));
 
-        handler(code);
-    });
+		handler(code);
+	});
 }
 
 void connection::connect(const std::string& host,
@@ -175,77 +175,77 @@
                          const connect_handler& handler) noexcept
 {
 #if !defined(NDEBUG)
-    assert(handler);
-    assert(!is_connecting_);
+	assert(handler);
+	assert(!is_connecting_);
 
-    is_connecting_ = true;
+	is_connecting_ = true;
 #endif
 
-    do_connect(host, service, [this, handler] (auto code) {
+	do_connect(host, service, [this, handler] (auto code) {
 #if !defined(NDEBUG)
-        is_connecting_ = false;
+		is_connecting_ = false;
 #endif
-        (void)this;
-        handler(std::move(code));
-    });
+		(void)this;
+		handler(std::move(code));
+	});
 }
 
 void connection::recv(const recv_handler& handler) noexcept
 {
 #if !defined(NDEBUG)
-    assert(handler);
-    assert(!is_receiving_);
+	assert(handler);
+	assert(!is_receiving_);
 
-    is_receiving_ = true;
+	is_receiving_ = true;
 #endif
 
-    do_recv([this, handler] (auto code, auto message) {
+	do_recv([this, handler] (auto code, auto message) {
 #if !defined(NDEBUG)
-        is_receiving_ = false;
+		is_receiving_ = false;
 #endif
-        (void)this;
-        handler(std::move(code), std::move(message));
-    });
+		(void)this;
+		handler(std::move(code), std::move(message));
+	});
 }
 
 void connection::send(std::string message, const send_handler& handler)
 {
 #if !defined(NDEBUG)
-    assert(handler);
-    assert(!is_sending_);
+	assert(handler);
+	assert(!is_sending_);
 
-    is_sending_ = true;
+	is_sending_ = true;
 #endif
 
-    std::ostream out(&output_);
+	std::ostream out(&output_);
 
-    out << std::move(message);
-    out << "\r\n";
+	out << std::move(message);
+	out << "\r\n";
 
-    do_send([this, handler] (auto code) {
+	do_send([this, handler] (auto code) {
 #if !defined(NDEBUG)
-        is_sending_ = false;
+		is_sending_ = false;
 #endif
-        (void)this;
-        handler(std::move(code));
-    });
+		(void)this;
+		handler(std::move(code));
+	});
 }
 
 void ip_connection::do_connect(const std::string& host,
                                const std::string& service,
                                const connect_handler& handler) noexcept
 {
-    wrap_connect(socket_, host, service, handler);
+	wrap_connect(socket_, host, service, handler);
 }
 
 void ip_connection::do_recv(const recv_handler& handler) noexcept
 {
-    wrap_recv(socket_, handler);
+	wrap_recv(socket_, handler);
 }
 
 void ip_connection::do_send(const send_handler& handler) noexcept
 {
-    wrap_send(socket_, handler);
+	wrap_send(socket_, handler);
 }
 
 #if defined(IRCCD_HAVE_SSL)
@@ -254,27 +254,27 @@
                                 const std::string& service,
                                 const connect_handler& handler) noexcept
 {
-    using boost::asio::ssl::stream_base;
+	using boost::asio::ssl::stream_base;
 
-    wrap_connect(socket_.lowest_layer(), host, service, [this, handler] (auto code) {
-        if (code) {
-            handler(code);
-        } else {
-            socket_.async_handshake(stream_base::client, [handler] (auto code) {
-                handler(code);
-            });
-        }
-    });
+	wrap_connect(socket_.lowest_layer(), host, service, [this, handler] (auto code) {
+		if (code) {
+			handler(code);
+		} else {
+			socket_.async_handshake(stream_base::client, [handler] (auto code) {
+				handler(code);
+			});
+		}
+	});
 }
 
 void tls_connection::do_recv(const recv_handler& handler) noexcept
 {
-    wrap_recv(socket_, handler);
+	wrap_recv(socket_, handler);
 }
 
 void tls_connection::do_send(const send_handler& handler) noexcept
 {
-    wrap_send(socket_, handler);
+	wrap_send(socket_, handler);
 }
 
 #endif // !IRCCD_HAVE_SSL
--- a/libirccd/irccd/daemon/irc.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/irc.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -46,444 +46,444 @@
  * See [RFC1459 (6.1)](https://tools.ietf.org/html/rfc1459#section-6.1).
  */
 enum class err {
-    /**
-     * ERR_NOSUCHNICK
-     *
-     * "<nickname> :No such nick/channel"
-     *
-     * Used to indicate the nickname parameter supplied to a
-     * command is currently unused.
-     */
-    nosuchnick = 401,
+	/**
+	 * ERR_NOSUCHNICK
+	 *
+	 * "<nickname> :No such nick/channel"
+	 *
+	 * Used to indicate the nickname parameter supplied to a
+	 * command is currently unused.
+	 */
+	nosuchnick = 401,
 
-    /**
-     * ERR_NOSUCHSERVER
-     *
-     * "<server name> :No such server"
-     *
-     * Used to indicate the server name given currently
-     * doesn't exist.
-     */
-    nosuchserver = 402,
+	/**
+	 * ERR_NOSUCHSERVER
+	 *
+	 * "<server name> :No such server"
+	 *
+	 * Used to indicate the server name given currently
+	 * doesn't exist.
+	 */
+	nosuchserver = 402,
 
-    /**
-     * ERR_NOSUCHCHANNEL
-     *
-     * "<channel name> :No such channel"
-     *
-     * Used to indicate the given channel name is invalid.
-     */
-    nosuchchannel = 403,
+	/**
+	 * ERR_NOSUCHCHANNEL
+	 *
+	 * "<channel name> :No such channel"
+	 *
+	 * Used to indicate the given channel name is invalid.
+	 */
+	nosuchchannel = 403,
 
-    /**
-     * ERR_CANNOTSENDTOCHAN
-     *
-     * "<channel name> :Cannot send to channel"
-     *
-     * Sent to a user who is either (a) not on a channel
-     * which is mode +n or (b) not a chanop (or mode +v) on
-     * a channel which has mode +m set and is trying to send
-     * a PRIVMSG message to that channel.
-     */
-    cannotsendtochan = 404,
+	/**
+	 * ERR_CANNOTSENDTOCHAN
+	 *
+	 * "<channel name> :Cannot send to channel"
+	 *
+	 * Sent to a user who is either (a) not on a channel
+	 * which is mode +n or (b) not a chanop (or mode +v) on
+	 * a channel which has mode +m set and is trying to send
+	 * a PRIVMSG message to that channel.
+	 */
+	cannotsendtochan = 404,
 
-    /**
-     * ERR_TOOMANYCHANNELS
-     *
-     * "<channel name> :You have joined too many channels"
-     *
-     * Sent to a user when they have joined the maximum
-     * number of allowed channels and they try to join
-     * another channel.
-     */
-    toomanychannels = 405,
+	/**
+	 * ERR_TOOMANYCHANNELS
+	 *
+	 * "<channel name> :You have joined too many channels"
+	 *
+	 * Sent to a user when they have joined the maximum
+	 * number of allowed channels and they try to join
+	 * another channel.
+	 */
+	toomanychannels = 405,
 
-    /**
-     * ERR_WASNOSUCHNICK
-     *
-     * "<nickname> :There was no such nickname"
-     *
-     * Returned by WHOWAS to indicate there is no history
-     * information for that nickname.
-     */
-    wasnosuchnick = 406,
+	/**
+	 * ERR_WASNOSUCHNICK
+	 *
+	 * "<nickname> :There was no such nickname"
+	 *
+	 * Returned by WHOWAS to indicate there is no history
+	 * information for that nickname.
+	 */
+	wasnosuchnick = 406,
 
-    /**
-     * ERR_TOOMANYTARGETS
-     *
-     * "<target> :Duplicate recipients. No message delivered"
-     *
-     * Returned to a client which is attempting to send a
-     * PRIVMSG/NOTICE using the user@host destination format
-     * and for a user@host which has several occurrences.
-     */
-    toomanytargets = 407,
+	/**
+	 * ERR_TOOMANYTARGETS
+	 *
+	 * "<target> :Duplicate recipients. No message delivered"
+	 *
+	 * Returned to a client which is attempting to send a
+	 * PRIVMSG/NOTICE using the user@host destination format
+	 * and for a user@host which has several occurrences.
+	 */
+	toomanytargets = 407,
 
-    /**
-     * ERR_NOORIGIN
-     *
-     * ":No origin specified"
-     *
-     * PING or PONG message missing the originator parameter
-     * which is required since these commands must work
-     * without valid prefixes.
-     */
-    noorigin = 409,
+	/**
+	 * ERR_NOORIGIN
+	 *
+	 * ":No origin specified"
+	 *
+	 * PING or PONG message missing the originator parameter
+	 * which is required since these commands must work
+	 * without valid prefixes.
+	 */
+	noorigin = 409,
 
-    /**
-     * ERR_NORECIPIENT
-     *
-     * ":No recipient given (<command>)"
-     */
-    norecipient = 411,
+	/**
+	 * ERR_NORECIPIENT
+	 *
+	 * ":No recipient given (<command>)"
+	 */
+	norecipient = 411,
 
-    /**
-     * ERR_NOTEXTTOSEND
-     *
-     * ":No text to send"
-     */
-    notexttosend = 412,
+	/**
+	 * ERR_NOTEXTTOSEND
+	 *
+	 * ":No text to send"
+	 */
+	notexttosend = 412,
 
-    /**
-     * ERR_NOTOPLEVEL
-     *
-     * "<mask> :No toplevel domain specified"
-     */
-    notoplevel = 413,
+	/**
+	 * ERR_NOTOPLEVEL
+	 *
+	 * "<mask> :No toplevel domain specified"
+	 */
+	notoplevel = 413,
 
-    /**
-     * ERR_WILDTOPLEVEL
-     *
-     * "<mask> :Wildcard in toplevel domain"
-     *
-     * are returned by PRIVMSG to indicate that
-     * the message wasn't delivered for some reason.
-     * ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
-     * are returned when an invalid use of
-     * "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
-     */
-    wildtoplevel = 414,
+	/**
+	 * ERR_WILDTOPLEVEL
+	 *
+	 * "<mask> :Wildcard in toplevel domain"
+	 *
+	 * are returned by PRIVMSG to indicate that
+	 * the message wasn't delivered for some reason.
+	 * ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+	 * are returned when an invalid use of
+	 * "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
+	 */
+	wildtoplevel = 414,
 
-    /**
-     * ERR_UNKNOWNCOMMAND
-     *
-     * "<command> :Unknown command"
-     *
-     * Returned to a registered client to indicate that the
-     * command sent is unknown by the server.
-     */
-    unknowncommand = 421,
+	/**
+	 * ERR_UNKNOWNCOMMAND
+	 *
+	 * "<command> :Unknown command"
+	 *
+	 * Returned to a registered client to indicate that the
+	 * command sent is unknown by the server.
+	 */
+	unknowncommand = 421,
 
-    /**
-     * ERR_NOMOTD
-     *
-     * ":MOTD File is missing"
-     *
-     * Server's MOTD file could not be opened by the server.
-     */
-    nomotd = 422,
+	/**
+	 * ERR_NOMOTD
+	 *
+	 * ":MOTD File is missing"
+	 *
+	 * Server's MOTD file could not be opened by the server.
+	 */
+	nomotd = 422,
 
-    /**
-     * ERR_NOADMININFO
-     *
-     * "<server> :No administrative info available"
-     *
-     * Returned by a server in response to an ADMIN message
-     * when there is an error in finding the appropriate
-     * information.
-     */
-    noadmininfo = 423,
+	/**
+	 * ERR_NOADMININFO
+	 *
+	 * "<server> :No administrative info available"
+	 *
+	 * Returned by a server in response to an ADMIN message
+	 * when there is an error in finding the appropriate
+	 * information.
+	 */
+	noadmininfo = 423,
 
-    /**
-     * ERR_FILEERROR
-     *
-     * ":File error doing <file op> on <file>"
-     *
-     * Generic error message used to report a failed file
-     * operation during the processing of a message.
-     */
-    fileerror = 424,
+	/**
+	 * ERR_FILEERROR
+	 *
+	 * ":File error doing <file op> on <file>"
+	 *
+	 * Generic error message used to report a failed file
+	 * operation during the processing of a message.
+	 */
+	fileerror = 424,
 
-    /**
-     * ERR_NONICKNAMEGIVEN
-     *
-     * ":No nickname given"
-     *
-     * Returned when a nickname parameter expected for a
-     * command and isn't found.
-     */
-    nonicknamegiven = 431,
+	/**
+	 * ERR_NONICKNAMEGIVEN
+	 *
+	 * ":No nickname given"
+	 *
+	 * Returned when a nickname parameter expected for a
+	 * command and isn't found.
+	 */
+	nonicknamegiven = 431,
 
-    /**
-     * ERR_ERRONEUSNICKNAME
-     *
-     * "<nick> :Erroneus nickname"
-     *
-     * Returned after receiving a NICK message which contains
-     * characters which do not fall in the defined set.  See
-     * section x.x.x for details on valid nicknames.
-     */
-    erroneusnickname = 432,
+	/**
+	 * ERR_ERRONEUSNICKNAME
+	 *
+	 * "<nick> :Erroneus nickname"
+	 *
+	 * Returned after receiving a NICK message which contains
+	 * characters which do not fall in the defined set.  See
+	 * section x.x.x for details on valid nicknames.
+	 */
+	erroneusnickname = 432,
 
-    /**
-     * ERR_NICKNAMEINUSE
-     *
-     * "<nick> :Nickname is already in use"
-     *
-     * Returned when a NICK message is processed that results
-     * in an attempt to change to a currently existing
-     * nickname.
-     */
-    nicknameinuse = 433,
+	/**
+	 * ERR_NICKNAMEINUSE
+	 *
+	 * "<nick> :Nickname is already in use"
+	 *
+	 * Returned when a NICK message is processed that results
+	 * in an attempt to change to a currently existing
+	 * nickname.
+	 */
+	nicknameinuse = 433,
 
-    /**
-     * ERR_NICKCOLLISION
-     *
-     * "<nick> :Nickname collision KILL"
-     *
-     * Returned by a server to a client when it detects a
-     * nickname collision (registered of a NICK that
-     * already exists by another server).
-     */
-    nickcollision = 436,
+	/**
+	 * ERR_NICKCOLLISION
+	 *
+	 * "<nick> :Nickname collision KILL"
+	 *
+	 * Returned by a server to a client when it detects a
+	 * nickname collision (registered of a NICK that
+	 * already exists by another server).
+	 */
+	nickcollision = 436,
 
-    /**
-     * ERR_USERNOTINCHANNEL
-     *
-     * "<nick> <channel> :They aren't on that channel"
-     *
-     * Returned by the server to indicate that the target
-     * user of the command is not on the given channel.
-     */
-    usernotinchannel = 441,
+	/**
+	 * ERR_USERNOTINCHANNEL
+	 *
+	 * "<nick> <channel> :They aren't on that channel"
+	 *
+	 * Returned by the server to indicate that the target
+	 * user of the command is not on the given channel.
+	 */
+	usernotinchannel = 441,
 
-    /**
-     * ERR_NOTONCHANNEL
-     *
-     * "<channel> :You're not on that channel"
-     *
-     * Returned by the server whenever a client tries to
-     * perform a channel effecting command for which the
-     * client isn't a member.
-     */
-    notonchannel = 442,
+	/**
+	 * ERR_NOTONCHANNEL
+	 *
+	 * "<channel> :You're not on that channel"
+	 *
+	 * Returned by the server whenever a client tries to
+	 * perform a channel effecting command for which the
+	 * client isn't a member.
+	 */
+	notonchannel = 442,
 
-    /**
-     * ERR_USERONCHANNEL
-     *
-     * "<user> <channel> :is already on channel"
-     *
-     * Returned when a client tries to invite a user to a
-     * channel they are already on.
-     */
-    useronchannel = 443,
+	/**
+	 * ERR_USERONCHANNEL
+	 *
+	 * "<user> <channel> :is already on channel"
+	 *
+	 * Returned when a client tries to invite a user to a
+	 * channel they are already on.
+	 */
+	useronchannel = 443,
 
-    /**
-     * ERR_NOLOGIN
-     *
-     * "<user> :User not logged in"
-     *
-     * Returned by the summon after a SUMMON command for a
-     * user was unable to be performed since they were not
-     * logged in.
-     */
-    nologin = 444,
+	/**
+	 * ERR_NOLOGIN
+	 *
+	 * "<user> :User not logged in"
+	 *
+	 * Returned by the summon after a SUMMON command for a
+	 * user was unable to be performed since they were not
+	 * logged in.
+	 */
+	nologin = 444,
 
-    /**
-     * ERR_SUMMONDISABLED
-     *
-     * ":SUMMON has been disabled"
-     *
-     * Returned as a response to the SUMMON command.  Must be
-     * returned by any server which does not implement it.
-     */
-    summondisabled = 445,
+	/**
+	 * ERR_SUMMONDISABLED
+	 *
+	 * ":SUMMON has been disabled"
+	 *
+	 * Returned as a response to the SUMMON command.  Must be
+	 * returned by any server which does not implement it.
+	 */
+	summondisabled = 445,
 
-    /**
-     * ERR_USERSDISABLED
-     *
-     * ":USERS has been disabled"
-     *
-     * Returned as a response to the USERS command.  Must be
-     * returned by any server which does not implement it.
-     */
-    usersdisabled = 446,
+	/**
+	 * ERR_USERSDISABLED
+	 *
+	 * ":USERS has been disabled"
+	 *
+	 * Returned as a response to the USERS command.  Must be
+	 * returned by any server which does not implement it.
+	 */
+	usersdisabled = 446,
 
-    /**
-     * ERR_NOTREGISTERED
-     *
-     * ":You have not registered"
-     *
-     * Returned by the server to indicate that the client
-     * must be registered before the server will allow it
-     * to be parsed in detail.
-     */
-    notregistered = 451,
+	/**
+	 * ERR_NOTREGISTERED
+	 *
+	 * ":You have not registered"
+	 *
+	 * Returned by the server to indicate that the client
+	 * must be registered before the server will allow it
+	 * to be parsed in detail.
+	 */
+	notregistered = 451,
 
-    /**
-     * ERR_NEEDMOREPARAMS
-     *
-     * "<command> :Not enough parameters"
-     *
-     * Returned by the server by numerous commands to
-     * indicate to the client that it didn't supply enough
-     * parameters.
-     */
-    needmoreparams = 461,
+	/**
+	 * ERR_NEEDMOREPARAMS
+	 *
+	 * "<command> :Not enough parameters"
+	 *
+	 * Returned by the server by numerous commands to
+	 * indicate to the client that it didn't supply enough
+	 * parameters.
+	 */
+	needmoreparams = 461,
 
-    /**
-     * ERR_ALREADYREGISTRED
-     *
-     * ":You may not reregister"
-     *
-     * Returned by the server to any link which tries to
-     * change part of the registered details (such as
-     * password or user details from second USER message).
-     */
-    alreadyregistred = 462,
+	/**
+	 * ERR_ALREADYREGISTRED
+	 *
+	 * ":You may not reregister"
+	 *
+	 * Returned by the server to any link which tries to
+	 * change part of the registered details (such as
+	 * password or user details from second USER message).
+	 */
+	alreadyregistred = 462,
 
-    /**
-     * ERR_NOPERMFORHOST
-     *
-     * ":Your host isn't among the privileged"
-     *
-     * Returned to a client which attempts to register with
-     * a server which does not been setup to allow
-     * connections from the host the attempted connection
-     * is tried.
-     */
-    nopermforhost = 463,
+	/**
+	 * ERR_NOPERMFORHOST
+	 *
+	 * ":Your host isn't among the privileged"
+	 *
+	 * Returned to a client which attempts to register with
+	 * a server which does not been setup to allow
+	 * connections from the host the attempted connection
+	 * is tried.
+	 */
+	nopermforhost = 463,
 
-    /**
-     * ERR_PASSWDMISMATCH
-     *
-     * ":Password incorrect"
-     *
-     * Returned to indicate a failed attempt at registering
-     * a connection for which a password was required and
-     * was either not given or incorrect.
-     */
-    passwdmismatch = 464,
+	/**
+	 * ERR_PASSWDMISMATCH
+	 *
+	 * ":Password incorrect"
+	 *
+	 * Returned to indicate a failed attempt at registering
+	 * a connection for which a password was required and
+	 * was either not given or incorrect.
+	 */
+	passwdmismatch = 464,
 
-    /**
-     * ERR_YOUREBANNEDCREEP
-     *
-     * ":You are banned from this server"
-     *
-     * Returned after an attempt to connect and register
-     * yourself with a server which has been setup to
-     * explicitly deny connections to you.
-     */
-    yourebannedcreep = 465,
+	/**
+	 * ERR_YOUREBANNEDCREEP
+	 *
+	 * ":You are banned from this server"
+	 *
+	 * Returned after an attempt to connect and register
+	 * yourself with a server which has been setup to
+	 * explicitly deny connections to you.
+	 */
+	yourebannedcreep = 465,
 
-    /**
-     * ERR_KEYSET
-     *
-     * "<channel> :Channel key already set"
-     */
-    keyset = 467,
+	/**
+	 * ERR_KEYSET
+	 *
+	 * "<channel> :Channel key already set"
+	 */
+	keyset = 467,
 
-    /**
-     * ERR_CHANNELISFULL
-     *
-     * "<channel> :Cannot join channel (+l)"
-     */
-    channelisfull = 471,
+	/**
+	 * ERR_CHANNELISFULL
+	 *
+	 * "<channel> :Cannot join channel (+l)"
+	 */
+	channelisfull = 471,
 
-    /**
-     * ERR_UNKNOWNMODE
-     *
-     * "<char> :is unknown mode char to me"
-     */
-    unknownmode = 472,
+	/**
+	 * ERR_UNKNOWNMODE
+	 *
+	 * "<char> :is unknown mode char to me"
+	 */
+	unknownmode = 472,
 
-    /**
-     * ERR_INVITEONLYCHAN
-     *
-     * "<channel> :Cannot join channel (+i)"
-     */
-    inviteonlychan = 473,
+	/**
+	 * ERR_INVITEONLYCHAN
+	 *
+	 * "<channel> :Cannot join channel (+i)"
+	 */
+	inviteonlychan = 473,
 
-    /**
-     * ERR_BANNEDFROMCHAN
-     *
-     * "<channel> :Cannot join channel (+b)"
-     */
-    bannedfromchan = 474,
+	/**
+	 * ERR_BANNEDFROMCHAN
+	 *
+	 * "<channel> :Cannot join channel (+b)"
+	 */
+	bannedfromchan = 474,
 
-    /**
-     * ERR_BADCHANNELKEY
-     *
-     * "<channel> :Cannot join channel (+k)"
-     */
-    badchannelkey = 475,
+	/**
+	 * ERR_BADCHANNELKEY
+	 *
+	 * "<channel> :Cannot join channel (+k)"
+	 */
+	badchannelkey = 475,
 
-    /**
-     * ERR_NOPRIVILEGES
-     *
-     * ":Permission Denied- You're not an IRC operator"
-     *
-     * Any command requiring operator privileges to operate
-     * must return this error to indicate the attempt was
-     * unsuccessful.
-     */
-    noprivileges = 481,
+	/**
+	 * ERR_NOPRIVILEGES
+	 *
+	 * ":Permission Denied- You're not an IRC operator"
+	 *
+	 * Any command requiring operator privileges to operate
+	 * must return this error to indicate the attempt was
+	 * unsuccessful.
+	 */
+	noprivileges = 481,
 
-    /**
-     * ERR_CHANOPRIVSNEEDED
-     *
-     * "<channel> :You're not channel operator"
-     *
-     * Any command requiring 'chanop' privileges (such as
-     * MODE messages) must return this error if the client
-     * making the attempt is not a chanop on the specified
-     * channel.
-     */
-    chanoprivsneeded = 482,
+	/**
+	 * ERR_CHANOPRIVSNEEDED
+	 *
+	 * "<channel> :You're not channel operator"
+	 *
+	 * Any command requiring 'chanop' privileges (such as
+	 * MODE messages) must return this error if the client
+	 * making the attempt is not a chanop on the specified
+	 * channel.
+	 */
+	chanoprivsneeded = 482,
 
-    /**
-     * ERR_CANTKILLSERVER
-     *
-     * ":You cant kill a server!"
-     *
-     * Any attempts to use the KILL command on a server
-     * are to be refused and this error returned directly
-     * to the client.
-     */
-    cantkillserver = 483,
+	/**
+	 * ERR_CANTKILLSERVER
+	 *
+	 * ":You cant kill a server!"
+	 *
+	 * Any attempts to use the KILL command on a server
+	 * are to be refused and this error returned directly
+	 * to the client.
+	 */
+	cantkillserver = 483,
 
-    /**
-     * ERR_NOOPERHOST
-     *
-     * ":No O-lines for your host"
-     *
-     * If a client sends an OPER message and the server has
-     * not been configured to allow connections from the
-     * client's host as an operator, this error must be
-     * returned.
-     */
-    nooperhost = 491,
+	/**
+	 * ERR_NOOPERHOST
+	 *
+	 * ":No O-lines for your host"
+	 *
+	 * If a client sends an OPER message and the server has
+	 * not been configured to allow connections from the
+	 * client's host as an operator, this error must be
+	 * returned.
+	 */
+	nooperhost = 491,
 
-    /**
-     * ERR_UMODEUNKNOWNFLAG
-     *
-     * ":Unknown MODE flag"
-     *
-     * Returned by the server to indicate that a MODE
-     * message was sent with a nickname parameter and that
-     * the a mode flag sent was not recognized.
-     */
-    umodeunknownflag = 501,
+	/**
+	 * ERR_UMODEUNKNOWNFLAG
+	 *
+	 * ":Unknown MODE flag"
+	 *
+	 * Returned by the server to indicate that a MODE
+	 * message was sent with a nickname parameter and that
+	 * the a mode flag sent was not recognized.
+	 */
+	umodeunknownflag = 501,
 
-    /**
-     * ERR_USERSDONTMATCH
-     *
-     * ":Cant change mode for other users"
-     *
-     * Error sent to any user trying to view or change the
-     * user mode for a user other than themselves.
-     */
-    usersdontmatch = 502
+	/**
+	 * ERR_USERSDONTMATCH
+	 *
+	 * ":Cant change mode for other users"
+	 *
+	 * Error sent to any user trying to view or change the
+	 * user mode for a user other than themselves.
+	 */
+	usersdontmatch = 502
 };
 
 /**
@@ -492,777 +492,777 @@
  * See [RFC1459 (6.2)](https://tools.ietf.org/html/rfc1459#section-6.2).
  */
 enum class rpl {
-    /**
-     * RPL_NONE
-     *
-     * Dummy reply number. Not used.
-     */
-    none = 300,
+	/**
+	 * RPL_NONE
+	 *
+	 * Dummy reply number. Not used.
+	 */
+	none = 300,
 
-    /**
-     * RPL_USERHOST
-     *
-     * ":[<reply>{<space><reply>}]"
-     *
-     * Reply format used by USERHOST to list replies to
-     * the query list.  The reply string is composed as
-     * follows:
-     *
-     * <reply> ::= <nick>['*'] '=' <'+'|'-'><hostname>
-     *
-     * The '*' indicates whether the client has registered
-     * as an Operator.  The '-' or '+' characters represent
-     * whether the client has set an AWAY message or not
-     * respectively.
-     */
-    userhost = 302,
+	/**
+	 * RPL_USERHOST
+	 *
+	 * ":[<reply>{<space><reply>}]"
+	 *
+	 * Reply format used by USERHOST to list replies to
+	 * the query list.  The reply string is composed as
+	 * follows:
+	 *
+	 * <reply> ::= <nick>['*'] '=' <'+'|'-'><hostname>
+	 *
+	 * The '*' indicates whether the client has registered
+	 * as an Operator.  The '-' or '+' characters represent
+	 * whether the client has set an AWAY message or not
+	 * respectively.
+	 */
+	userhost = 302,
 
-    /**
-     * RPL_ISON
-     *
-     * ":[<nick> {<space><nick>}]"
-     *
-     * Reply format used by ISON to list replies to the
-     * query list.
-     */
-    ison = 303,
+	/**
+	 * RPL_ISON
+	 *
+	 * ":[<nick> {<space><nick>}]"
+	 *
+	 * Reply format used by ISON to list replies to the
+	 * query list.
+	 */
+	ison = 303,
 
-    /**
-     * RPL_AWAY
-     *
-     * "<nick> :<away message>"
-     */
-    away = 301,
+	/**
+	 * RPL_AWAY
+	 *
+	 * "<nick> :<away message>"
+	 */
+	away = 301,
 
-    /**
-     * RPL_UNAWAY
-     *
-     * ":You are no longer marked as being away"
-     */
-    unaway = 305,
+	/**
+	 * RPL_UNAWAY
+	 *
+	 * ":You are no longer marked as being away"
+	 */
+	unaway = 305,
 
-    /**
-     * RPL_NOWAWAY
-     *
-     * ":You have been marked as being away"
-     *
-     * These replies are used with the AWAY command (if
-     * allowed).  RPL_AWAY is sent to any client sending a
-     * PRIVMSG to a client which is away.  RPL_AWAY is only
-     * sent by the server to which the client is connected.
-     * Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
-     * client removes and sets an AWAY message.
-     */
-    nowaway = 306,
+	/**
+	 * RPL_NOWAWAY
+	 *
+	 * ":You have been marked as being away"
+	 *
+	 * These replies are used with the AWAY command (if
+	 * allowed).  RPL_AWAY is sent to any client sending a
+	 * PRIVMSG to a client which is away.  RPL_AWAY is only
+	 * sent by the server to which the client is connected.
+	 * Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+	 * client removes and sets an AWAY message.
+	 */
+	nowaway = 306,
 
-    /**
-     * RPL_WHOISUSER
-     *
-     * "<nick> <user> <host> * :<real name>"
-     */
-    whoisuser = 311,
+	/**
+	 * RPL_WHOISUSER
+	 *
+	 * "<nick> <user> <host> * :<real name>"
+	 */
+	whoisuser = 311,
 
-    /**
-     * RPL_WHOISSERVER
-     *
-     * "<nick> <server> :<server info>"
-     */
-    whoisserver = 312,
+	/**
+	 * RPL_WHOISSERVER
+	 *
+	 * "<nick> <server> :<server info>"
+	 */
+	whoisserver = 312,
 
-    /**
-     * RPL_WHOISOPERATOR
-     *
-     * "<nick> :is an IRC operator"
-     */
-    whoisoperator = 313,
+	/**
+	 * RPL_WHOISOPERATOR
+	 *
+	 * "<nick> :is an IRC operator"
+	 */
+	whoisoperator = 313,
 
-    /**
-     * RPL_WHOISIDLE
-     *
-     * "<nick> <integer> :seconds idle"
-     */
-    whoisidle = 317,
+	/**
+	 * RPL_WHOISIDLE
+	 *
+	 * "<nick> <integer> :seconds idle"
+	 */
+	whoisidle = 317,
 
-    /**
-     * RPL_ENDOFWHOIS
-     *
-     * "<nick> :End of /WHOIS list"
-     */
-    endofwhois = 318,
+	/**
+	 * RPL_ENDOFWHOIS
+	 *
+	 * "<nick> :End of /WHOIS list"
+	 */
+	endofwhois = 318,
 
-    /**
-     * RPL_WHOISCHANNELS
-     *
-     * "<nick> :{[@|+]<channel><space>}"
-     *
-     * Replies 311 - 313, 317 - 319 are all replies
-     * generated in response to a WHOIS message.  Given that
-     * there are enough parameters present, the answering
-     * server must either formulate a reply out of the above
-     * numerics (if the query nick is found) or return an
-     * error reply.  The '*' in RPL_WHOISUSER is there as
-     * the literal character and not as a wild card.  For
-     * each reply set, only RPL_WHOISCHANNELS may appear
-     * more than once (for long lists of channel names).
-     * The '@' and '+' characters next to the channel name
-     * indicate whether a client is a channel operator or
-     * has been granted permission to speak on a moderated
-     * channel.  The RPL_ENDOFWHOIS reply is used to mark
-     * the end of processing a WHOIS message.
-     */
-    whoischannels = 319,
+	/**
+	 * RPL_WHOISCHANNELS
+	 *
+	 * "<nick> :{[@|+]<channel><space>}"
+	 *
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	whoischannels = 319,
 
-    /**
-     * RPL_WHOWASUSER
-     *
-     * "<nick> <user> <host> * :<real name>"
-     */
-    whowasuser = 314,
+	/**
+	 * RPL_WHOWASUSER
+	 *
+	 * "<nick> <user> <host> * :<real name>"
+	 */
+	whowasuser = 314,
 
-    /**
-     * RPL_ENDOFWHOWAS
-     *
-     * "<nick> :End of WHOWAS"
-     *
-     * When replying to a WHOWAS message, a server must use
-     * the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
-     * ERR_WASNOSUCHNICK for each nickname in the presented
-     * list.  At the end of all reply batches, there must
-     * be RPL_ENDOFWHOWAS (even if there was only one reply
-     * and it was an error).
-     */
-    endofwhowas = 369,
+	/**
+	 * RPL_ENDOFWHOWAS
+	 *
+	 * "<nick> :End of WHOWAS"
+	 *
+	 * When replying to a WHOWAS message, a server must use
+	 * the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+	 * ERR_WASNOSUCHNICK for each nickname in the presented
+	 * list.  At the end of all reply batches, there must
+	 * be RPL_ENDOFWHOWAS (even if there was only one reply
+	 * and it was an error).
+	 */
+	endofwhowas = 369,
 
-    /**
-     * RPL_LISTSTART
-     *
-     * "Channel :Users  Name"
-     */
-    liststart = 321,
+	/**
+	 * RPL_LISTSTART
+	 *
+	 * "Channel :Users  Name"
+	 */
+	liststart = 321,
 
-    /**
-     * RPL_LIST
-     *
-     * "<channel> <# visible> :<topic>"
-     */
-    list = 322,
+	/**
+	 * RPL_LIST
+	 *
+	 * "<channel> <# visible> :<topic>"
+	 */
+	list = 322,
 
-    /**
-     * RPL_LISTEND
-     *
-     * ":End of /LIST"
-     *
-     * Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
-     * the start, actual replies with data and end of the
-     * server's response to a LIST command.  If there are
-     * no channels available to return, only the start
-     * and end reply must be sent.
-     */
-    listend = 323,
+	/**
+	 * RPL_LISTEND
+	 *
+	 * ":End of /LIST"
+	 *
+	 * Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+	 * the start, actual replies with data and end of the
+	 * server's response to a LIST command.  If there are
+	 * no channels available to return, only the start
+	 * and end reply must be sent.
+	 */
+	listend = 323,
 
-    /**
-     * RPL_CHANNELMODEIS
-     *
-     * "<channel> <mode> <mode params>"
-     */
-    channelmodeis = 324,
+	/**
+	 * RPL_CHANNELMODEIS
+	 *
+	 * "<channel> <mode> <mode params>"
+	 */
+	channelmodeis = 324,
 
-    /**
-     * RPL_NOTOPIC
-     *
-     * "<channel> :No topic is set"
-     */
-    notopic = 331,
+	/**
+	 * RPL_NOTOPIC
+	 *
+	 * "<channel> :No topic is set"
+	 */
+	notopic = 331,
 
-    /**
-     * RPL_TOPIC
-     *
-     * "<channel> :<topic>"
-     *
-     * When sending a TOPIC message to determine the
-     * channel topic, one of two replies is sent.  If
-     * the topic is set, RPL_TOPIC is sent back else
-     * RPL_NOTOPIC.
-     */
-    topic = 332,
+	/**
+	 * RPL_TOPIC
+	 *
+	 * "<channel> :<topic>"
+	 *
+	 * When sending a TOPIC message to determine the
+	 * channel topic, one of two replies is sent.  If
+	 * the topic is set, RPL_TOPIC is sent back else
+	 * RPL_NOTOPIC.
+	 */
+	topic = 332,
 
-    /**
-     * RPL_INVITING
-     *
-     * "<channel> <nick>"
-     *
-     * Returned by the server to indicate that the
-     * attempted INVITE message was successful and is
-     * being passed onto the end client.
-     */
-    inviting = 341,
+	/**
+	 * RPL_INVITING
+	 *
+	 * "<channel> <nick>"
+	 *
+	 * Returned by the server to indicate that the
+	 * attempted INVITE message was successful and is
+	 * being passed onto the end client.
+	 */
+	inviting = 341,
 
-    /**
-     * RPL_SUMMONING
-     *
-     * "<user> :Summoning user to IRC"
-     *
-     * Returned by a server answering a SUMMON message to
-     * indicate that it is summoning that user.
-     */
-    summoning = 342,
+	/**
+	 * RPL_SUMMONING
+	 *
+	 * "<user> :Summoning user to IRC"
+	 *
+	 * Returned by a server answering a SUMMON message to
+	 * indicate that it is summoning that user.
+	 */
+	summoning = 342,
 
-    /**
-     * RPL_VERSION
-     *
-     * "<version>.<debuglevel> <server> :<comments>"
-     *
-     * Reply by the server showing its version details.
-     * The <version> is the version of the software being
-     * used (including any patchlevel revisions) and the
-     * <debuglevel> is used to indicate if the server is
-     * running in "debug mode".
-     *
-     * The "comments" field may contain any comments about
-     * the version or further version details.
-     */
-    version = 351,
+	/**
+	 * RPL_VERSION
+	 *
+	 * "<version>.<debuglevel> <server> :<comments>"
+	 *
+	 * Reply by the server showing its version details.
+	 * The <version> is the version of the software being
+	 * used (including any patchlevel revisions) and the
+	 * <debuglevel> is used to indicate if the server is
+	 * running in "debug mode".
+	 *
+	 * The "comments" field may contain any comments about
+	 * the version or further version details.
+	 */
+	version = 351,
 
-    /**
-     * RPL_WHOREPLY
-     *
-     * "<channel> <user> <host> <server> <nick> \
-     *  <H|G>[*][@|+] :<hopcount> <real name>"
-     */
-    whoreply = 352,
+	/**
+	 * RPL_WHOREPLY
+	 *
+	 * "<channel> <user> <host> <server> <nick> \
+	 *  <H|G>[*][@|+] :<hopcount> <real name>"
+	 */
+	whoreply = 352,
 
-    /**
-     * RPL_ENDOFWHO
-     *
-     * "<name> :End of /WHO list"
-     *
-     * The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
-     * to answer a WHO message.  The RPL_WHOREPLY is only
-     * sent if there is an appropriate match to the WHO
-     * query.  If there is a list of parameters supplied
-     * with a WHO message, a RPL_ENDOFWHO must be sent
-     * after processing each list item with <name> being
-     * the item.
-     */
-    endofwho = 315,
+	/**
+	 * RPL_ENDOFWHO
+	 *
+	 * "<name> :End of /WHO list"
+	 *
+	 * The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+	 * to answer a WHO message.  The RPL_WHOREPLY is only
+	 * sent if there is an appropriate match to the WHO
+	 * query.  If there is a list of parameters supplied
+	 * with a WHO message, a RPL_ENDOFWHO must be sent
+	 * after processing each list item with <name> being
+	 * the item.
+	 */
+	endofwho = 315,
 
-    /**
-     * RPL_NAMREPLY
-     *
-     * "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
-     */
-    namreply = 353,
+	/**
+	 * RPL_NAMREPLY
+	 *
+	 * "<channel> :[[@|+]<nick> [[@|+]<nick> [...]]]"
+	 */
+	namreply = 353,
 
-    /**
-     * RPL_ENDOFNAMES
-     *
-     * "<channel> :End of /NAMES list"
-     *
-     * To reply to a NAMES message, a reply pair consisting
-     * of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
-     * server back to the client.  If there is no channel
-     * found as in the query, then only RPL_ENDOFNAMES is
-     * returned.  The exception to this is when a NAMES
-     * message is sent with no parameters and all visible
-     * channels and contents are sent back in a series of
-     * RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
-     * the end.
-     */
-    endofnames = 366,
+	/**
+	 * RPL_ENDOFNAMES
+	 *
+	 * "<channel> :End of /NAMES list"
+	 *
+	 * To reply to a NAMES message, a reply pair consisting
+	 * of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+	 * server back to the client.  If there is no channel
+	 * found as in the query, then only RPL_ENDOFNAMES is
+	 * returned.  The exception to this is when a NAMES
+	 * message is sent with no parameters and all visible
+	 * channels and contents are sent back in a series of
+	 * RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+	 * the end.
+	 */
+	endofnames = 366,
 
-    /**
-     * RPL_LINKS
-     *
-     * "<mask> <server> :<hopcount> <server info>"
-     */
-    links = 364,
+	/**
+	 * RPL_LINKS
+	 *
+	 * "<mask> <server> :<hopcount> <server info>"
+	 */
+	links = 364,
 
-    /**
-     * RPL_ENDOFLINKS
-     *
-     * "<mask> :End of /LINKS list"
-     *
-     * In replying to the LINKS message, a server must send
-     * replies back using the RPL_LINKS numeric and mark the
-     * end of the list using an RPL_ENDOFLINKS reply.
-     */
-    endoflinks = 365,
+	/**
+	 * RPL_ENDOFLINKS
+	 *
+	 * "<mask> :End of /LINKS list"
+	 *
+	 * In replying to the LINKS message, a server must send
+	 * replies back using the RPL_LINKS numeric and mark the
+	 * end of the list using an RPL_ENDOFLINKS reply.
+	 */
+	endoflinks = 365,
 
-    /**
-     * RPL_BANLIST
-     *
-     * "<channel> <banid>"
-     */
-    banlist = 367,
+	/**
+	 * RPL_BANLIST
+	 *
+	 * "<channel> <banid>"
+	 */
+	banlist = 367,
 
-    /**
-     * RPL_ENDOFBANLIST
-     *
-     * "<channel> :End of channel ban list"
-     *
-     * When listing the active 'bans' for a given channel,
-     * a server is required to send the list back using the
-     * RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
-     * RPL_BANLIST is sent for each active banid.  After the
-     * banids have been listed (or if none present) a
-     * RPL_ENDOFBANLIST must be sent.
-     */
-    endofbanlist = 368,
+	/**
+	 * RPL_ENDOFBANLIST
+	 *
+	 * "<channel> :End of channel ban list"
+	 *
+	 * When listing the active 'bans' for a given channel,
+	 * a server is required to send the list back using the
+	 * RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
+	 * RPL_BANLIST is sent for each active banid.  After the
+	 * banids have been listed (or if none present) a
+	 * RPL_ENDOFBANLIST must be sent.
+	 */
+	endofbanlist = 368,
 
-    /**
-     * RPL_INFO
-     *
-     * ":<string>"
-     */
-    info = 371,
+	/**
+	 * RPL_INFO
+	 *
+	 * ":<string>"
+	 */
+	info = 371,
 
-    /**
-     * RPL_ENDOFINFO
-     *
-     * ":End of /INFO list"
-     *
-     * A server responding to an INFO message is required to
-     * send all its 'info' in a series of RPL_INFO messages
-     * with a RPL_ENDOFINFO reply to indicate the end of the
-     * replies.
-     */
-    endofinfo = 374,
+	/**
+	 * RPL_ENDOFINFO
+	 *
+	 * ":End of /INFO list"
+	 *
+	 * A server responding to an INFO message is required to
+	 * send all its 'info' in a series of RPL_INFO messages
+	 * with a RPL_ENDOFINFO reply to indicate the end of the
+	 * replies.
+	 */
+	endofinfo = 374,
 
-    /**
-     * RPL_MOTDSTART
-     *
-     * ":- <server> Message of the day - "
-     */
-    motdstart = 375,
+	/**
+	 * RPL_MOTDSTART
+	 *
+	 * ":- <server> Message of the day - "
+	 */
+	motdstart = 375,
 
-    /**
-     * RPL_MOTD
-     *
-     * ":- <text>"
-     */
-    motd = 372,
+	/**
+	 * RPL_MOTD
+	 *
+	 * ":- <text>"
+	 */
+	motd = 372,
 
-    /**
-     * RPL_ENDOFMOTD
-     *
-     * ":End of /MOTD command"
-     *
-     * When responding to the MOTD message and the MOTD file
-     * is found, the file is displayed line by line, with
-     * each line no longer than 80 characters, using
-     * RPL_MOTD format replies.  These should be surrounded
-     * by a RPL_MOTDSTART (before the RPL_MOTDs) and an
-     * RPL_ENDOFMOTD (after).
-     */
-    endofmotd = 376,
+	/**
+	 * RPL_ENDOFMOTD
+	 *
+	 * ":End of /MOTD command"
+	 *
+	 * When responding to the MOTD message and the MOTD file
+	 * is found, the file is displayed line by line, with
+	 * each line no longer than 80 characters, using
+	 * RPL_MOTD format replies.  These should be surrounded
+	 * by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+	 * RPL_ENDOFMOTD (after).
+	 */
+	endofmotd = 376,
 
-    /**
-     * RPL_YOUREOPER
-     *
-     * ":You are now an IRC operator"
-     *
-     * RPL_YOUREOPER is sent back to a client which has
-     * just successfully issued an OPER message and gained
-     * operator status.
-     */
-    youreoper = 381,
+	/**
+	 * RPL_YOUREOPER
+	 *
+	 * ":You are now an IRC operator"
+	 *
+	 * RPL_YOUREOPER is sent back to a client which has
+	 * just successfully issued an OPER message and gained
+	 * operator status.
+	 */
+	youreoper = 381,
 
-    /**
-     * RPL_REHASHING
-     *
-     * "<config file> :Rehashing"
-     *
-     * If the REHASH option is used and an operator sends
-     * a REHASH message, an RPL_REHASHING is sent back to
-     * the operator.
-     */
-    rehashing = 382,
+	/**
+	 * RPL_REHASHING
+	 *
+	 * "<config file> :Rehashing"
+	 *
+	 * If the REHASH option is used and an operator sends
+	 * a REHASH message, an RPL_REHASHING is sent back to
+	 * the operator.
+	 */
+	rehashing = 382,
 
-    /**
-     * RPL_TIME
-     *
-     * "<server> :<string showing server's local time>"
-     *
-     * When replying to the TIME message, a server must send
-     * the reply using the RPL_TIME format above.  The string
-     * showing the time need only contain the correct day and
-     * time there.  There is no further requirement for the
-     * time string.
-     */
-    time = 391,
+	/**
+	 * RPL_TIME
+	 *
+	 * "<server> :<string showing server's local time>"
+	 *
+	 * When replying to the TIME message, a server must send
+	 * the reply using the RPL_TIME format above.  The string
+	 * showing the time need only contain the correct day and
+	 * time there.  There is no further requirement for the
+	 * time string.
+	 */
+	time = 391,
 
-    /**
-     * RPL_USERSSTART
-     *
-     * ":UserID   Terminal  Host"
-     */
-    userstart = 392,
+	/**
+	 * RPL_USERSSTART
+	 *
+	 * ":UserID   Terminal  Host"
+	 */
+	userstart = 392,
 
-    /**
-     * RPL_USERS
-     *
-     * ":%-8s %-9s %-8s"
-     */
-    users = 393,
+	/**
+	 * RPL_USERS
+	 *
+	 * ":%-8s %-9s %-8s"
+	 */
+	users = 393,
 
-    /**
-     * RPL_ENDOFUSERS
-     *
-     * ":End of users"
-     */
-    endofusers = 394,
+	/**
+	 * RPL_ENDOFUSERS
+	 *
+	 * ":End of users"
+	 */
+	endofusers = 394,
 
-    /**
-     * RPL_NOUSERS
-     *
-     * ":Nobody logged in"
-     *
-     * If the USERS message is handled by a server, the
-     * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
-     * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
-     * first, following by either a sequence of RPL_USERS
-     * or a single RPL_NOUSER.  Following this is
-     * RPL_ENDOFUSERS.
-     */
-    nousers = 395,
+	/**
+	 * RPL_NOUSERS
+	 *
+	 * ":Nobody logged in"
+	 *
+	 * If the USERS message is handled by a server, the
+	 * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+	 * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+	 * first, following by either a sequence of RPL_USERS
+	 * or a single RPL_NOUSER.  Following this is
+	 * RPL_ENDOFUSERS.
+	 */
+	nousers = 395,
 
-    /**
-     * RPL_TRACELINK
-     *
-     * "Link <version & debug level> <destination> <next server>"
-     */
-    tracelink = 200,
+	/**
+	 * RPL_TRACELINK
+	 *
+	 * "Link <version & debug level> <destination> <next server>"
+	 */
+	tracelink = 200,
 
-    /**
-     * RPL_TRACECONNECTING
-     *
-     * "Try. <class> <server>"
-     */
-    traceconnecting = 201,
+	/**
+	 * RPL_TRACECONNECTING
+	 *
+	 * "Try. <class> <server>"
+	 */
+	traceconnecting = 201,
 
-    /**
-     * RPL_TRACEHANDSHAKE
-     *
-     * "H.S. <class> <server>"
-     */
-    tracehandshake = 202,
+	/**
+	 * RPL_TRACEHANDSHAKE
+	 *
+	 * "H.S. <class> <server>"
+	 */
+	tracehandshake = 202,
 
-    /**
-     * RPL_TRACEUNKNOWN
-     *
-     * "???? <class> [<client IP address in dot form>]"
-     */
-    traceunknown = 203,
+	/**
+	 * RPL_TRACEUNKNOWN
+	 *
+	 * "???? <class> [<client IP address in dot form>]"
+	 */
+	traceunknown = 203,
 
-    /**
-     * RPL_TRACEOPERATOR
-     *
-     * "Oper <class> <nick>"
-     */
-    traceoperator = 204,
+	/**
+	 * RPL_TRACEOPERATOR
+	 *
+	 * "Oper <class> <nick>"
+	 */
+	traceoperator = 204,
 
-    /**
-     * RPL_TRACEUSER
-     *
-     * "User <class> <nick>"
-     */
-    traceuser = 205,
+	/**
+	 * RPL_TRACEUSER
+	 *
+	 * "User <class> <nick>"
+	 */
+	traceuser = 205,
 
-    /**
-     * RPL_TRACESERVER
-     *
-     * "Serv <class> <int>S <int>C <server> \
-     *  <nick!user|*!*>@<host|server>
-     */
-    traceserver = 206,
+	/**
+	 * RPL_TRACESERVER
+	 *
+	 * "Serv <class> <int>S <int>C <server> \
+	 *  <nick!user|*!*>@<host|server>
+	 */
+	traceserver = 206,
 
-    /**
-     * RPL_TRACENEWTYPE
-     *
-     * "<newtype> 0 <client name>"
-     */
-    tracenewtype = 208,
+	/**
+	 * RPL_TRACENEWTYPE
+	 *
+	 * "<newtype> 0 <client name>"
+	 */
+	tracenewtype = 208,
 
-    /**
-     * RPL_TRACELOG
-     *
-     * "File <logfile> <debug level>"
-     *
-     * The RPL_TRACE* are all returned by the server in
-     * response to the TRACE message.  How many are
-     * returned is dependent on the the TRACE message and
-     * whether it was sent by an operator or not.  There
-     * is no predefined order for which occurs first.
-     * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
-     * RPL_TRACEHANDSHAKE are all used for connections
-     * which have not been fully established and are either
-     * unknown, still attempting to connect or in the
-     * process of completing the 'server handshake'.
-     * RPL_TRACELINK is sent by any server which handles
-     * a TRACE message and has to pass it on to another
-     * server.  The list of RPL_TRACELINKs sent in
-     * response to a TRACE command traversing the IRC
-     * network should reflect the actual connectivity of
-     * the servers themselves along that path.
-     * RPL_TRACENEWTYPE is to be used for any connection
-     * which does not fit in the other categories but is
-     * being displayed anyway.
-     */
-    tracelog = 261,
+	/**
+	 * RPL_TRACELOG
+	 *
+	 * "File <logfile> <debug level>"
+	 *
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	tracelog = 261,
 
-    /**
-     * RPL_STATSLINKINFO
-     *
-     * "<linkname> <sendq> <sent messages> \
-     *  <sent bytes> <received messages> \
-     *  <received bytes> <time open>"
-     */
-    statslinkinfo = 211,
+	/**
+	 * RPL_STATSLINKINFO
+	 *
+	 * "<linkname> <sendq> <sent messages> \
+	 *  <sent bytes> <received messages> \
+	 *  <received bytes> <time open>"
+	 */
+	statslinkinfo = 211,
 
-    /**
-     * RPL_STATSCOMMANDS
-     *
-     * "<command> <count>"
-     */
-    statscommands = 212,
+	/**
+	 * RPL_STATSCOMMANDS
+	 *
+	 * "<command> <count>"
+	 */
+	statscommands = 212,
 
-    /**
-     * RPL_STATSCLINE
-     *
-     * "C <host> * <name> <port> <class>"
-     */
-    statscline = 213,
+	/**
+	 * RPL_STATSCLINE
+	 *
+	 * "C <host> * <name> <port> <class>"
+	 */
+	statscline = 213,
 
-    /**
-     * RPL_STATSNLINE
-     *
-     * "N <host> * <name> <port> <class>"
-     */
-    statsnline = 214,
+	/**
+	 * RPL_STATSNLINE
+	 *
+	 * "N <host> * <name> <port> <class>"
+	 */
+	statsnline = 214,
 
-    /**
-     * RPL_STATSILINE
-     *
-     * "I <host> * <host> <port> <class>"
-     */
-    statsiline = 215,
+	/**
+	 * RPL_STATSILINE
+	 *
+	 * "I <host> * <host> <port> <class>"
+	 */
+	statsiline = 215,
 
-    /**
-     * RPL_STATSKLINE
-     *
-     * K <host> * <username> <port> <class>"
-     */
-    statskline = 216,
+	/**
+	 * RPL_STATSKLINE
+	 *
+	 * K <host> * <username> <port> <class>"
+	 */
+	statskline = 216,
 
-    /**
-     * RPL_STATSYLINE
-     *
-     * "Y <class> <ping frequency> <connect frequency> <max sendq>"
-     */
-    statsyline = 218,
+	/**
+	 * RPL_STATSYLINE
+	 *
+	 * "Y <class> <ping frequency> <connect frequency> <max sendq>"
+	 */
+	statsyline = 218,
 
-    /**
-     * RPL_ENDOFSTATS
-     *
-     * "<stats letter> :End of /STATS report"
-     */
-    endofstats = 219,
+	/**
+	 * RPL_ENDOFSTATS
+	 *
+	 * "<stats letter> :End of /STATS report"
+	 */
+	endofstats = 219,
 
-    /**
-     * RPL_STATSLLINE
-     *
-     * "L <hostmask> * <servername> <maxdepth>"
-     */
-    statslline = 241,
+	/**
+	 * RPL_STATSLLINE
+	 *
+	 * "L <hostmask> * <servername> <maxdepth>"
+	 */
+	statslline = 241,
 
-    /**
-     * RPL_STATSUPTIME
-     *
-     * ":Server Up %d days %d:%02d:%02d"
-     */
-    statsuptime = 242,
+	/**
+	 * RPL_STATSUPTIME
+	 *
+	 * ":Server Up %d days %d:%02d:%02d"
+	 */
+	statsuptime = 242,
 
-    /**
-     * RPL_STATSOLINE
-     *
-     * "O <hostmask> * <name>"
-     */
-    statsoline = 243,
+	/**
+	 * RPL_STATSOLINE
+	 *
+	 * "O <hostmask> * <name>"
+	 */
+	statsoline = 243,
 
-    /**
-     * RPL_STATSHLINE
-     *
-     * "H <hostmask> * <servername>"
-     */
-    statshline = 244,
+	/**
+	 * RPL_STATSHLINE
+	 *
+	 * "H <hostmask> * <servername>"
+	 */
+	statshline = 244,
 
-    /**
-     * RPL_UMODEIS
-     *
-     * "<user mode string>"
-     *
-     * To answer a query about a client's own mode,
-     * RPL_UMODEIS is sent back.
-     */
-    umodeis = 221,
+	/**
+	 * RPL_UMODEIS
+	 *
+	 * "<user mode string>"
+	 *
+	 * To answer a query about a client's own mode,
+	 * RPL_UMODEIS is sent back.
+	 */
+	umodeis = 221,
 
-    /**
-     * RPL_LUSERCLIENT
-     *
-     * ":There are <integer> users and <integer> \
-     *  invisible on <integer> servers"
-     */
-    luserclient = 251,
+	/**
+	 * RPL_LUSERCLIENT
+	 *
+	 * ":There are <integer> users and <integer> \
+	 *  invisible on <integer> servers"
+	 */
+	luserclient = 251,
 
-    /**
-     * RPL_LUSEROP
-     *
-     * "<integer> :operator(s) online"
-     */
-    luserop = 252,
+	/**
+	 * RPL_LUSEROP
+	 *
+	 * "<integer> :operator(s) online"
+	 */
+	luserop = 252,
 
-    /**
-     * RPL_LUSERUNKNOWN
-     *
-     * "<integer> :unknown connection(s)"
-     */
-    luserunknown = 253,
+	/**
+	 * RPL_LUSERUNKNOWN
+	 *
+	 * "<integer> :unknown connection(s)"
+	 */
+	luserunknown = 253,
 
-    /**
-     * RPL_LUSERCHANNELS
-     *
-     * "<integer> :channels formed"
-     */
-    luserchannels = 254,
+	/**
+	 * RPL_LUSERCHANNELS
+	 *
+	 * "<integer> :channels formed"
+	 */
+	luserchannels = 254,
 
-    /**
-     * RPL_LUSERME
-     *
-     * ":I have <integer> clients and <integer> servers"
-     *
-     * In processing an LUSERS message, the server
-     * sends a set of replies from RPL_LUSERCLIENT,
-     * RPL_LUSEROP, RPL_USERUNKNOWN,
-     * RPL_LUSERCHANNELS and RPL_LUSERME.  When
-     * replying, a server must send back
-     * RPL_LUSERCLIENT and RPL_LUSERME.  The other
-     * replies are only sent back if a non-zero count
-     * is found for them.
-     */
-    luserme = 255,
+	/**
+	 * RPL_LUSERME
+	 *
+	 * ":I have <integer> clients and <integer> servers"
+	 *
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	luserme = 255,
 
-    /**
-     * RPL_ADMINME
-     *
-     * "<server> :Administrative info"
-     */
-    adminme = 256,
+	/**
+	 * RPL_ADMINME
+	 *
+	 * "<server> :Administrative info"
+	 */
+	adminme = 256,
 
-    /**
-     * RPL_ADMINLOC1
-     *
-     * ":<admin info>"
-     */
-    adminloc1 = 257,
+	/**
+	 * RPL_ADMINLOC1
+	 *
+	 * ":<admin info>"
+	 */
+	adminloc1 = 257,
 
-    /**
-     * RPL_ADMINLOC2
-     *
-     * ":<admin info>"
-     */
-    adminloc2 = 258,
+	/**
+	 * RPL_ADMINLOC2
+	 *
+	 * ":<admin info>"
+	 */
+	adminloc2 = 258,
 
-    /**
-     * RPL_ADMINEMAIL
-     *
-     * ":<admin info>"
-     *
-     * When replying to an ADMIN message, a server
-     * is expected to use replies RLP_ADMINME
-     * through to RPL_ADMINEMAIL and provide a text
-     * message with each.  For RPL_ADMINLOC1 a
-     * description of what city, state and country
-     * the server is in is expected, followed by
-     * details of the university and department
-     * (RPL_ADMINLOC2) and finally the administrative
-     * contact for the server (an email address here
-     * is required) in RPL_ADMINEMAIL.
-     */
-    adminemail = 259
+	/**
+	 * RPL_ADMINEMAIL
+	 *
+	 * ":<admin info>"
+	 *
+	 * When replying to an ADMIN message, a server
+	 * is expected to use replies RLP_ADMINME
+	 * through to RPL_ADMINEMAIL and provide a text
+	 * message with each.  For RPL_ADMINLOC1 a
+	 * description of what city, state and country
+	 * the server is in is expected, followed by
+	 * details of the university and department
+	 * (RPL_ADMINLOC2) and finally the administrative
+	 * contact for the server (an email address here
+	 * is required) in RPL_ADMINEMAIL.
+	 */
+	adminemail = 259
 };
 
 /**
  * \brief Describe a IRC message
  */
 struct message {
-    std::string prefix;             //!< optional prefix
-    std::string command;            //!< command (maybe string or code)
-    std::vector<std::string> args;  //!< parameters
+	std::string prefix;			 //!< optional prefix
+	std::string command;			//!< command (maybe string or code)
+	std::vector<std::string> args;  //!< parameters
 
-    /**
-     * Check if the command is of the given enum number.
-     *
-     * \return true if command is a number and equals to e
-     */
-    template <typename Enum>
-    auto is(Enum e) const noexcept -> bool
-    {
-        try {
-            return std::stoi(command) == static_cast<int>(e);
-        } catch (...) {
-            return false;
-        }
-    }
+	/**
+	 * Check if the command is of the given enum number.
+	 *
+	 * \return true if command is a number and equals to e
+	 */
+	template <typename Enum>
+	auto is(Enum e) const noexcept -> bool
+	{
+		try {
+			return std::stoi(command) == static_cast<int>(e);
+		} catch (...) {
+			return false;
+		}
+	}
 
-    /**
-     * Convenient function that returns an empty string if the nth argument is
-     * not defined.
-     *
-     * \param index the index
-     * \return a string or empty if out of bounds
-     */
-    auto get(unsigned short index) const noexcept -> const std::string&;
+	/**
+	 * Convenient function that returns an empty string if the nth argument is
+	 * not defined.
+	 *
+	 * \param index the index
+	 * \return a string or empty if out of bounds
+	 */
+	auto get(unsigned short index) const noexcept -> const std::string&;
 
-    /**
-     * Tells if the message is a CTCP.
-     *
-     * \param index the param index (maybe out of bounds)
-     * \return true if CTCP
-     */
-    auto is_ctcp(unsigned index) const noexcept -> bool;
+	/**
+	 * Tells if the message is a CTCP.
+	 *
+	 * \param index the param index (maybe out of bounds)
+	 * \return true if CTCP
+	 */
+	auto is_ctcp(unsigned index) const noexcept -> bool;
 
-    /**
-     * Parse a CTCP message.
-     *
-     * \pre is_ctcp(index)
-     * \param index the param index
-     * \return the CTCP command
-     */
-    auto ctcp(unsigned index) const -> std::string;
+	/**
+	 * Parse a CTCP message.
+	 *
+	 * \pre is_ctcp(index)
+	 * \param index the param index
+	 * \return the CTCP command
+	 */
+	auto ctcp(unsigned index) const -> std::string;
 
-    /**
-     * Parse a IRC message.
-     *
-     * \param line the buffer content (without `\r\n`)
-     * \return the message (maybe empty if line is empty)
-     */
-    static auto parse(const std::string& line) -> message;
+	/**
+	 * Parse a IRC message.
+	 *
+	 * \param line the buffer content (without `\r\n`)
+	 * \return the message (maybe empty if line is empty)
+	 */
+	static auto parse(const std::string& line) -> message;
 };
 
 /**
  * \brief Describe a user.
  */
 struct user {
-    std::string nick;
-    std::string host;
+	std::string nick;
+	std::string host;
 
-    /**
-     * Parse a nick/host combination.
-     *
-     * \param line the line to parse
-     * \return a user
-     */
-    static auto parse(std::string_view line) -> user;
+	/**
+	 * Parse a nick/host combination.
+	 *
+	 * \param line the line to parse
+	 * \return a user
+	 */
+	static auto parse(std::string_view line) -> user;
 };
 
 /**
@@ -1270,144 +1270,144 @@
  */
 class connection {
 public:
-    /**
-     * Handler for connecting.
-     */
-    using connect_handler = std::function<void (std::error_code)>;
+	/**
+	 * Handler for connecting.
+	 */
+	using connect_handler = std::function<void (std::error_code)>;
 
-    /**
-     * Handler for receiving.
-     */
-    using recv_handler = std::function<void (std::error_code, message)>;
+	/**
+	 * Handler for receiving.
+	 */
+	using recv_handler = std::function<void (std::error_code, message)>;
 
-    /**
-     * Handler for sending.
-     */
-    using send_handler = std::function<void (std::error_code)>;
+	/**
+	 * Handler for sending.
+	 */
+	using send_handler = std::function<void (std::error_code)>;
 
 private:
-    boost::asio::ip::tcp::resolver resolver_;
-    boost::asio::streambuf input_;
-    boost::asio::streambuf output_;
+	boost::asio::ip::tcp::resolver resolver_;
+	boost::asio::streambuf input_;
+	boost::asio::streambuf output_;
 
 #if !defined(NDEBUG)
-    bool is_connecting_{false};
-    bool is_receiving_{false};
-    bool is_sending_{false};
+	bool is_connecting_{false};
+	bool is_receiving_{false};
+	bool is_sending_{false};
 #endif
 
 protected:
-    /**
-     * Use boost::asio::async_resolve and boost::asio::async_connect on the
-     * given real socket type.
-     *
-     * \param socket the socket
-     * \param host the hostname
-     * \param service the service or port number
-     * \param handler the non-null handler
-     */
-    template <typename Socket>
-    void wrap_connect(Socket& socket,
-                      const std::string& host,
-                      const std::string& service,
-                      const connect_handler& handler) noexcept;
+	/**
+	 * Use boost::asio::async_resolve and boost::asio::async_connect on the
+	 * given real socket type.
+	 *
+	 * \param socket the socket
+	 * \param host the hostname
+	 * \param service the service or port number
+	 * \param handler the non-null handler
+	 */
+	template <typename Socket>
+	void wrap_connect(Socket& socket,
+	                  const std::string& host,
+	                  const std::string& service,
+	                  const connect_handler& handler) noexcept;
 
-    /**
-     * Use boost::asio::asynd_read_until on the given real socket type.
-     *
-     * \param socket the socket
-     * \param handler the non-null handler
-     */
-    template <typename Socket>
-    void wrap_recv(Socket& socket, const recv_handler& handler) noexcept;
+	/**
+	 * Use boost::asio::asynd_read_until on the given real socket type.
+	 *
+	 * \param socket the socket
+	 * \param handler the non-null handler
+	 */
+	template <typename Socket>
+	void wrap_recv(Socket& socket, const recv_handler& handler) noexcept;
 
-    /**
-     * Use boost::asio::asynd_write on the given real socket type.
-     *
-     * \param socket the socket
-     * \param handler the non-null handler
-     */
-    template <typename Socket>
-    void wrap_send(Socket& socket, const send_handler& handler) noexcept;
+	/**
+	 * Use boost::asio::asynd_write on the given real socket type.
+	 *
+	 * \param socket the socket
+	 * \param handler the non-null handler
+	 */
+	template <typename Socket>
+	void wrap_send(Socket& socket, const send_handler& handler) noexcept;
 
-    /**
-     * Do the connection.
-     *
-     * Derived implementation may call wrap_connect on its underlying socket.
-     *
-     * \param host the hostname
-     * \param service the service or port number
-     * \param handler the non-null handler
-     */
-    virtual void do_connect(const std::string& host,
-                            const std::string& service,
-                            const connect_handler& handler) noexcept = 0;
+	/**
+	 * Do the connection.
+	 *
+	 * Derived implementation may call wrap_connect on its underlying socket.
+	 *
+	 * \param host the hostname
+	 * \param service the service or port number
+	 * \param handler the non-null handler
+	 */
+	virtual void do_connect(const std::string& host,
+	                        const std::string& service,
+	                        const connect_handler& handler) noexcept = 0;
 
-    /**
-     * Receive some data.
-     *
-     * \param handler the non-null handler
-     */
-    virtual void do_recv(const recv_handler& handler) noexcept = 0;
+	/**
+	 * Receive some data.
+	 *
+	 * \param handler the non-null handler
+	 */
+	virtual void do_recv(const recv_handler& handler) noexcept = 0;
 
-    /**
-     * Send data.
-     *
-     * \param handler the non-null handler
-     */
-    virtual void do_send(const send_handler& handler) noexcept = 0;
+	/**
+	 * Send data.
+	 *
+	 * \param handler the non-null handler
+	 */
+	virtual void do_send(const send_handler& handler) noexcept = 0;
 
 public:
-    /**
-     * Default constructor.
-     */
-    inline connection(boost::asio::io_service& service)
-        : resolver_(service)
-    {
-    }
+	/**
+	 * Default constructor.
+	 */
+	inline connection(boost::asio::io_service& service)
+		: resolver_(service)
+	{
+	}
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~connection() = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~connection() = default;
 
-    /**
-     * Connect to the host.
-     *
-     * \pre handler the handler
-     * \pre another connect operation must not be running
-     * \param host the host
-     * \param service the service or port number
-     * \param handler the non-null handler
-     */
-    void connect(const std::string& host,
-                 const std::string& service,
-                 const connect_handler& handler) noexcept;
+	/**
+	 * Connect to the host.
+	 *
+	 * \pre handler the handler
+	 * \pre another connect operation must not be running
+	 * \param host the host
+	 * \param service the service or port number
+	 * \param handler the non-null handler
+	 */
+	void connect(const std::string& host,
+				 const std::string& service,
+				 const connect_handler& handler) noexcept;
 
-    /**
-     * Start receiving data.
-     *
-     * The handler must not throw exceptions and `this` must be valid in the
-     * lifetime of the handler.
-     *
-     * \pre another recv operation must not be running
-     * \pre handler != nullptr
-     * \param handler the handler to call
-     */
-    void recv(const recv_handler& handler) noexcept;
+	/**
+	 * Start receiving data.
+	 *
+	 * The handler must not throw exceptions and `this` must be valid in the
+	 * lifetime of the handler.
+	 *
+	 * \pre another recv operation must not be running
+	 * \pre handler != nullptr
+	 * \param handler the handler to call
+	 */
+	void recv(const recv_handler& handler) noexcept;
 
-    /**
-     * Start sending data.
-     *
-     * The handler must not throw exceptions and `this` must be valid in the
-     * lifetime of the handler.
-     *
-     * \pre another send operation must not be running
-     * \pre handler != nullptr
-     * \param message the raw message
-     * \param handler the handler to call
-     */
-    void send(std::string message, const send_handler& handler);
+	/**
+	 * Start sending data.
+	 *
+	 * The handler must not throw exceptions and `this` must be valid in the
+	 * lifetime of the handler.
+	 *
+	 * \pre another send operation must not be running
+	 * \pre handler != nullptr
+	 * \param message the raw message
+	 * \param handler the handler to call
+	 */
+	void send(std::string message, const send_handler& handler);
 };
 
 /**
@@ -1415,37 +1415,37 @@
  */
 class ip_connection : public connection {
 private:
-    boost::asio::ip::tcp::socket socket_;
+	boost::asio::ip::tcp::socket socket_;
 
 protected:
-    /**
-     * \copydoc connection::do_connect
-     */
-    void do_connect(const std::string& host,
-                    const std::string& service,
-                    const connect_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_connect
+	 */
+	void do_connect(const std::string& host,
+	                const std::string& service,
+	                const connect_handler& handler) noexcept override;
 
-    /**
-     * \copydoc connection::do_recv
-     */
-    void do_recv(const recv_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_recv
+	 */
+	void do_recv(const recv_handler& handler) noexcept override;
 
-    /**
-     * \copydoc connection::do_send
-     */
-    void do_send(const send_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_send
+	 */
+	void do_send(const send_handler& handler) noexcept override;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param service the io service
-     */
-    inline ip_connection(boost::asio::io_service& service)
-        : connection(service)
-        , socket_(service)
-    {
-    }
+	/**
+	 * Constructor.
+	 *
+	 * \param service the io service
+	 */
+	inline ip_connection(boost::asio::io_service& service)
+		: connection(service)
+		, socket_(service)
+	{
+	}
 };
 
 #if defined(IRCCD_HAVE_SSL)
@@ -1455,39 +1455,39 @@
  */
 class tls_connection : public connection {
 private:
-    boost::asio::ssl::context context_;
-    boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
+	boost::asio::ssl::context context_;
+	boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
 
 protected:
-    /**
-     * \copydoc connection::do_connect
-     */
-    void do_connect(const std::string& host,
-                    const std::string& service,
-                    const connect_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_connect
+	 */
+	void do_connect(const std::string& host,
+	                const std::string& service,
+	                const connect_handler& handler) noexcept override;
 
-    /**
-     * \copydoc connection::do_recv
-     */
-    void do_recv(const recv_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_recv
+	 */
+	void do_recv(const recv_handler& handler) noexcept override;
 
-    /**
-     * \copydoc connection::do_send
-     */
-    void do_send(const send_handler& handler) noexcept override;
+	/**
+	 * \copydoc connection::do_send
+	 */
+	void do_send(const send_handler& handler) noexcept override;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param service the io service
-     */
-    inline tls_connection(boost::asio::io_service& service)
-        : connection(service)
-        , context_(boost::asio::ssl::context::sslv23)
-        , socket_(service, context_)
-    {
-    }
+	/**
+	 * Constructor.
+	 *
+	 * \param service the io service
+	 */
+	inline tls_connection(boost::asio::io_service& service)
+		: connection(service)
+		, context_(boost::asio::ssl::context::sslv23)
+		, socket_(service, context_)
+	{
+	}
 };
 
 #endif // !IRCCD_HAVE_SSL
--- a/libirccd/irccd/daemon/irccd.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/irccd.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,29 +36,29 @@
 
 class format_filter : public logger::filter {
 private:
-    std::string info_;
-    std::string warning_;
-    std::string debug_;
+	std::string info_;
+	std::string warning_;
+	std::string debug_;
 
-    auto convert(const std::string&,
-                 std::string_view,
-                 std::string_view,
-                 std::string_view) const -> std::string;
+	auto convert(const std::string&,
+	             std::string_view,
+	             std::string_view,
+	             std::string_view) const -> std::string;
 
 public:
-    format_filter(std::string info, std::string warning, std::string debug) noexcept;
+	format_filter(std::string info, std::string warning, std::string debug) noexcept;
 
-    auto pre_debug(std::string_view,
-                   std::string_view,
-                   std::string_view) const -> std::string override;
+	auto pre_debug(std::string_view,
+	               std::string_view,
+	               std::string_view) const -> std::string override;
 
-    auto pre_info(std::string_view,
-                  std::string_view,
-                  std::string_view) const -> std::string override;
+	auto pre_info(std::string_view,
+	              std::string_view,
+	              std::string_view) const -> std::string override;
 
-    auto pre_warning(std::string_view,
-                     std::string_view,
-                     std::string_view) const -> std::string override;
+	auto pre_warning(std::string_view,
+	                 std::string_view,
+	                 std::string_view) const -> std::string override;
 };
 
 auto format_filter::convert(const std::string& tmpl,
@@ -66,24 +66,24 @@
                             std::string_view component,
                             std::string_view message) const -> std::string
 {
-    if (tmpl.empty())
-        return pre(category, component, message);
+	if (tmpl.empty())
+		return pre(category, component, message);
 
-    string_util::subst params;
+	string_util::subst params;
 
-    params.flags &= ~(string_util::subst_flags::irc_attrs);
-    params.flags |= string_util::subst_flags::shell_attrs;
-    params.keywords.emplace("category", std::string(category));
-    params.keywords.emplace("component", std::string(component));
-    params.keywords.emplace("message", std::string(message));
+	params.flags &= ~(string_util::subst_flags::irc_attrs);
+	params.flags |= string_util::subst_flags::shell_attrs;
+	params.keywords.emplace("category", std::string(category));
+	params.keywords.emplace("component", std::string(component));
+	params.keywords.emplace("message", std::string(message));
 
-    return string_util::format(tmpl, params);
+	return string_util::format(tmpl, params);
 }
 
 format_filter::format_filter(std::string info, std::string warning, std::string debug) noexcept
-    : info_(std::move(info))
-    , warning_(std::move(warning))
-    , debug_(std::move(debug))
+	: info_(std::move(info))
+	, warning_(std::move(warning))
+	, debug_(std::move(debug))
 {
 }
 
@@ -91,105 +91,105 @@
                               std::string_view component,
                               std::string_view message) const -> std::string
 {
-    return convert(debug_, category, component, message);
+	return convert(debug_, category, component, message);
 }
 
 auto format_filter::pre_info(std::string_view category,
                              std::string_view component,
                              std::string_view message) const -> std::string
 {
-    return convert(info_, category, component, message);
+	return convert(info_, category, component, message);
 }
 
 auto format_filter::pre_warning(std::string_view category,
                                 std::string_view component,
                                 std::string_view message) const -> std::string
 {
-    return convert(warning_, category, component, message);
+	return convert(warning_, category, component, message);
 }
 
 } // !namespace
 
 void irccd::load_logs_file(const ini::section& sc)
 {
-    /*
-     * TODO: improve that with CMake options.
-     */
+	/*
+	 * TODO: improve that with CMake options.
+	 */
 #if BOOST_OS_WINDOWS
-    std::string normal = "log.txt";
-    std::string errors = "errors.txt";
+	std::string normal = "log.txt";
+	std::string errors = "errors.txt";
 #else
-    std::string normal = "/var/log/irccd/log.txt";
-    std::string errors = "/var/log/irccd/errors.txt";
+	std::string normal = "/var/log/irccd/log.txt";
+	std::string errors = "/var/log/irccd/errors.txt";
 #endif
 
-    ini::section::const_iterator it;
+	ini::section::const_iterator it;
 
-    if ((it = sc.find("path-logs")) != sc.end())
-        normal = it->value();
-    if ((it = sc.find("path-errors")) != sc.end())
-        errors = it->value();
+	if ((it = sc.find("path-logs")) != sc.end())
+		normal = it->get_value();
+	if ((it = sc.find("path-errors")) != sc.end())
+		errors = it->get_value();
 
-    try {
-        sink_ = std::make_unique<logger::file_sink>(std::move(normal), std::move(errors));
-    } catch (const std::exception& ex) {
-        sink_->warning("logs", "") << ex.what() << std::endl;
-    }
+	try {
+		sink_ = std::make_unique<logger::file_sink>(std::move(normal), std::move(errors));
+	} catch (const std::exception& ex) {
+		sink_->warning("logs", "") << ex.what() << std::endl;
+	}
 }
 
 void irccd::load_logs_syslog()
 {
 #if defined(IRCCD_HAVE_SYSLOG)
-    sink_ = std::make_unique<logger::syslog_sink>();
+	sink_ = std::make_unique<logger::syslog_sink>();
 #else
-    sink_->warning("logs", "") << "logs: syslog is not available on this platform" << std::endl;
+	sink_->warning("logs", "") << "logs: syslog is not available on this platform" << std::endl;
 #endif // !IRCCD_HAVE_SYSLOG
 }
 
 void irccd::load_logs()
 {
-    const auto sc = config_.get("logs");
+	const auto sc = config_.get("logs");
 
-    if (sc.empty())
-        return;
+	if (sc.empty())
+		return;
 
-    sink_->set_verbose(string_util::is_identifier(sc.get("verbose").value()));
+	sink_->set_verbose(string_util::is_identifier(sc.get("verbose").get_value()));
 
-    const auto type = sc.get("type").value();
+	const auto type = sc.get("type").get_value();
 
-    if (!type.empty()) {
-        // Console is the default, no test case.
-        if (type == "file")
-            load_logs_file(sc);
-        else if (type == "syslog")
-            load_logs_syslog();
-        else if (type != "console")
-            sink_->warning("logs", "") << "invalid log type '" << type << std::endl;
-    }
+	if (!type.empty()) {
+		// Console is the default, no test case.
+		if (type == "file")
+			load_logs_file(sc);
+		else if (type == "syslog")
+			load_logs_syslog();
+		else if (type != "console")
+			sink_->warning("logs", "") << "invalid log type '" << type << std::endl;
+	}
 }
 
 void irccd::load_formats()
 {
-    const auto sc = config_.get("format");
+	const auto sc = config_.get("format");
 
-    if (sc.empty())
-        return;
+	if (sc.empty())
+		return;
 
-    sink_->set_filter(std::make_unique<format_filter>(
-        sc.get("info").value(),
-        sc.get("warning").value(),
-        sc.get("debug").value()
-    ));
+	sink_->set_filter(std::make_unique<format_filter>(
+		sc.get("info").get_value(),
+		sc.get("warning").get_value(),
+		sc.get("debug").get_value()
+	));
 }
 
 irccd::irccd(boost::asio::io_service& service, std::string config)
-    : config_(std::move(config))
-    , service_(service)
-    , sink_(std::make_unique<logger::console_sink>())
-    , server_service_(std::make_unique<server_service>(*this))
-    , tpt_service_(std::make_unique<transport_service>(*this))
-    , rule_service_(std::make_unique<rule_service>(*this))
-    , plugin_service_(std::make_unique<plugin_service>(*this))
+	: config_(std::move(config))
+	, service_(service)
+	, sink_(std::make_unique<logger::console_sink>())
+	, server_service_(std::make_unique<server_service>(*this))
+	, tpt_service_(std::make_unique<transport_service>(*this))
+	, rule_service_(std::make_unique<rule_service>(*this))
+	, plugin_service_(std::make_unique<plugin_service>(*this))
 {
 }
 
@@ -197,128 +197,128 @@
 
 auto irccd::get_config() const noexcept -> const config&
 {
-    return config_;
+	return config_;
 }
 
 void irccd::set_config(config cfg) noexcept
 {
-    config_ = std::move(cfg);
+	config_ = std::move(cfg);
 }
 
 auto irccd::get_service() const noexcept -> const boost::asio::io_service&
 {
-    return service_;
+	return service_;
 }
 
 auto irccd::get_service() noexcept -> boost::asio::io_service&
 {
-    return service_;
+	return service_;
 }
 
 auto irccd::get_log() const noexcept -> const logger::sink&
 {
-    return *sink_;
+	return *sink_;
 }
 
 auto irccd::get_log() noexcept -> logger::sink&
 {
-    return *sink_;
+	return *sink_;
 }
 
 auto irccd::servers() noexcept -> server_service&
 {
-    return *server_service_;
+	return *server_service_;
 }
 
 auto irccd::transports() noexcept -> transport_service&
 {
-    return *tpt_service_;
+	return *tpt_service_;
 }
 
 auto irccd::rules() noexcept -> rule_service&
 {
-    return *rule_service_;
+	return *rule_service_;
 }
 
 auto irccd::plugins() noexcept -> plugin_service&
 {
-    return *plugin_service_;
+	return *plugin_service_;
 }
 
 void irccd::set_log(std::unique_ptr<logger::sink> sink) noexcept
 {
-    assert(sink);
+	assert(sink);
 
-    sink_ = std::move(sink);
+	sink_ = std::move(sink);
 }
 
 void irccd::load() noexcept
 {
-    /*
-     * Order matters, please be careful when changing this.
-     *
-     * 1. Open logs as early as possible to use the defined outputs on any
-     *    loading errors.
-     */
+	/*
+	 * Order matters, please be careful when changing this.
+	 *
+	 * 1. Open logs as early as possible to use the defined outputs on any
+	 *	loading errors.
+	 */
 
-    // [logs] and [format] sections.
-    load_logs();
-    load_formats();
+	// [logs] and [format] sections.
+	load_logs();
+	load_formats();
 
-    if (!loaded_)
-        sink_->info("irccd", "") << "loading configuration from " << config_.get_path() << std::endl;
-    else
-        sink_->info("irccd", "") << "reloading configuration" << std::endl;
+	if (!loaded_)
+		sink_->info("irccd", "") << "loading configuration from " << config_.get_path() << std::endl;
+	else
+		sink_->info("irccd", "") << "reloading configuration" << std::endl;
 
-    if (!loaded_)
-        tpt_service_->load(config_);
+	if (!loaded_)
+		tpt_service_->load(config_);
 
-    server_service_->load(config_);
-    plugin_service_->load(config_);
-    rule_service_->load(config_);
+	server_service_->load(config_);
+	plugin_service_->load(config_);
+	rule_service_->load(config_);
 
-    // Mark as loaded.
-    loaded_ = true;
+	// Mark as loaded.
+	loaded_ = true;
 }
 
 auto irccd_category() noexcept -> const std::error_category&
 {
-    static const class category : public std::error_category {
-    public:
-        const char* name() const noexcept override
-        {
-            return "irccd";
-        }
+	static const class category : public std::error_category {
+	public:
+		const char* name() const noexcept override
+		{
+			return "irccd";
+		}
 
-        std::string message(int e) const override
-        {
-            switch (static_cast<irccd_error::error>(e)) {
-            case irccd_error::error::not_irccd:
-                return "daemon is not irccd instance";
-            case irccd_error::error::incompatible_version:
-                return "major version is incompatible";
-            case irccd_error::error::auth_required:
-                return "authentication is required";
-            case irccd_error::error::invalid_auth:
-                return "invalid authentication";
-            case irccd_error::error::invalid_message:
-                return "invalid message";
-            case irccd_error::error::invalid_command:
-                return "invalid command";
-            case irccd_error::error::incomplete_message:
-                return "command requires more arguments";
-            default:
-                return "no error";
-            }
-        }
-    } category;
+		std::string message(int e) const override
+		{
+			switch (static_cast<irccd_error::error>(e)) {
+			case irccd_error::error::not_irccd:
+				return "daemon is not irccd instance";
+			case irccd_error::error::incompatible_version:
+				return "major version is incompatible";
+			case irccd_error::error::auth_required:
+				return "authentication is required";
+			case irccd_error::error::invalid_auth:
+				return "invalid authentication";
+			case irccd_error::error::invalid_message:
+				return "invalid message";
+			case irccd_error::error::invalid_command:
+				return "invalid command";
+			case irccd_error::error::incomplete_message:
+				return "command requires more arguments";
+			default:
+				return "no error";
+			}
+		}
+	} category;
 
-    return category;
+	return category;
 }
 
 auto make_error_code(irccd_error::error e) noexcept -> std::error_code
 {
-    return {static_cast<int>(e), irccd_category()};
+	return {static_cast<int>(e), irccd_category()};
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/irccd.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/irccd.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -54,137 +54,137 @@
  */
 class irccd {
 private:
-    // Configuration.
-    config config_;
+	// Configuration.
+	config config_;
 
-    // Main io service.
-    boost::asio::io_service& service_;
+	// Main io service.
+	boost::asio::io_service& service_;
 
-    // Tells if the configuration has already been called.
-    bool loaded_{false};
+	// Tells if the configuration has already been called.
+	bool loaded_{false};
 
-    // Custom logger.
-    std::unique_ptr<logger::sink> sink_;
+	// Custom logger.
+	std::unique_ptr<logger::sink> sink_;
 
-    // Services.
-    std::unique_ptr<server_service> server_service_;
-    std::unique_ptr<transport_service> tpt_service_;
-    std::unique_ptr<rule_service> rule_service_;
-    std::unique_ptr<plugin_service> plugin_service_;
+	// Services.
+	std::unique_ptr<server_service> server_service_;
+	std::unique_ptr<transport_service> tpt_service_;
+	std::unique_ptr<rule_service> rule_service_;
+	std::unique_ptr<plugin_service> plugin_service_;
 
-    // Not copyable and not movable because services have references to irccd.
-    irccd(const irccd&) = delete;
-    irccd(irccd&&) = delete;
+	// Not copyable and not movable because services have references to irccd.
+	irccd(const irccd&) = delete;
+	irccd(irccd&&) = delete;
 
-    void operator=(const irccd&) = delete;
-    void operator=(irccd&&) = delete;
+	void operator=(const irccd&) = delete;
+	void operator=(irccd&&) = delete;
 
-    // Load functions.
-    void load_logs_file(const ini::section&);
-    void load_logs_syslog();
-    void load_logs();
-    void load_formats();
+	// Load functions.
+	void load_logs_file(const ini::section&);
+	void load_logs_syslog();
+	void load_logs();
+	void load_formats();
 
 public:
-    /**
-     * Constructor.
-     *
-     * This only create a barebone irccd instance.
-     *
-     * \param service the service
-     * \param config the optional path to the configuration.
-     * \see load_all
-     * \see load_config
-     */
-    irccd(boost::asio::io_service& service, std::string config = "");
+	/**
+	 * Constructor.
+	 *
+	 * This only create a barebone irccd instance.
+	 *
+	 * \param service the service
+	 * \param config the optional path to the configuration.
+	 * \see load_all
+	 * \see load_config
+	 */
+	irccd(boost::asio::io_service& service, std::string config = "");
 
-    /**
-     * Default destructor.
-     */
-    ~irccd();
+	/**
+	 * Default destructor.
+	 */
+	~irccd();
 
-    /**
-     * Get the current configuration.
-     *
-     * \return the configuration
-     */
-    auto get_config() const noexcept -> const config&;
+	/**
+	 * Get the current configuration.
+	 *
+	 * \return the configuration
+	 */
+	auto get_config() const noexcept -> const config&;
 
-    /**
-     * Set the configuration.
-     *
-     * \param cfg the new config
-     */
-    void set_config(config cfg) noexcept;
+	/**
+	 * Set the configuration.
+	 *
+	 * \param cfg the new config
+	 */
+	void set_config(config cfg) noexcept;
 
-    /**
-     * Get the underlying io service.
-     *
-     * \return the service
-     */
-    auto get_service() const noexcept -> const boost::asio::io_service&;
+	/**
+	 * Get the underlying io service.
+	 *
+	 * \return the service
+	 */
+	auto get_service() const noexcept -> const boost::asio::io_service&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the service
-     */
-    auto get_service() noexcept -> boost::asio::io_service&;
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the service
+	 */
+	auto get_service() noexcept -> boost::asio::io_service&;
 
-    /**
-     * Access the logger.
-     *
-     * \return the logger
-     */
-    auto get_log() const noexcept -> const logger::sink&;
+	/**
+	 * Access the logger.
+	 *
+	 * \return the logger
+	 */
+	auto get_log() const noexcept -> const logger::sink&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the logger
-     */
-    auto get_log() noexcept -> logger::sink&;
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the logger
+	 */
+	auto get_log() noexcept -> logger::sink&;
 
-    /**
-     * Set the logger.
-     *
-     * \pre logger != nullptr
-     * \param logger the new logger
-     */
-    void set_log(std::unique_ptr<logger::sink> sink) noexcept;
+	/**
+	 * Set the logger.
+	 *
+	 * \pre logger != nullptr
+	 * \param logger the new logger
+	 */
+	void set_log(std::unique_ptr<logger::sink> sink) noexcept;
 
-    /**
-     * Access the server service.
-     *
-     * \return the service
-     */
-    auto servers() noexcept -> server_service&;
+	/**
+	 * Access the server service.
+	 *
+	 * \return the service
+	 */
+	auto servers() noexcept -> server_service&;
 
-    /**
-     * Access the transport service.
-     *
-     * \return the service
-     */
-    auto transports() noexcept -> transport_service&;
+	/**
+	 * Access the transport service.
+	 *
+	 * \return the service
+	 */
+	auto transports() noexcept -> transport_service&;
 
-    /**
-     * Access the rule service.
-     *
-     * \return the service
-     */
-    auto rules() noexcept -> rule_service&;
+	/**
+	 * Access the rule service.
+	 *
+	 * \return the service
+	 */
+	auto rules() noexcept -> rule_service&;
 
-    /**
-     * Access the plugin service.
-     *
-     * \return the service
-     */
-    auto plugins() noexcept -> plugin_service&;
+	/**
+	 * Access the plugin service.
+	 *
+	 * \return the service
+	 */
+	auto plugins() noexcept -> plugin_service&;
 
-    /**
-     * Load and re-apply the configuration to the daemon.
-     */
-    void load() noexcept;
+	/**
+	 * Load and re-apply the configuration to the daemon.
+	 */
+	void load() noexcept;
 };
 
 /**
@@ -192,39 +192,39 @@
  */
 class irccd_error : public std::system_error {
 public:
-    /**
-     * \brief Irccd related errors.
-     */
-    enum error {
-        //!< No error.
-        no_error = 0,
+	/**
+	 * \brief Irccd related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
 
-        //!< The connected peer is not irccd.
-        not_irccd,
+		//!< The connected peer is not irccd.
+		not_irccd,
 
-        //!< The irccd version is too different.
-        incompatible_version,
+		//!< The irccd version is too different.
+		incompatible_version,
 
-        //!< Authentication was required but not issued.
-        auth_required,
+		//!< Authentication was required but not issued.
+		auth_required,
 
-        //!< Authentication was invalid.
-        invalid_auth,
+		//!< Authentication was invalid.
+		invalid_auth,
 
-        //!< The message was not a valid JSON object.
-        invalid_message,
+		//!< The message was not a valid JSON object.
+		invalid_message,
 
-        //!< The specified command does not exist.
-        invalid_command,
+		//!< The specified command does not exist.
+		invalid_command,
 
-        //!< The specified command requires more arguments.
-        incomplete_message,
-    };
+		//!< The specified command requires more arguments.
+		incomplete_message,
+	};
 
-    /**
-     * Inherited constructors.
-     */
-    using system_error::system_error;
+	/**
+	 * Inherited constructors.
+	 */
+	using system_error::system_error;
 };
 
 /**
--- a/libirccd/irccd/daemon/logger.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/logger.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,101 +31,101 @@
 
 void logger::debug(const std::string& line)
 {
-    // Print only in debug mode, the buffer is flushed anyway.
+	// Print only in debug mode, the buffer is flushed anyway.
 #if !defined(NDEBUG)
-    parent_.write_debug(parent_.filter_->pre_debug(category_, component_, line));
+	parent_.write_debug(parent_.filter_->pre_debug(category_, component_, line));
 #else
-    (void)line;
+	(void)line;
 #endif
 }
 
 void logger::info(const std::string& line)
 {
-    // Print only if verbose, the buffer will be flushed anyway.
-    if (parent_.verbose_)
-        parent_.write_info(parent_.filter_->pre_info(category_, component_, line));
+	// Print only if verbose, the buffer will be flushed anyway.
+	if (parent_.verbose_)
+		parent_.write_info(parent_.filter_->pre_info(category_, component_, line));
 }
 
 void logger::warning(const std::string& line)
 {
-    parent_.write_warning(parent_.filter_->pre_warning(category_, component_, line));
+	parent_.write_warning(parent_.filter_->pre_warning(category_, component_, line));
 }
 
 logger::logger(sink& parent, level level, std::string_view category, std::string_view component) noexcept
-    : std::ostream(this)
-    , level_(level)
-    , parent_(parent)
-    , category_(category)
-    , component_(component)
+	: std::ostream(this)
+	, level_(level)
+	, parent_(parent)
+	, category_(category)
+	, component_(component)
 {
-    assert(level >= level::debug && level <= level::warning);
+	assert(level >= level::debug && level <= level::warning);
 }
 
 int logger::sync()
 {
-    std::string buffer = str();
-    std::string::size_type pos;
+	std::string buffer = str();
+	std::string::size_type pos;
 
-    while ((pos = buffer.find("\n")) != std::string::npos) {
-        auto line = buffer.substr(0, pos);
+	while ((pos = buffer.find("\n")) != std::string::npos) {
+		auto line = buffer.substr(0, pos);
 
-        // Remove this line.
-        buffer.erase(buffer.begin(), buffer.begin() + pos + 1);
+		// Remove this line.
+		buffer.erase(buffer.begin(), buffer.begin() + pos + 1);
 
-        switch (level_) {
-        case level::debug:
-            debug(line);
-            break;
-        case level::info:
-            info(line);
-            break;
-        case level::warning:
-            warning(line);
-            break;
-        default:
-            break;
-        }
-    }
+		switch (level_) {
+		case level::debug:
+			debug(line);
+			break;
+		case level::info:
+			info(line);
+			break;
+		case level::warning:
+			warning(line);
+			break;
+		default:
+			break;
+		}
+	}
 
-    str(buffer);
+	str(buffer);
 
-    return 0;
+	return 0;
 }
 
 void console_sink::write_info(const std::string& line)
 {
-    std::cout << line << std::endl;
+	std::cout << line << std::endl;
 }
 
 void console_sink::write_warning(const std::string& line)
 {
-    std::cerr << line << std::endl;
+	std::cerr << line << std::endl;
 }
 
 void console_sink::write_debug(const std::string& line)
 {
-    std::cout << line << std::endl;
+	std::cout << line << std::endl;
 }
 
 file_sink::file_sink(std::string normal, std::string errors)
-    : output_normal_(std::move(normal))
-    , output_error_(std::move(errors))
+	: output_normal_(std::move(normal))
+	, output_error_(std::move(errors))
 {
 }
 
 void file_sink::write_info(const std::string& line)
 {
-    std::ofstream(output_normal_, std::ofstream::out | std::ofstream::app) << line << std::endl;
+	std::ofstream(output_normal_, std::ofstream::out | std::ofstream::app) << line << std::endl;
 }
 
 void file_sink::write_warning(const std::string& line)
 {
-    std::ofstream(output_error_, std::ofstream::out | std::ofstream::app) << line << std::endl;
+	std::ofstream(output_error_, std::ofstream::out | std::ofstream::app) << line << std::endl;
 }
 
 void file_sink::write_debug(const std::string& line)
 {
-    std::ofstream(output_normal_, std::ofstream::out | std::ofstream::app) << line << std::endl;
+	std::ofstream(output_normal_, std::ofstream::out | std::ofstream::app) << line << std::endl;
 }
 
 void silent_sink::write_info(const std::string&)
@@ -144,104 +144,104 @@
 
 syslog_sink::syslog_sink()
 {
-    openlog("irccd", LOG_PID, LOG_DAEMON);
+	openlog("irccd", LOG_PID, LOG_DAEMON);
 }
 
 syslog_sink::~syslog_sink()
 {
-    closelog();
+	closelog();
 }
 
 void syslog_sink::write_info(const std::string& line)
 {
-    syslog(LOG_INFO | LOG_USER, "%s", line.c_str());
+	syslog(LOG_INFO | LOG_USER, "%s", line.c_str());
 }
 
 void syslog_sink::write_warning(const std::string& line)
 {
-    syslog(LOG_WARNING | LOG_USER, "%s", line.c_str());
+	syslog(LOG_WARNING | LOG_USER, "%s", line.c_str());
 }
 
 void syslog_sink::write_debug(const std::string& line)
 {
-    syslog(LOG_DEBUG | LOG_USER, "%s", line.c_str());
+	syslog(LOG_DEBUG | LOG_USER, "%s", line.c_str());
 }
 
 #endif // !IRCCD_HAVE_SYSLOG
 
 sink::sink()
-    : filter_(new filter)
+	: filter_(new filter)
 {
 }
 
 auto sink::is_verbose() const noexcept -> bool
 {
-    return verbose_;
+	return verbose_;
 }
 
 void sink::set_verbose(bool mode) noexcept
 {
-    verbose_ = mode;
+	verbose_ = mode;
 }
 
 void sink::set_filter(std::unique_ptr<filter> filter) noexcept
 {
-    assert(filter);
+	assert(filter);
 
-    filter_ = std::move(filter);
+	filter_ = std::move(filter);
 }
 
 auto sink::info(std::string_view category, std::string_view component) -> logger
 {
-    return logger(*this, logger::level::info, category, component);;
+	return logger(*this, logger::level::info, category, component);;
 }
 
 auto sink::warning(std::string_view category, std::string_view component) -> logger
 {
-    return logger(*this, logger::level::warning, category, component);;
+	return logger(*this, logger::level::warning, category, component);;
 }
 
 auto sink::debug(std::string_view category, std::string_view component) -> logger
 {
-    return logger(*this, logger::level::debug, category, component);;
+	return logger(*this, logger::level::debug, category, component);;
 }
 
 auto filter::pre(std::string_view category,
                  std::string_view component,
                  std::string_view message) const -> std::string
 {
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    oss << category;
+	oss << category;
 
-    if (!component.empty())
-        oss << " " << component;
+	if (!component.empty())
+		oss << " " << component;
 
-    oss << ": ";
-    oss << message;
+	oss << ": ";
+	oss << message;
 
-    return oss.str();
+	return oss.str();
 }
 
 auto filter::pre_debug(std::string_view category,
                        std::string_view component,
                        std::string_view message) const -> std::string
 {
-    return pre(category, component, message);
+	return pre(category, component, message);
 }
 
 auto filter::pre_info(std::string_view category,
                       std::string_view component,
                       std::string_view message) const -> std::string
 {
-    return pre(category, component, message);
+	return pre(category, component, message);
 }
 
 auto filter::pre_warning(std::string_view category,
-                        std::string_view component,
-                        std::string_view message) const -> std::string
+                         std::string_view component,
+                         std::string_view message) const -> std::string
 {
-    return pre(category, component, message);
+	return pre(category, component, message);
 }
 
 } // !irccd::logger
--- a/libirccd/irccd/daemon/logger.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/logger.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -53,24 +53,24 @@
 
 class logger : public std::ostream, public std::stringbuf {
 private:
-    friend class sink;
+	friend class sink;
 
-    enum class level {
-        debug,
-        info,
-        warning
-    } level_;
+	enum class level {
+		debug,
+		info,
+		warning
+	} level_;
 
-    sink& parent_;
+	sink& parent_;
 
-    std::string_view category_;
-    std::string_view component_;
+	std::string_view category_;
+	std::string_view component_;
 
-    void debug(const std::string&);
-    void info(const std::string&);
-    void warning(const std::string&);
-    auto sync() -> int override;
-    logger(sink&, level, std::string_view, std::string_view) noexcept;
+	void debug(const std::string&);
+	void info(const std::string&);
+	void warning(const std::string&);
+	auto sync() -> int override;
+	logger(sink&, level, std::string_view, std::string_view) noexcept;
 };
 
 /**
@@ -86,158 +86,158 @@
  */
 class sink {
 private:
-    friend class logger;
+	friend class logger;
 
-    // User options.
-    bool verbose_{false};
-    std::unique_ptr<filter> filter_;
+	// User options.
+	bool verbose_{false};
+	std::unique_ptr<filter> filter_;
 
 protected:
-    /**
-     * Write a debug message.
-     *
-     * This function is called only if NDEBUG is not defined.
-     *
-     * \param line the data
-     * \see log::debug
-     */
-    virtual void write_debug(const std::string& line) = 0;
+	/**
+	 * Write a debug message.
+	 *
+	 * This function is called only if NDEBUG is not defined.
+	 *
+	 * \param line the data
+	 * \see log::debug
+	 */
+	virtual void write_debug(const std::string& line) = 0;
 
-    /**
-     * Write a information message.
-     *
-     * The function is called only if verbose is true.
-     *
-     * \param line the data
-     * \see log::info
-     */
-    virtual void write_info(const std::string& line) = 0;
+	/**
+	 * Write a information message.
+	 *
+	 * The function is called only if verbose is true.
+	 *
+	 * \param line the data
+	 * \see log::info
+	 */
+	virtual void write_info(const std::string& line) = 0;
 
-    /**
-     * Write an error message.
-     *
-     * This function is always called.
-     *
-     * \param line the data
-     * \see log::warning
-     */
-    virtual void write_warning(const std::string& line) = 0;
+	/**
+	 * Write an error message.
+	 *
+	 * This function is always called.
+	 *
+	 * \param line the data
+	 * \see log::warning
+	 */
+	virtual void write_warning(const std::string& line) = 0;
 
 public:
-    /**
-     * Default constructor.
-     */
-    sink();
+	/**
+	 * Default constructor.
+	 */
+	sink();
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~sink() = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~sink() = default;
 
-    /**
-     * Tells if logger is verbose.
-     *
-     * \return true if verbose
-     */
-    auto is_verbose() const noexcept -> bool;
+	/**
+	 * Tells if logger is verbose.
+	 *
+	 * \return true if verbose
+	 */
+	auto is_verbose() const noexcept -> bool;
 
-    /**
-     * Set the verbosity mode.
-     *
-     * \param mode the new mode
-     */
-    void set_verbose(bool mode) noexcept;
+	/**
+	 * Set the verbosity mode.
+	 *
+	 * \param mode the new mode
+	 */
+	void set_verbose(bool mode) noexcept;
 
-    /**
-     * Set an optional filter.
-     *
-     * \pre filter must not be null
-     * \param filter the filter
-     */
-    void set_filter(std::unique_ptr<filter> filter) noexcept;
+	/**
+	 * Set an optional filter.
+	 *
+	 * \pre filter must not be null
+	 * \param filter the filter
+	 */
+	void set_filter(std::unique_ptr<filter> filter) noexcept;
 
-    /**
-     * Get the stream for informational messages.
-     *
-     * If message is specified, a new line character is appended.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \return the output stream
-     * \note Has no effect if verbose is set to false.
-     */
-    auto info(std::string_view category, std::string_view component) -> logger;
+	/**
+	 * Get the stream for informational messages.
+	 *
+	 * If message is specified, a new line character is appended.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \return the output stream
+	 * \note Has no effect if verbose is set to false.
+	 */
+	auto info(std::string_view category, std::string_view component) -> logger;
 
-    /**
-     * Convenient function with loggable objects.
-     *
-     * \param loggable the loggable object
-     * \return the output stream
-     * \see loggable_traits
-     */
-    template <typename Loggable>
-    auto info(const Loggable& loggable) -> logger
-    {
-        return info(
-            loggable_traits<Loggable>::get_category(loggable),
-            loggable_traits<Loggable>::get_component(loggable)
-        );
-    }
+	/**
+	 * Convenient function with loggable objects.
+	 *
+	 * \param loggable the loggable object
+	 * \return the output stream
+	 * \see loggable_traits
+	 */
+	template <typename Loggable>
+	auto info(const Loggable& loggable) -> logger
+	{
+		return info(
+			loggable_traits<Loggable>::get_category(loggable),
+			loggable_traits<Loggable>::get_component(loggable)
+		);
+	}
 
-    /**
-     * Get the stream for warnings.
-     *
-     * If message is specified, a new line character is appended.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \return the output stream
-     */
-    auto warning(std::string_view category, std::string_view component) -> logger;
+	/**
+	 * Get the stream for warnings.
+	 *
+	 * If message is specified, a new line character is appended.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \return the output stream
+	 */
+	auto warning(std::string_view category, std::string_view component) -> logger;
 
-    /**
-     * Convenient function with loggable objects.
-     *
-     * \param loggable the loggable object
-     * \return the output stream
-     * \see loggable_traits
-     */
-    template <typename Loggable>
-    auto warning(const Loggable& loggable) -> logger
-    {
-        return warning(
-            loggable_traits<Loggable>::get_category(loggable),
-            loggable_traits<Loggable>::get_component(loggable)
-        );
-    }
+	/**
+	 * Convenient function with loggable objects.
+	 *
+	 * \param loggable the loggable object
+	 * \return the output stream
+	 * \see loggable_traits
+	 */
+	template <typename Loggable>
+	auto warning(const Loggable& loggable) -> logger
+	{
+		return warning(
+			loggable_traits<Loggable>::get_category(loggable),
+			loggable_traits<Loggable>::get_component(loggable)
+		);
+	}
 
-    /**
-     * Get the stream for debug messages.
-     *
-     * If message is specified, a new line character is appended.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \return the output stream
-     * \note Has no effect if compiled in release mode.
-     */
-    auto debug(std::string_view category, std::string_view component) -> logger;
+	/**
+	 * Get the stream for debug messages.
+	 *
+	 * If message is specified, a new line character is appended.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \return the output stream
+	 * \note Has no effect if compiled in release mode.
+	 */
+	auto debug(std::string_view category, std::string_view component) -> logger;
 
-    /**
-     * Convenient function with loggable objects.
-     *
-     * \param loggable the loggable object
-     * \return the output stream
-     * \see loggable_traits
-     */
-    template <typename Loggable>
-    auto debug(const Loggable& loggable) -> logger
-    {
-        return debug(
-            loggable_traits<Loggable>::get_category(loggable),
-            loggable_traits<Loggable>::get_component(loggable)
-        );
-    }
+	/**
+	 * Convenient function with loggable objects.
+	 *
+	 * \param loggable the loggable object
+	 * \return the output stream
+	 * \see loggable_traits
+	 */
+	template <typename Loggable>
+	auto debug(const Loggable& loggable) -> logger
+	{
+		return debug(
+			loggable_traits<Loggable>::get_category(loggable),
+			loggable_traits<Loggable>::get_component(loggable)
+		);
+	}
 };
 
 /**
@@ -246,81 +246,81 @@
 class filter {
 private:
 public:
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~filter() = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~filter() = default;
 
-    /**
-     * Default function called for each virtual ones.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \param message the message
-     * \return default formatted message
-     */
-    auto pre(std::string_view category,
-             std::string_view component,
-             std::string_view message) const -> std::string;
+	/**
+	 * Default function called for each virtual ones.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \param message the message
+	 * \return default formatted message
+	 */
+	auto pre(std::string_view category,
+	         std::string_view component,
+	         std::string_view message) const -> std::string;
 
 
-    /**
-     * Update the debug message.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \param message the message
-     * \return the message
-     */
-    virtual auto pre_debug(std::string_view category,
-                           std::string_view component,
-                           std::string_view message) const -> std::string;
+	/**
+	 * Update the debug message.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \param message the message
+	 * \return the message
+	 */
+	virtual auto pre_debug(std::string_view category,
+	                       std::string_view component,
+	                       std::string_view message) const -> std::string;
 
-    /**
-     * Update the information message.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \param message the message
-     * \return the updated message
-     */
-    virtual auto pre_info(std::string_view category,
-                          std::string_view component,
-                          std::string_view message) const -> std::string;
+	/**
+	 * Update the information message.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \param message the message
+	 * \return the updated message
+	 */
+	virtual auto pre_info(std::string_view category,
+	                      std::string_view component,
+	                      std::string_view message) const -> std::string;
 
-    /**
-     * Update the warning message.
-     *
-     * \param category the category subsystem
-     * \param component the optional component
-     * \param message the message
-     * \return the updated message
-     */
-    virtual auto pre_warning(std::string_view category,
-                             std::string_view component,
-                             std::string_view message) const -> std::string;
+	/**
+	 * Update the warning message.
+	 *
+	 * \param category the category subsystem
+	 * \param component the optional component
+	 * \param message the message
+	 * \return the updated message
+	 */
+	virtual auto pre_warning(std::string_view category,
+	                         std::string_view component,
+	                         std::string_view message) const -> std::string;
 };
 
 /**
  * \brief Logger implementation for console output using std::cout and
- *        std::cerr.
+ *		std::cerr.
  */
 class console_sink : public sink {
 protected:
-    /**
-     * \copydoc logger::write_debug
-     */
-    void write_debug(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_debug
+	 */
+	void write_debug(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_info
-     */
-    void write_info(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_info
+	 */
+	void write_info(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_warning
-     */
-    void write_warning(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_warning
+	 */
+	void write_warning(const std::string& line) override;
 };
 
 /**
@@ -328,33 +328,33 @@
  */
 class file_sink : public sink {
 private:
-    std::string output_normal_;
-    std::string output_error_;
+	std::string output_normal_;
+	std::string output_error_;
 
 protected:
-    /**
-     * \copydoc logger::write_debug
-     */
-    void write_debug(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_debug
+	 */
+	void write_debug(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_info
-     */
-    void write_info(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_info
+	 */
+	void write_info(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_warning
-     */
-    void write_warning(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_warning
+	 */
+	void write_warning(const std::string& line) override;
 
 public:
-    /**
-     * Outputs to files.
-     *
-     * \param normal the path to the normal logs
-     * \param errors the path to the errors logs
-     */
-    file_sink(std::string normal, std::string errors);
+	/**
+	 * Outputs to files.
+	 *
+	 * \param normal the path to the normal logs
+	 * \param errors the path to the errors logs
+	 */
+	file_sink(std::string normal, std::string errors);
 };
 
 /**
@@ -364,20 +364,20 @@
  */
 class silent_sink : public sink {
 protected:
-    /**
-     * \copydoc logger::write_debug
-     */
-    void write_debug(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_debug
+	 */
+	void write_debug(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_info
-     */
-    void write_info(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_info
+	 */
+	void write_info(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_warning
-     */
-    void write_warning(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_warning
+	 */
+	void write_warning(const std::string& line) override;
 };
 
 #if defined(IRCCD_HAVE_SYSLOG)
@@ -387,31 +387,31 @@
  */
 class syslog_sink : public sink {
 protected:
-    /**
-     * \copydoc logger::write_debug
-     */
-    void write_debug(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_debug
+	 */
+	void write_debug(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_info
-     */
-    void write_info(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_info
+	 */
+	void write_info(const std::string& line) override;
 
-    /**
-     * \copydoc logger::write_warning
-     */
-    void write_warning(const std::string& line) override;
+	/**
+	 * \copydoc logger::write_warning
+	 */
+	void write_warning(const std::string& line) override;
 
 public:
-    /**
-     * Open the syslog.
-     */
-    syslog_sink();
+	/**
+	 * Open the syslog.
+	 */
+	syslog_sink();
 
-    /**
-     * Close the syslog.
-     */
-    ~syslog_sink();
+	/**
+	 * Close the syslog.
+	 */
+	~syslog_sink();
 };
 
 #endif // !IRCCD_HAVE_SYSLOG
--- a/libirccd/irccd/daemon/plugin.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/plugin.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,39 +29,39 @@
 namespace irccd {
 
 plugin::plugin(std::string id) noexcept
-    : id_(std::move(id))
+	: id_(std::move(id))
 {
-    assert(string_util::is_identifier(id_));
+	assert(string_util::is_identifier(id_));
 }
 
 auto plugin::get_id() const noexcept -> const std::string&
 {
-    return id_;
+	return id_;
 }
 
 auto plugin::get_author() const noexcept -> std::string_view
 {
-    return "unknown";
+	return "unknown";
 }
 
 auto plugin::get_license() const noexcept -> std::string_view
 {
-    return "unknown";
+	return "unknown";
 }
 
 auto plugin::get_summary() const noexcept -> std::string_view
 {
-    return "unknown";
+	return "unknown";
 }
 
 auto plugin::get_version() const noexcept -> std::string_view
 {
-    return "unknown";
+	return "unknown";
 }
 
 auto plugin::get_options() const -> map
 {
-    return {};
+	return {};
 }
 
 void plugin::set_options(const map&)
@@ -70,7 +70,7 @@
 
 auto plugin::get_formats() const -> map
 {
-    return {};
+	return {};
 }
 
 void plugin::set_formats(const map&)
@@ -79,7 +79,7 @@
 
 auto plugin::get_paths() const -> map
 {
-    return {};
+	return {};
 }
 
 void plugin::set_paths(const map&)
@@ -159,105 +159,105 @@
 }
 
 plugin_loader::plugin_loader(std::vector<std::string> directories,
-              std::vector<std::string> extensions) noexcept
-    : directories_(std::move(directories))
-    , extensions_(std::move(extensions))
+			  std::vector<std::string> extensions) noexcept
+	: directories_(std::move(directories))
+	, extensions_(std::move(extensions))
 {
-    assert(!extensions_.empty());
+	assert(!extensions_.empty());
 }
 
 auto plugin_loader::find(std::string_view name) -> std::shared_ptr<plugin>
 {
-    std::vector<std::string> filenames;
+	std::vector<std::string> filenames;
 
-    if (directories_.empty())
-        filenames = sys::plugin_filenames(std::string(name), extensions_);
-    else {
-        for (const auto& dir : directories_)
-            for (const auto& ext : extensions_)
-                filenames.push_back(dir + std::string("/") + std::string(name) + ext);
-    }
+	if (directories_.empty())
+		filenames = sys::plugin_filenames(std::string(name), extensions_);
+	else {
+		for (const auto& dir : directories_)
+			for (const auto& ext : extensions_)
+				filenames.push_back(dir + std::string("/") + std::string(name) + ext);
+	}
 
-    for (const auto& candidate : filenames) {
-        boost::system::error_code ec;
+	for (const auto& candidate : filenames) {
+		boost::system::error_code ec;
 
-        if (!boost::filesystem::exists(candidate, ec) || ec)
-            continue;
+		if (!boost::filesystem::exists(candidate, ec) || ec)
+			continue;
 
-        auto plugin = open(name, candidate);
+		auto plugin = open(name, candidate);
 
-        if (plugin)
-            return plugin;
-    }
+		if (plugin)
+			return plugin;
+	}
 
-    return nullptr;
+	return nullptr;
 }
 
 plugin_error::plugin_error(error errc, std::string_view name, std::string_view message)
-    : system_error(make_error_code(errc))
-    , name_(std::move(name))
-    , message_(std::move(message))
+	: system_error(make_error_code(errc))
+	, name_(std::move(name))
+	, message_(std::move(message))
 {
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    oss << code().message();
+	oss << code().message();
 
-    std::istringstream iss(message_);
-    std::string line;
+	std::istringstream iss(message_);
+	std::string line;
 
-    while (getline(iss, line))
-        oss << "\n" << line;
+	while (getline(iss, line))
+		oss << "\n" << line;
 
-    what_ = oss.str();
+	what_ = oss.str();
 }
 
 auto plugin_error::get_name() const noexcept -> const std::string&
 {
-    return name_;
+	return name_;
 }
 
 auto plugin_error::get_message() const noexcept -> const std::string&
 {
-    return message_;
+	return message_;
 }
 
 auto plugin_error::what() const noexcept -> const char*
 {
-    return what_.c_str();
+	return what_.c_str();
 }
 
 auto plugin_category() -> const std::error_category&
 {
-    static const class category : public std::error_category {
-    public:
-        auto name() const noexcept -> const char* override
-        {
-            return "plugin";
-        }
+	static const class category : public std::error_category {
+	public:
+		auto name() const noexcept -> const char* override
+		{
+			return "plugin";
+		}
 
-        auto message(int e) const -> std::string override
-        {
-            switch (static_cast<plugin_error::error>(e)) {
-            case plugin_error::not_found:
-                return "plugin not found";
-            case plugin_error::invalid_identifier:
-                return "invalid plugin identifier";
-            case plugin_error::exec_error:
-                return "plugin exec error";
-            case plugin_error::already_exists:
-                return "plugin already exists";
-            default:
-                return "no error";
-            }
-        }
-    } category;
+		auto message(int e) const -> std::string override
+		{
+			switch (static_cast<plugin_error::error>(e)) {
+			case plugin_error::not_found:
+				return "plugin not found";
+			case plugin_error::invalid_identifier:
+				return "invalid plugin identifier";
+			case plugin_error::exec_error:
+				return "plugin exec error";
+			case plugin_error::already_exists:
+				return "plugin already exists";
+			default:
+				return "no error";
+			}
+		}
+	} category;
 
-    return category;
+	return category;
 }
 
 auto make_error_code(plugin_error::error e) -> std::error_code
 {
-    return {static_cast<int>(e), plugin_category()};
+	return {static_cast<int>(e), plugin_category()};
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/plugin.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/plugin.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -65,256 +65,256 @@
  */
 class plugin : public std::enable_shared_from_this<plugin> {
 public:
-    /**
-     * Map for key/value pairs.
-     *
-     * Used in options, formats and paths.
-     */
-    using map = std::unordered_map<std::string, std::string>;
+	/**
+	 * Map for key/value pairs.
+	 *
+	 * Used in options, formats and paths.
+	 */
+	using map = std::unordered_map<std::string, std::string>;
 
 private:
-    std::string id_;
+	std::string id_;
 
 public:
-    /**
-     * Construct a plugin.
-     *
-     * \pre id must be a valid identifier
-     * \param id the plugin id
-     */
-    plugin(std::string id) noexcept;
+	/**
+	 * Construct a plugin.
+	 *
+	 * \pre id must be a valid identifier
+	 * \param id the plugin id
+	 */
+	plugin(std::string id) noexcept;
 
-    /**
-     * Temporary, close all timers.
-     */
-    virtual ~plugin() = default;
+	/**
+	 * Temporary, close all timers.
+	 */
+	virtual ~plugin() = default;
 
-    /**
-     * Get user unique id.
-     *
-     * \return the plugin id
-     */
-    auto get_id() const noexcept -> const std::string&;
+	/**
+	 * Get user unique id.
+	 *
+	 * \return the plugin id
+	 */
+	auto get_id() const noexcept -> const std::string&;
 
-    /**
-     * Get the plugin name.
-     *
-     * \return the plugin name
-     */
-    virtual auto get_name() const noexcept -> std::string_view = 0;
+	/**
+	 * Get the plugin name.
+	 *
+	 * \return the plugin name
+	 */
+	virtual auto get_name() const noexcept -> std::string_view = 0;
 
-    /**
-     * Get the author.
-     *
-     * \return the author
-     */
-    virtual auto get_author() const noexcept -> std::string_view;
+	/**
+	 * Get the author.
+	 *
+	 * \return the author
+	 */
+	virtual auto get_author() const noexcept -> std::string_view;
 
-    /**
-     * Get the license.
-     *
-     * \return the license
-     */
-    virtual auto get_license() const noexcept -> std::string_view;
+	/**
+	 * Get the license.
+	 *
+	 * \return the license
+	 */
+	virtual auto get_license() const noexcept -> std::string_view;
 
-    /**
-     * Get the summary.
-     *
-     * \return the summary
-     */
-    virtual auto get_summary() const noexcept -> std::string_view;
+	/**
+	 * Get the summary.
+	 *
+	 * \return the summary
+	 */
+	virtual auto get_summary() const noexcept -> std::string_view;
 
-    /**
-     * Get the version.
-     *
-     * \return the version
-     */
-    virtual auto get_version() const noexcept -> std::string_view;
+	/**
+	 * Get the version.
+	 *
+	 * \return the version
+	 */
+	virtual auto get_version() const noexcept -> std::string_view;
 
-    /**
-     * Get all options.
-     *
-     * \return options
-     */
-    virtual auto get_options() const -> map;
+	/**
+	 * Get all options.
+	 *
+	 * \return options
+	 */
+	virtual auto get_options() const -> map;
 
-    /**
-     * Set all options.
-     *
-     * \param map the options
-     */
-    virtual void set_options(const map& map);
+	/**
+	 * Set all options.
+	 *
+	 * \param map the options
+	 */
+	virtual void set_options(const map& map);
 
-    /**
-     * Get all formats.
-     *
-     * \return formats
-     */
-    virtual auto get_formats() const -> map;
+	/**
+	 * Get all formats.
+	 *
+	 * \return formats
+	 */
+	virtual auto get_formats() const -> map;
 
-    /**
-     * Set all formats.
-     *
-     * \param map the formats
-     */
-    virtual void set_formats(const map& map);
+	/**
+	 * Set all formats.
+	 *
+	 * \param map the formats
+	 */
+	virtual void set_formats(const map& map);
 
-    /**
-     * Get all paths.
-     *
-     * \return paths
-     */
-    virtual auto get_paths() const -> map;
+	/**
+	 * Get all paths.
+	 *
+	 * \return paths
+	 */
+	virtual auto get_paths() const -> map;
 
-    /**
-     * Set all paths.
-     *
-     * \param map the paths
-     */
-    virtual void set_paths(const map& map);
+	/**
+	 * Set all paths.
+	 *
+	 * \param map the paths
+	 */
+	virtual void set_paths(const map& map);
 
-    /**
-     * On channel message. This event will call onMessage or
-     * onCommand if the messages starts with the command character
-     * plus the plugin name.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_command(irccd& irccd, const message_event& event);
+	/**
+	 * On channel message. This event will call onMessage or
+	 * onCommand if the messages starts with the command character
+	 * plus the plugin name.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_command(irccd& irccd, const message_event& event);
 
-    /**
-     * On successful connection.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_connect(irccd& irccd, const connect_event& event);
+	/**
+	 * On successful connection.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_connect(irccd& irccd, const connect_event& event);
 
-    /**
-     * On disconnection.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_disconnect(irccd& irccd, const disconnect_event& event);
+	/**
+	 * On disconnection.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_disconnect(irccd& irccd, const disconnect_event& event);
 
-    /**
-     * On invitation.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_invite(irccd& irccd, const invite_event& event);
+	/**
+	 * On invitation.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_invite(irccd& irccd, const invite_event& event);
 
-    /**
-     * On join.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_join(irccd& irccd, const join_event& event);
+	/**
+	 * On join.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_join(irccd& irccd, const join_event& event);
 
-    /**
-     * On kick.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_kick(irccd& irccd, const kick_event& event);
+	/**
+	 * On kick.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_kick(irccd& irccd, const kick_event& event);
 
-    /**
-     * On load.
-     *
-     * \param irccd the irccd instance
-     */
-    virtual void handle_load(irccd& irccd);
+	/**
+	 * On load.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	virtual void handle_load(irccd& irccd);
 
-    /**
-     * On channel message.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_message(irccd& irccd, const message_event& event);
+	/**
+	 * On channel message.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_message(irccd& irccd, const message_event& event);
 
-    /**
-     * On CTCP Action.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_me(irccd& irccd, const me_event& event);
+	/**
+	 * On CTCP Action.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_me(irccd& irccd, const me_event& event);
 
-    /**
-     * On user mode change.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_mode(irccd& irccd, const mode_event& event);
+	/**
+	 * On user mode change.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_mode(irccd& irccd, const mode_event& event);
 
-    /**
-     * On names listing.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_names(irccd& irccd, const names_event& event);
+	/**
+	 * On names listing.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_names(irccd& irccd, const names_event& event);
 
-    /**
-     * On nick change.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_nick(irccd& irccd, const nick_event& event);
+	/**
+	 * On nick change.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_nick(irccd& irccd, const nick_event& event);
 
-    /**
-     * On user notice.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_notice(irccd& irccd, const notice_event& event);
+	/**
+	 * On user notice.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_notice(irccd& irccd, const notice_event& event);
 
-    /**
-     * On part.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_part(irccd& irccd, const part_event& event);
+	/**
+	 * On part.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_part(irccd& irccd, const part_event& event);
 
-    /**
-     * On reload.
-     *
-     * \param irccd the irccd instance
-     */
-    virtual void handle_reload(irccd& irccd);
+	/**
+	 * On reload.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	virtual void handle_reload(irccd& irccd);
 
-    /**
-     * On topic change.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_topic(irccd& irccd, const topic_event& event);
+	/**
+	 * On topic change.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_topic(irccd& irccd, const topic_event& event);
 
-    /**
-     * On unload.
-     *
-     * \param irccd the irccd instance
-     */
-    virtual void handle_unload(irccd& irccd);
+	/**
+	 * On unload.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	virtual void handle_unload(irccd& irccd);
 
-    /**
-     * On whois information.
-     *
-     * \param irccd the irccd instance
-     * \param event the event
-     */
-    virtual void handle_whois(irccd& irccd, const whois_event& event);
+	/**
+	 * On whois information.
+	 *
+	 * \param irccd the irccd instance
+	 * \param event the event
+	 */
+	virtual void handle_whois(irccd& irccd, const whois_event& event);
 };
 
 /**
@@ -331,48 +331,48 @@
  */
 class plugin_loader {
 private:
-    std::vector<std::string> directories_;
-    std::vector<std::string> extensions_;
+	std::vector<std::string> directories_;
+	std::vector<std::string> extensions_;
 
 public:
-    /**
-     * Construct the loader with a predefined set of directories and extensions.
-     *
-     * If directories is not specified, a sensible default list of system and
-     * user paths are searched.
-     *
-     * \pre !extensions.empty()
-     * \param directories optional list of directories to search
-     * \param extensions the non empty list of extensions supported
-     */
-    plugin_loader(std::vector<std::string> directories,
-                  std::vector<std::string> extensions) noexcept;
+	/**
+	 * Construct the loader with a predefined set of directories and extensions.
+	 *
+	 * If directories is not specified, a sensible default list of system and
+	 * user paths are searched.
+	 *
+	 * \pre !extensions.empty()
+	 * \param directories optional list of directories to search
+	 * \param extensions the non empty list of extensions supported
+	 */
+	plugin_loader(std::vector<std::string> directories,
+				  std::vector<std::string> extensions) noexcept;
 
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~plugin_loader() = default;
+	/**
+	 * Virtual destructor defaulted.
+	 */
+	virtual ~plugin_loader() = default;
 
-    /**
-     * Try to open the plugin specified by path.
-     *
-     * The implementation must test if the plugin is suitable for opening, by
-     * testing extension for example.
-     *
-     * \param id the plugin identifier
-     * \param file the file path
-     * \throw plugin_error on errors
-     */
-    virtual auto open(std::string_view id, std::string_view file) -> std::shared_ptr<plugin> = 0;
+	/**
+	 * Try to open the plugin specified by path.
+	 *
+	 * The implementation must test if the plugin is suitable for opening, by
+	 * testing extension for example.
+	 *
+	 * \param id the plugin identifier
+	 * \param file the file path
+	 * \throw plugin_error on errors
+	 */
+	virtual auto open(std::string_view id, std::string_view file) -> std::shared_ptr<plugin> = 0;
 
-    /**
-     * Search for a plugin named by this id.
-     *
-     * \param id the plugin id
-     * \return the plugin
-     * \throw plugin_error on errors
-     */
-    virtual auto find(std::string_view id) -> std::shared_ptr<plugin>;
+	/**
+	 * Search for a plugin named by this id.
+	 *
+	 * \param id the plugin id
+	 * \return the plugin
+	 * \throw plugin_error on errors
+	 */
+	virtual auto find(std::string_view id) -> std::shared_ptr<plugin>;
 };
 
 /**
@@ -380,59 +380,59 @@
  */
 class plugin_error : public std::system_error {
 public:
-    /**
-     * \brief Plugin related errors.
-     */
-    enum error {
-        //!< No error.
-        no_error = 0,
+	/**
+	 * \brief Plugin related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
 
-        //!< The specified identifier is invalid.
-        invalid_identifier,
+		//!< The specified identifier is invalid.
+		invalid_identifier,
 
-        //!< The specified plugin is not found.
-        not_found,
+		//!< The specified plugin is not found.
+		not_found,
 
-        //!< The plugin was unable to run the function.
-        exec_error,
+		//!< The plugin was unable to run the function.
+		exec_error,
 
-        //!< The plugin is already loaded.
-        already_exists,
-    };
+		//!< The plugin is already loaded.
+		already_exists,
+	};
 
 private:
-    std::string name_;
-    std::string message_;
-    std::string what_;
+	std::string name_;
+	std::string message_;
+	std::string what_;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param code the error code
-     * \param name the plugin name
-     * \param message the optional message (e.g. error from plugin)
-     */
-    plugin_error(error code, std::string_view name = "", std::string_view message = "");
+	/**
+	 * Constructor.
+	 *
+	 * \param code the error code
+	 * \param name the plugin name
+	 * \param message the optional message (e.g. error from plugin)
+	 */
+	plugin_error(error code, std::string_view name = "", std::string_view message = "");
 
-    /**
-     * Get the plugin name.
-     *
-     * \return the name
-     */
-    auto get_name() const noexcept -> const std::string&;
+	/**
+	 * Get the plugin name.
+	 *
+	 * \return the name
+	 */
+	auto get_name() const noexcept -> const std::string&;
 
-    /**
-     * Get the additional message.
-     *
-     * \return the message
-     */
-    auto get_message() const noexcept -> const std::string&;
+	/**
+	 * Get the additional message.
+	 *
+	 * \return the message
+	 */
+	auto get_message() const noexcept -> const std::string&;
 
-    /**
-     * Get message appropriate for use with logger.
-     */
-    auto what() const noexcept -> const char* override;
+	/**
+	 * Get message appropriate for use with logger.
+	 */
+	auto what() const noexcept -> const char* override;
 };
 
 /**
--- a/libirccd/irccd/daemon/plugin_service.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/plugin_service.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,242 +35,242 @@
 
 auto to_map(const config& conf, const std::string& section) -> plugin::map
 {
-    plugin::map ret;
+	plugin::map ret;
 
-    for (const auto& opt : conf.get(section))
-        ret.emplace(opt.key(), opt.value());
+	for (const auto& opt : conf.get(section))
+		ret.emplace(opt.get_key(), opt.get_value());
 
-    return ret;
+	return ret;
 }
 
 } // !namespace
 
 plugin_service::plugin_service(irccd& irccd) noexcept
-    : irccd_(irccd)
+	: irccd_(irccd)
 {
 }
 
 plugin_service::~plugin_service()
 {
-    for (const auto& plg : plugins_) {
-        try {
-            plg->handle_unload(irccd_);
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning(*plg) << ex.what() << std::endl;
-        }
-    }
+	for (const auto& plg : plugins_) {
+		try {
+			plg->handle_unload(irccd_);
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning(*plg) << ex.what() << std::endl;
+		}
+	}
 }
 
 auto plugin_service::all() const noexcept -> plugins
 {
-    return plugins_;
+	return plugins_;
 }
 
 auto plugin_service::has(std::string_view id) const noexcept -> bool
 {
-    return get(id) != nullptr;
+	return get(id) != nullptr;
 }
 
 auto plugin_service::get(std::string_view id) const noexcept -> std::shared_ptr<plugin>
 {
-    const auto find = [id] (const auto& plg) {
-        return plg->get_id() == id;
-    };
+	const auto find = [id] (const auto& plg) {
+		return plg->get_id() == id;
+	};
 
-    if (const auto it = std::find_if(plugins_.begin(), plugins_.end(), find); it != plugins_.end())
-        return *it;
+	if (const auto it = std::find_if(plugins_.begin(), plugins_.end(), find); it != plugins_.end())
+		return *it;
 
-    return nullptr;
+	return nullptr;
 }
 
 auto plugin_service::require(std::string_view id) const -> std::shared_ptr<plugin>
 {
-    auto plugin = get(id);
+	auto plugin = get(id);
 
-    if (!plugin)
-        throw plugin_error(plugin_error::not_found, id);
+	if (!plugin)
+		throw plugin_error(plugin_error::not_found, id);
 
-    return plugin;
+	return plugin;
 }
 
 void plugin_service::add(std::shared_ptr<plugin> plugin)
 {
-    assert(plugin);
+	assert(plugin);
 
-    plugins_.push_back(std::move(plugin));
+	plugins_.push_back(std::move(plugin));
 }
 
 void plugin_service::add_loader(std::unique_ptr<plugin_loader> loader)
 {
-    assert(loader);
+	assert(loader);
 
-    loaders_.push_back(std::move(loader));
+	loaders_.push_back(std::move(loader));
 }
 
 auto plugin_service::get_options(std::string_view id) -> plugin::map
 {
-    return to_map(irccd_.get_config(), str(format("plugin.%1%") % id));
+	return to_map(irccd_.get_config(), str(format("plugin.%1%") % id));
 }
 
 auto plugin_service::get_formats(std::string_view id) -> plugin::map
 {
-    return to_map(irccd_.get_config(), str(format("format.%1%") % id));
+	return to_map(irccd_.get_config(), str(format("format.%1%") % id));
 }
 
 auto plugin_service::get_paths(std::string_view id) -> plugin::map
 {
-    auto defaults = to_map(irccd_.get_config(), "paths");
-    auto paths = to_map(irccd_.get_config(), str(format("paths.%1%") % id));
+	auto defaults = to_map(irccd_.get_config(), "paths");
+	auto paths = to_map(irccd_.get_config(), str(format("paths.%1%") % id));
 
-    // Fill defaults paths.
-    if (!defaults.count("cache"))
-        defaults.emplace("cache", sys::cachedir().string());
-    if (!defaults.count("data"))
-        defaults.emplace("data", sys::datadir().string());
-    if (!defaults.count("config"))
-        defaults.emplace("config", sys::sysconfdir().string());
+	// Fill defaults paths.
+	if (!defaults.count("cache"))
+		defaults.emplace("cache", sys::cachedir().string());
+	if (!defaults.count("data"))
+		defaults.emplace("data", sys::datadir().string());
+	if (!defaults.count("config"))
+		defaults.emplace("config", sys::sysconfdir().string());
 
-    const auto join = [id] (auto path) {
-        return (boost::filesystem::path(path) / "plugin" / std::string(id)).string();
-    };
+	const auto join = [id] (auto path) {
+		return (boost::filesystem::path(path) / "plugin" / std::string(id)).string();
+	};
 
-    // Now fill missing fields.
-    if (!paths.count("cache"))
-        paths.emplace("cache", join(defaults["cache"]));
-    if (!paths.count("data"))
-        paths.emplace("data", join(defaults["data"]));
-    if (!paths.count("config"))
-        paths.emplace("config", join(defaults["config"]));
+	// Now fill missing fields.
+	if (!paths.count("cache"))
+		paths.emplace("cache", join(defaults["cache"]));
+	if (!paths.count("data"))
+		paths.emplace("data", join(defaults["data"]));
+	if (!paths.count("config"))
+		paths.emplace("config", join(defaults["config"]));
 
-    return paths;
+	return paths;
 }
 
 auto plugin_service::open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>
 {
-    for (const auto& loader : loaders_) {
-        auto plugin = loader->open(id, path);
+	for (const auto& loader : loaders_) {
+		auto plugin = loader->open(id, path);
 
-        if (plugin)
-            return plugin;
-    }
+		if (plugin)
+			return plugin;
+	}
 
-    return nullptr;
+	return nullptr;
 }
 
 auto plugin_service::find(std::string_view id) -> std::shared_ptr<plugin>
 {
-    for (const auto& loader : loaders_) {
-        try {
-            auto plugin = loader->find(id);
+	for (const auto& loader : loaders_) {
+		try {
+			auto plugin = loader->find(id);
 
-            if (plugin)
-                return plugin;
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning("plugin", id) << ex.what() << std::endl;
-        }
-    }
+			if (plugin)
+				return plugin;
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning("plugin", id) << ex.what() << std::endl;
+		}
+	}
 
-    return nullptr;
+	return nullptr;
 }
 
 void plugin_service::load(std::string_view id, std::string_view path)
 {
-    if (has(id))
-        throw plugin_error(plugin_error::already_exists, id);
+	if (has(id))
+		throw plugin_error(plugin_error::already_exists, id);
 
-    std::shared_ptr<plugin> plugin;
+	std::shared_ptr<plugin> plugin;
 
-    if (path.empty())
-        plugin = find(id);
-    else
-        plugin = open(id, std::move(path));
+	if (path.empty())
+		plugin = find(id);
+	else
+		plugin = open(id, std::move(path));
 
-    if (!plugin)
-        throw plugin_error(plugin_error::not_found, id);
+	if (!plugin)
+		throw plugin_error(plugin_error::not_found, id);
 
-    plugin->set_options(get_options(id));
-    plugin->set_formats(get_formats(id));
-    plugin->set_paths(get_paths(id));
+	plugin->set_options(get_options(id));
+	plugin->set_formats(get_formats(id));
+	plugin->set_paths(get_paths(id));
 
-    exec(plugin, &plugin::handle_load, irccd_);
-    add(std::move(plugin));
+	exec(plugin, &plugin::handle_load, irccd_);
+	add(std::move(plugin));
 }
 
 void plugin_service::reload(std::string_view id)
 {
-    auto plugin = get(id);
+	auto plugin = get(id);
 
-    if (!plugin)
-        throw plugin_error(plugin_error::not_found, id);
+	if (!plugin)
+		throw plugin_error(plugin_error::not_found, id);
 
-    exec(plugin, &plugin::handle_reload, irccd_);
+	exec(plugin, &plugin::handle_reload, irccd_);
 }
 
 void plugin_service::unload(std::string_view id)
 {
-    const auto find = [id] (const auto& plg) {
-        return plg->get_id() == id;
-    };
+	const auto find = [id] (const auto& plg) {
+		return plg->get_id() == id;
+	};
 
-    const auto it = std::find_if(plugins_.begin(), plugins_.end(), find);
+	const auto it = std::find_if(plugins_.begin(), plugins_.end(), find);
 
-    if (it == plugins_.end())
-        throw plugin_error(plugin_error::not_found, id);
+	if (it == plugins_.end())
+		throw plugin_error(plugin_error::not_found, id);
 
-    // Erase first, in case of throwing.
-    const auto save = *it;
+	// Erase first, in case of throwing.
+	const auto save = *it;
 
-    plugins_.erase(it);
-    exec(save, &plugin::handle_unload, irccd_);
+	plugins_.erase(it);
+	exec(save, &plugin::handle_unload, irccd_);
 }
 
 void plugin_service::clear() noexcept
 {
-    while (plugins_.size() > 0) {
-        const auto plugin = plugins_[0];
+	while (plugins_.size() > 0) {
+		const auto plugin = plugins_[0];
 
-        try {
-            unload(plugin->get_id());
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning(*plugin) << ex.what() << std::endl;
-        }
-    }
+		try {
+			unload(plugin->get_id());
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning(*plugin) << ex.what() << std::endl;
+		}
+	}
 }
 
 void plugin_service::load(const config& cfg) noexcept
 {
-    for (const auto& option : cfg.get("plugins")) {
-        if (!string_util::is_identifier(option.key()))
-            continue;
+	for (const auto& option : cfg.get("plugins")) {
+		if (!string_util::is_identifier(option.get_key()))
+			continue;
 
-        auto id = option.key();
-        auto p = get(id);
+		auto id = option.get_key();
+		auto p = get(id);
 
-        // Reload the plugin if already loaded.
-        if (p) {
-            p->set_options(get_options(id));
-            p->set_formats(get_formats(id));
-            p->set_paths(get_paths(id));
-        } else {
-            try {
-                load(id, option.value());
-            } catch (const std::exception& ex) {
-                irccd_.get_log().warning("plugin", id) << ex.what() << std::endl;
-            }
-        }
-    }
+		// Reload the plugin if already loaded.
+		if (p) {
+			p->set_options(get_options(id));
+			p->set_formats(get_formats(id));
+			p->set_paths(get_paths(id));
+		} else {
+			try {
+				load(id, option.get_value());
+			} catch (const std::exception& ex) {
+				irccd_.get_log().warning("plugin", id) << ex.what() << std::endl;
+			}
+		}
+	}
 }
 
 namespace logger {
 
 auto loggable_traits<plugin>::get_category(const plugin&) -> std::string_view
 {
-    return "plugin";
+	return "plugin";
 }
 
 auto loggable_traits<plugin>::get_component(const plugin& plugin) -> std::string_view
 {
-    return plugin.get_id();
+	return plugin.get_id();
 }
 
 } // !logger
--- a/libirccd/irccd/daemon/plugin_service.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/plugin_service.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -43,211 +43,211 @@
  */
 class plugin_service {
 public:
-    /**
-     * \brief Map of plugins.
-     */
-    using plugins = std::vector<std::shared_ptr<plugin>>;
+	/**
+	 * \brief Map of plugins.
+	 */
+	using plugins = std::vector<std::shared_ptr<plugin>>;
 
-    /**
-     * \brief List of loaders.
-     */
-    using plugin_loaders = std::vector<std::unique_ptr<plugin_loader>>;
+	/**
+	 * \brief List of loaders.
+	 */
+	using plugin_loaders = std::vector<std::unique_ptr<plugin_loader>>;
 
 private:
-    irccd& irccd_;
-    plugins plugins_;
-    plugin_loaders loaders_;
+	irccd& irccd_;
+	plugins plugins_;
+	plugin_loaders loaders_;
 
 public:
-    /**
-     * Create the plugin service.
-     *
-     * \param irccd the irccd instance
-     */
-    plugin_service(irccd& irccd) noexcept;
+	/**
+	 * Create the plugin service.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	plugin_service(irccd& irccd) noexcept;
 
-    /**
-     * Destroy plugins.
-     */
-    virtual ~plugin_service();
+	/**
+	 * Destroy plugins.
+	 */
+	virtual ~plugin_service();
 
-    /**
-     * Get the list of plugins.
-     *
-     * \return the list of plugins
-     */
-    auto all() const noexcept -> plugins;
+	/**
+	 * Get the list of plugins.
+	 *
+	 * \return the list of plugins
+	 */
+	auto all() const noexcept -> plugins;
 
-    /**
-     * Check if a plugin is loaded.
-     *
-     * \param id the plugin id
-     * \return true if has plugin
-     */
-    auto has(std::string_view id) const noexcept -> bool;
+	/**
+	 * Check if a plugin is loaded.
+	 *
+	 * \param id the plugin id
+	 * \return true if has plugin
+	 */
+	auto has(std::string_view id) const noexcept -> bool;
 
-    /**
-     * Get a loaded plugin or null if not found.
-     *
-     * \param id the plugin id
-     * \return the plugin or empty one if not found
-     */
-    auto get(std::string_view id) const noexcept -> std::shared_ptr<plugin>;
+	/**
+	 * Get a loaded plugin or null if not found.
+	 *
+	 * \param id the plugin id
+	 * \return the plugin or empty one if not found
+	 */
+	auto get(std::string_view id) const noexcept -> std::shared_ptr<plugin>;
 
-    /**
-     * Find a loaded plugin.
-     *
-     * \param id the plugin id
-     * \return the plugin
-     * \throw plugin_error on errors
-     */
-    auto require(std::string_view id) const -> std::shared_ptr<plugin>;
+	/**
+	 * Find a loaded plugin.
+	 *
+	 * \param id the plugin id
+	 * \return the plugin
+	 * \throw plugin_error on errors
+	 */
+	auto require(std::string_view id) const -> std::shared_ptr<plugin>;
 
-    /**
-     * Add the specified plugin to the registry.
-     *
-     * \pre plg != nullptr
-     * \param plg the plugin
-     * \note the plugin is only added to the list, no action is performed on it
-     */
-    void add(std::shared_ptr<plugin> plg);
+	/**
+	 * Add the specified plugin to the registry.
+	 *
+	 * \pre plg != nullptr
+	 * \param plg the plugin
+	 * \note the plugin is only added to the list, no action is performed on it
+	 */
+	void add(std::shared_ptr<plugin> plg);
 
-    /**
-     * Add a loader.
-     *
-     * \pre loader != nullptr
-     * \param loader the loader
-     */
-    void add_loader(std::unique_ptr<plugin_loader> loader);
+	/**
+	 * Add a loader.
+	 *
+	 * \pre loader != nullptr
+	 * \param loader the loader
+	 */
+	void add_loader(std::unique_ptr<plugin_loader> loader);
 
-    /**
-     * Get the configuration for the specified plugin.
-     *
-     * \param id the plugin id
-     * \return the configuration
-     */
-    auto get_options(std::string_view id) -> plugin::map;
+	/**
+	 * Get the configuration for the specified plugin.
+	 *
+	 * \param id the plugin id
+	 * \return the configuration
+	 */
+	auto get_options(std::string_view id) -> plugin::map;
 
-    /**
-     * Get the formats for the specified plugin.
-     *
-     * \param id the plugin id
-     * \return the formats
-     */
-    auto get_formats(std::string_view id) -> plugin::map;
+	/**
+	 * Get the formats for the specified plugin.
+	 *
+	 * \param id the plugin id
+	 * \return the formats
+	 */
+	auto get_formats(std::string_view id) -> plugin::map;
 
-    /**
-     * Get the paths for the specified plugin.
-     *
-     * If none is defined, return the default ones.
-     *
-     * \param id the plugin id
-     * \return the paths
-     */
-    auto get_paths(std::string_view id) -> plugin::map;
+	/**
+	 * Get the paths for the specified plugin.
+	 *
+	 * If none is defined, return the default ones.
+	 *
+	 * \param id the plugin id
+	 * \return the paths
+	 */
+	auto get_paths(std::string_view id) -> plugin::map;
 
-    /**
-     * Generic function for opening the plugin at the given path.
-     *
-     * This function will search for every pluginLoader and call open() on it,
-     * the first one that success will be returned.
-     *
-     * \param id the plugin id
-     * \param path the path to the file
-     * \return the plugin or nullptr on failures
-     */
-    auto open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>;
+	/**
+	 * Generic function for opening the plugin at the given path.
+	 *
+	 * This function will search for every pluginLoader and call open() on it,
+	 * the first one that success will be returned.
+	 *
+	 * \param id the plugin id
+	 * \param path the path to the file
+	 * \return the plugin or nullptr on failures
+	 */
+	auto open(std::string_view id, std::string_view path) -> std::shared_ptr<plugin>;
 
-    /**
-     * Generic function for finding a plugin.
-     *
-     * \param id the plugin id
-     * \return the plugin or nullptr on failures
-     */
-    auto find(std::string_view id) -> std::shared_ptr<plugin>;
+	/**
+	 * Generic function for finding a plugin.
+	 *
+	 * \param id the plugin id
+	 * \return the plugin or nullptr on failures
+	 */
+	auto find(std::string_view id) -> std::shared_ptr<plugin>;
 
-    /**
-     * Convenient wrapper that loads a plugin, call handle_load and add it to
-     * the registry.
-     *
-     * Any errors are printed using logger.
-     *
-     * \param id the plugin id
-     * \param path the optional path (searched if empty)
-     */
-    void load(std::string_view name, std::string_view path = "");
+	/**
+	 * Convenient wrapper that loads a plugin, call handle_load and add it to
+	 * the registry.
+	 *
+	 * Any errors are printed using logger.
+	 *
+	 * \param id the plugin id
+	 * \param path the optional path (searched if empty)
+	 */
+	void load(std::string_view name, std::string_view path = "");
 
-    /**
-     * Unload a plugin and remove it.
-     *
-     * \param id the plugin id
-     * \param name the plugin id
-     */
-    void unload(std::string_view id);
+	/**
+	 * Unload a plugin and remove it.
+	 *
+	 * \param id the plugin id
+	 * \param name the plugin id
+	 */
+	void unload(std::string_view id);
 
-    /**
-     * Reload a plugin by calling onReload.
-     *
-     * \param id the plugin id
-     * \throw std::exception on failures
-     */
-    void reload(std::string_view id);
+	/**
+	 * Reload a plugin by calling onReload.
+	 *
+	 * \param id the plugin id
+	 * \throw std::exception on failures
+	 */
+	void reload(std::string_view id);
 
-    /**
-     * Call a plugin function and throw an exception with the following errors:
-     *
-     *   - plugin_error::not_found if not loaded
-     *   - plugin_error::exec_error if function failed
-     *
-     * \pre plugin != nullptr
-     * \param plugin the plugin
-     * \param fn the plugin member function (pointer to member)
-     * \param args the arguments to pass
-     */
-    template <typename Func, typename... Args>
-    void exec(std::shared_ptr<plugin> plugin, Func fn, Args&&... args)
-    {
-        assert(plugin);
+	/**
+	 * Call a plugin function and throw an exception with the following errors:
+	 *
+	 *   - plugin_error::not_found if not loaded
+	 *   - plugin_error::exec_error if function failed
+	 *
+	 * \pre plugin != nullptr
+	 * \param plugin the plugin
+	 * \param fn the plugin member function (pointer to member)
+	 * \param args the arguments to pass
+	 */
+	template <typename Func, typename... Args>
+	void exec(std::shared_ptr<plugin> plugin, Func fn, Args&&... args)
+	{
+		assert(plugin);
 
-        // TODO: replace with C++17 std::invoke.
-        try {
-            ((*plugin).*(fn))(std::forward<Args>(args)...);
-        } catch (const std::exception& ex) {
-            throw plugin_error(plugin_error::exec_error, plugin->get_name(), ex.what());
-        } catch (...) {
-            throw plugin_error(plugin_error::exec_error, plugin->get_name());
-        }
-    }
+		// TODO: replace with C++17 std::invoke.
+		try {
+			((*plugin).*(fn))(std::forward<Args>(args)...);
+		} catch (const std::exception& ex) {
+			throw plugin_error(plugin_error::exec_error, plugin->get_name(), ex.what());
+		} catch (...) {
+			throw plugin_error(plugin_error::exec_error, plugin->get_name());
+		}
+	}
 
-    /**
-     * Overloaded function.
-     *
-     * \param name the plugin name
-     * \param fn the plugin member function (pointer to member)
-     * \param args the arguments to pass
-     */
-    template <typename Func, typename... Args>
-    void exec(const std::string& name, Func fn, Args&&... args)
-    {
-        auto plugin = find(name);
+	/**
+	 * Overloaded function.
+	 *
+	 * \param name the plugin name
+	 * \param fn the plugin member function (pointer to member)
+	 * \param args the arguments to pass
+	 */
+	template <typename Func, typename... Args>
+	void exec(const std::string& name, Func fn, Args&&... args)
+	{
+		auto plugin = find(name);
 
-        if (!plugin)
-            throw plugin_error(plugin_error::not_found, plugin->get_name());
+		if (!plugin)
+			throw plugin_error(plugin_error::not_found, plugin->get_name());
 
-        exec(plugin, fn, std::forward<Args>(args)...);
-    }
+		exec(plugin, fn, std::forward<Args>(args)...);
+	}
 
-    /**
-     * Remove all plugins.
-     */
-    void clear() noexcept;
+	/**
+	 * Remove all plugins.
+	 */
+	void clear() noexcept;
 
-    /**
-     * Load all plugins.
-     *
-     * \param cfg the config
-     */
-    void load(const config& cfg) noexcept;
+	/**
+	 * Load all plugins.
+	 *
+	 * \param cfg the config
+	 */
+	void load(const config& cfg) noexcept;
 };
 
 namespace logger {
@@ -260,21 +260,21 @@
  */
 template <>
 struct loggable_traits<plugin> {
-    /**
-     * Return "plugin"
-     *
-     * \param plugin the plugin
-     * \return the category
-     */
-    static auto get_category(const plugin& plugin) -> std::string_view;
+	/**
+	 * Return "plugin"
+	 *
+	 * \param plugin the plugin
+	 * \return the category
+	 */
+	static auto get_category(const plugin& plugin) -> std::string_view;
 
-    /**
-     * Return the plugin id.
-     *
-     * \param plugin the plugin
-     * \return the plugin id
-     */
-    static auto get_component(const plugin& plugin) -> std::string_view;
+	/**
+	 * Return the plugin id.
+	 *
+	 * \param plugin the plugin
+	 * \return the plugin id
+	 */
+	static auto get_component(const plugin& plugin) -> std::string_view;
 };
 
 } // !logger
--- a/libirccd/irccd/daemon/rule.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -23,68 +23,58 @@
 
 namespace irccd {
 
-bool rule::match_set(const set& set, const std::string& value) const noexcept
+auto rule::match_set(const set& set, const std::string& value) const noexcept -> bool
 {
-    return value.empty() || set.empty() || set.count(value) == 1;
+	return value.empty() || set.empty() || set.count(value) == 1;
 }
 
-rule::rule(set servers, set channels, set origins, set plugins, set events, action action)
-    : servers_(std::move(servers))
-    , channels_(std::move(channels))
-    , origins_(std::move(origins))
-    , plugins_(std::move(plugins))
-    , events_(std::move(events))
-    , action_(action)
-{
-}
-
-bool rule::match(std::string_view server,
+auto rule::match(std::string_view server,
                  std::string_view channel,
                  std::string_view nick,
                  std::string_view plugin,
-                 std::string_view event) const noexcept
+                 std::string_view event) const noexcept -> bool
 {
-    const auto tolower = [] (auto str) noexcept -> std::string {
-        std::string ret(str);
-        std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
-        return ret;
-    };
+	const auto tolower = [] (auto str) noexcept -> std::string {
+		std::string ret(str);
+		std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
+		return ret;
+	};
 
-    return match_set(servers_, tolower(server)) &&
-           match_set(channels_, tolower(channel)) &&
-           match_set(origins_, tolower(nick)) &&
-           match_set(plugins_, tolower(plugin)) &&
-           match_set(events_, std::string(event));
+	return match_set(servers, tolower(server)) &&
+	       match_set(channels, tolower(channel)) &&
+	       match_set(origins, tolower(nick)) &&
+	       match_set(plugins, tolower(plugin)) &&
+	       match_set(events, std::string(event));
 }
 
-const std::error_category& rule_category()
+auto rule_category() -> const std::error_category&
 {
-    static const class category : public std::error_category {
-    public:
-        const char* name() const noexcept override
-        {
-            return "rule";
-        }
+	static const class category : public std::error_category {
+	public:
+		const char* name() const noexcept override
+		{
+			return "rule";
+		}
 
-        std::string message(int e) const override
-        {
-            switch (static_cast<rule_error::error>(e)) {
-            case rule_error::invalid_action:
-                return "invalid rule action";
-            case rule_error::invalid_index:
-                return "invalid rule index";
-            default:
-                return "no error";
-            }
-        }
-    } category;
+		std::string message(int e) const override
+		{
+			switch (static_cast<rule_error::error>(e)) {
+			case rule_error::invalid_action:
+				return "invalid rule action";
+			case rule_error::invalid_index:
+				return "invalid rule index";
+			default:
+				return "no error";
+			}
+		}
+	} category;
 
-    return category;
+	return category;
 }
 
-std::error_code make_error_code(rule_error::error e)
+auto make_error_code(rule_error::error e) -> std::error_code
 {
-    return {static_cast<int>(e), rule_category()};
+	return {static_cast<int>(e), rule_category()};
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/rule.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,191 +36,48 @@
 /**
  * \brief Manage rule to activate or deactive events.
  */
-class rule {
-public:
-    /**
-     * List of criterias.
-     */
-    using set = std::set<std::string>;
-
-    /**
-     * \brief Rule action type.
-     */
-    enum class action {
-        accept,         //!< The event is accepted (default)
-        drop            //!< The event is dropped
-    };
-
-private:
-    set servers_;
-    set channels_;
-    set origins_;
-    set plugins_;
-    set events_;
-    action action_{action::accept};
-
-    /*
-     * Check if a set contains the value and return true if it is or return
-     * true if value is empty (which means applicable).
-     */
-    bool match_set(const set&, const std::string&) const noexcept;
+struct rule {
+	/**
+	 * List of criterias.
+	 */
+	using set = std::set<std::string>;
 
-public:
-    /**
-     * Rule constructor.
-     *
-     * \param servers the server list
-     * \param channels the channels
-     * \param nicknames the nicknames
-     * \param plugins the plugins
-     * \param events the events
-     * \param action the rule action
-     * \throw std::invalid_argument if events are invalid
-     */
-    rule(set servers = {},
-         set channels = {},
-         set nicknames = {},
-         set plugins = {},
-         set events = {},
-         action action = action::accept);
+	/**
+	 * \brief Rule action type.
+	 */
+	enum class action_type {
+		accept,         //!< The event is accepted (default)
+		drop            //!< The event is dropped
+	};
 
-    /**
-     * Check if that rule apply for the given criterias.
-     *
-     * \param server the server
-     * \param channel the channel
-     * \param nick the origin
-     * \param plugin the plugin
-     * \param event the event
-     * \return true if match
-     */
-    bool match(std::string_view server,
-               std::string_view channel,
-               std::string_view nick,
-               std::string_view plugin,
-               std::string_view event) const noexcept;
-
-    /**
-     * Get the action.
-     *
-     * \return the action
-     */
-    inline action get_action() const noexcept
-    {
-        return action_;
-    }
-
-    /**
-     * Set the action.
-     *
-     * \pre action must be valid
-     */
-    inline void set_action(action action) noexcept
-    {
-        assert(action == action::accept || action == action::drop);
-
-        action_ = action;
-    }
+	set servers;
+	set channels;
+	set origins;
+	set plugins;
+	set events;
+	action_type action{action_type::accept};
 
-    /**
-     * Get the servers.
-     *
-     * \return the servers
-     */
-    inline const set& get_servers() const noexcept
-    {
-        return servers_;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the servers
-     */
-    inline set& get_servers() noexcept
-    {
-        return servers_;
-    }
-
-    /**
-     * Get the channels.
-     *
-     * \return the channels
-     */
-    inline const set& get_channels() const noexcept
-    {
-        return channels_;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the channels
-     */
-    inline set& get_channels() noexcept
-    {
-        return channels_;
-    }
-
-    /**
-     * Get the origins.
-     *
-     * \return the origins
-     */
-    inline const set& get_origins() const noexcept
-    {
-        return origins_;
-    }
+	/*
+	 * Check if a set contains the value and return true if it is or return
+	 * true if value is empty (which means applicable).
+	 */
+	auto match_set(const set&, const std::string&) const noexcept -> bool;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the origins
-     */
-    inline set& get_origins() noexcept
-    {
-        return origins_;
-    }
-
-    /**
-     * Get the plugins.
-     *
-     * \return the plugins
-     */
-    inline const set& get_plugins() const noexcept
-    {
-        return plugins_;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the plugins
-     */
-    inline set& get_plugins() noexcept
-    {
-        return plugins_;
-    }
-
-    /**
-     * Get the events.
-     *
-     * \return the events
-     */
-    inline const set& get_events() const noexcept
-    {
-        return events_;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the events
-     */
-    inline set& get_events() noexcept
-    {
-        return events_;
-    }
+	/**
+	 * Check if that rule apply for the given criterias.
+	 *
+	 * \param server the server
+	 * \param channel the channel
+	 * \param nick the origin
+	 * \param plugin the plugin
+	 * \param event the event
+	 * \return true if match
+	 */
+	auto match(std::string_view server,
+	           std::string_view channel,
+	           std::string_view nick,
+	           std::string_view plugin,
+	           std::string_view event) const noexcept -> bool;
 };
 
 /**
@@ -228,24 +85,24 @@
  */
 class rule_error : public std::system_error {
 public:
-    /**
-     * \brief Rule related errors.
-     */
-    enum error {
-        //!< No error.
-        no_error = 0,
+	/**
+	 * \brief Rule related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
 
-        //!< Invalid action given.
-        invalid_action,
+		//!< Invalid action given.
+		invalid_action,
 
-        //!< Invalid rule index.
-        invalid_index,
-    };
+		//!< Invalid rule index.
+		invalid_index,
+	};
 
-    /**
-     * Inherited constructors.
-     */
-    using system_error::system_error;
+	/**
+	 * Inherited constructors.
+	 */
+	using system_error::system_error;
 };
 
 /**
@@ -253,14 +110,14 @@
  *
  * \return the singleton
  */
-const std::error_category& rule_category();
+auto rule_category() -> const std::error_category&;
 
 /**
  * Create a std::error_code from rule_error::error enum.
  *
  * \param e the error code
  */
-std::error_code make_error_code(rule_error::error e);
+auto make_error_code(rule_error::error e) -> std::error_code;
 
 } // !irccd
 
--- a/libirccd/irccd/daemon/rule_service.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule_service.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,105 +29,110 @@
 namespace irccd {
 
 rule_service::rule_service(irccd &irccd)
-    : irccd_(irccd)
+	: irccd_(irccd)
 {
 }
 
+auto rule_service::list() const noexcept -> const std::vector<rule>&
+{
+	return rules_;
+}
+
 void rule_service::add(rule rule)
 {
-    rules_.push_back(std::move(rule));
+	rules_.push_back(std::move(rule));
 }
 
 void rule_service::insert(rule rule, unsigned position)
 {
-    assert(position <= rules_.size());
+	assert(position <= rules_.size());
 
-    rules_.insert(rules_.begin() + position, std::move(rule));
+	rules_.insert(rules_.begin() + position, std::move(rule));
 }
 
 void rule_service::remove(unsigned position)
 {
-    assert(position < rules_.size());
+	assert(position < rules_.size());
 
-    rules_.erase(rules_.begin() + position);
+	rules_.erase(rules_.begin() + position);
 }
 
-const rule &rule_service::require(unsigned position) const
+auto rule_service::require(unsigned position) const -> const rule&
 {
-    if (position >= rules_.size())
-        throw rule_error(rule_error::invalid_index);
+	if (position >= rules_.size())
+		throw rule_error(rule_error::invalid_index);
 
-    return rules_[position];
+	return rules_[position];
 }
 
-rule &rule_service::require(unsigned position)
+auto rule_service::require(unsigned position) -> rule&
 {
-    if (position >= rules_.size())
-        throw rule_error(rule_error::invalid_index);
+	if (position >= rules_.size())
+		throw rule_error(rule_error::invalid_index);
 
-    return rules_[position];
+	return rules_[position];
 }
 
-bool rule_service::solve(std::string_view server,
+auto rule_service::solve(std::string_view server,
                          std::string_view channel,
                          std::string_view origin,
                          std::string_view plugin,
-                         std::string_view event) noexcept
+                         std::string_view event) noexcept -> bool
 {
-    bool result = true;
+	bool result = true;
 
-    irccd_.get_log().debug("rule", "")
-        << "solving for server=" << server
-        << ", channel=" << channel
-        << ", origin=" << origin
-        << ", plugin=" << plugin
-        << ", event=" << event << std::endl;
+	irccd_.get_log().debug("rule", "")
+		<< "solving for server=" << server
+		<< ", channel=" << channel
+		<< ", origin=" << origin
+		<< ", plugin=" << plugin
+		<< ", event=" << event << std::endl;
 
-    int i = 0;
-    for (const auto& rule : rules_) {
-        auto action = rule.get_action() == rule::action::accept ? "accept" : "drop";
+	int i = 0;
+	for (const auto& rule : rules_) {
+		auto action = rule.action == rule::action_type::accept ? "accept" : "drop";
 
-        irccd_.get_log().debug(rule) << "candidate "  << i++ << ":" << std::endl;
-        irccd_.get_log().debug(rule) << "  servers: "  << string_util::join(rule.get_servers()) << std::endl;
-        irccd_.get_log().debug(rule) << "  channels: " << string_util::join(rule.get_channels()) << std::endl;
-        irccd_.get_log().debug(rule) << "  origins: "  << string_util::join(rule.get_origins()) << std::endl;
-        irccd_.get_log().debug(rule) << "  plugins: "  << string_util::join(rule.get_plugins()) << std::endl;
-        irccd_.get_log().debug(rule) << "  events: "   << string_util::join(rule.get_events()) << std::endl;
-        irccd_.get_log().debug(rule) << "  action: "   << action << std::endl;
+		irccd_.get_log().debug(rule) << "candidate "  << i++ << ":" << std::endl;
+		irccd_.get_log().debug(rule) << "  servers: "  << string_util::join(rule.servers) << std::endl;
+		irccd_.get_log().debug(rule) << "  channels: " << string_util::join(rule.channels) << std::endl;
+		irccd_.get_log().debug(rule) << "  origins: "  << string_util::join(rule.origins) << std::endl;
+		irccd_.get_log().debug(rule) << "  plugins: "  << string_util::join(rule.plugins) << std::endl;
+		irccd_.get_log().debug(rule) << "  events: "   << string_util::join(rule.events) << std::endl;
+		irccd_.get_log().debug(rule) << "  action: "   << action << std::endl;
 
-        if (rule.match(server, channel, origin, plugin, event))
-            result = rule.get_action() == rule::action::accept;
-    }
+		if (rule.match(server, channel, origin, plugin, event))
+			result = rule.action == rule::action_type::accept;
+	}
 
-    return result;
+	return result;
 }
 
 void rule_service::load(const config& cfg) noexcept
 {
-    rules_.clear();
+	rules_.clear();
 
-    for (const auto& section : cfg) {
-        if (section.key() != "rule")
-            continue;
+	for (const auto& section : cfg) {
+		if (section.get_key() != "rule")
+			continue;
 
-        try {
-            rules_.push_back(rule_util::from_config(section));
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning("rule", "") << ex.what() << std::endl;
-        }
-    }
+		try {
+			rules_.push_back(rule_util::from_config(section));
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning("rule", "") << ex.what() << std::endl;
+		}
+	}
 }
 
 namespace logger {
 
 auto loggable_traits<rule>::get_category(const rule&) -> std::string_view
 {
-    return "rule";
+	return "rule";
 }
 
 auto loggable_traits<rule>::get_component(const rule&) -> std::string_view
 {
-    return "";
+	return "";
 }
 
 } // !logger
--- a/libirccd/irccd/daemon/rule_service.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule_service.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -41,96 +41,83 @@
  */
 class rule_service {
 private:
-    irccd& irccd_;
-    std::vector<rule> rules_;
+	irccd& irccd_;
+	std::vector<rule> rules_;
 
 public:
-    /**
-     * Create the rule service.
-     */
-    rule_service(irccd& instance);
+	/**
+	 * Create the rule service.
+	 */
+	rule_service(irccd& instance);
 
-    /**
-     * Get the list of rules.
-     *
-     * \return the list of rules
-     */
-    inline const std::vector<rule>& list() const noexcept
-    {
-        return rules_;
-    }
+	/**
+	 * Get the list of rules.
+	 *
+	 * \return the list of rules
+	 */
+	auto list() const noexcept -> const std::vector<rule>&;
 
-    /**
-     * Get the number of rules.
-     *
-     * \return the number of rules
-     */
-    inline std::size_t length() const noexcept
-    {
-        return rules_.size();
-    }
+	/**
+	 * Append a rule.
+	 *
+	 * \param rule the rule to append
+	 */
+	void add(rule rule);
 
-    /**
-     * Append a rule.
-     *
-     * \param rule the rule to append
-     */
-    void add(rule rule);
+	/**
+	 * Insert a new rule at the specified position.
+	 *
+	 * \param rule the rule
+	 * \param position the position
+	 */
+	void insert(rule rule, unsigned position);
 
-    /**
-     * Insert a new rule at the specified position.
-     *
-     * \param rule the rule
-     * \param position the position
-     */
-    void insert(rule rule, unsigned position);
+	/**
+	 * Remove a new rule from the specified position.
+	 *
+	 * \pre position must be valid
+	 * \param position the position
+	 */
+	void remove(unsigned position);
 
-    /**
-     * Remove a new rule from the specified position.
-     *
-     * \pre position must be valid
-     * \param position the position
-     */
-    void remove(unsigned position);
+	/**
+	 * Get a rule at the specified index or throw an exception if not found.
+	 *
+	 * \param position the position
+	 * \return the rule
+	 * \throw std::out_of_range if position is invalid
+	 */
+	auto require(unsigned position) const -> const rule&;
 
-    /**
-     * Get a rule at the specified index or throw an exception if not found.
-     *
-     * \param position the position
-     * \return the rule
-     * \throw std::out_of_range if position is invalid
-     */
-    const rule& require(unsigned position) const;
+	/**
+	 * Overloaded function.
+	 *
+	 * \copydoc require
+	 */
+	auto require(unsigned position) -> rule&;
 
-    /**
-     * Overloaded function.
-     *
-     * \copydoc require
-     */
-    rule& require(unsigned position);
+	/**
+	 * Resolve the action to execute with the specified list of rules.
+	 *
+	 * \param server the server name
+	 * \param channel the channel name
+	 * \param origin the origin
+	 * \param plugin the plugin name
+	 * \param event the event name (e.g onKick)
+	 * \return true if the plugin must be called
+	 */
+	auto solve(std::string_view server,
+	           std::string_view channel,
+	           std::string_view origin,
+	           std::string_view plugin,
+	           std::string_view event) noexcept -> bool;
 
-    /**
-     * Resolve the action to execute with the specified list of rules.
-     *
-     * \param server the server name
-     * \param channel the channel name
-     * \param origin the origin
-     * \param plugin the plugin name
-     * \param event the event name (e.g onKick)
-     * \return true if the plugin must be called
-     */
-    bool solve(std::string_view server,
-               std::string_view channel,
-               std::string_view origin,
-               std::string_view plugin,
-               std::string_view event) noexcept;
-
-    /**
-     * Load rules from the configuration.
-     *
-     * \param cfg the config
-     */
-    void load(const config& cfg) noexcept;
+	/**
+	 * Load rules from the configuration.
+	 *
+	 * \param cfg the config
+	 */
+	void load(const config& cfg) noexcept;
 };
 
 namespace logger {
@@ -140,9 +127,9 @@
 
 template <>
 struct loggable_traits<rule> {
-    static auto get_category(const rule& rule) -> std::string_view;
+	static auto get_category(const rule& rule) -> std::string_view;
 
-    static auto get_component(const rule& rule) -> std::string_view;
+	static auto get_component(const rule& rule) -> std::string_view;
 };
 
 } // !logger
--- a/libirccd/irccd/daemon/rule_util.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -21,131 +21,127 @@
 #include "rule.hpp"
 #include "rule_util.hpp"
 
-namespace irccd {
+namespace irccd::rule_util {
 
-namespace rule_util {
-
-rule from_config(const ini::section& sc)
+auto from_config(const ini::section& sc) -> rule
 {
-    // Simple converter from std::vector to std::unordered_set.
-    const auto toset = [] (const auto& v) {
-        return std::set<std::string>(v.begin(), v.end());
-    };
+	// Simple converter from std::vector to std::unordered_set.
+	const auto toset = [] (const auto& v) {
+		return std::set<std::string>(v.begin(), v.end());
+	};
 
-    rule::set servers, channels, origins, plugins, events;
-    rule::action action = rule::action::accept;
+	rule::set servers, channels, origins, plugins, events;
+	rule::action_type action = rule::action_type::accept;
 
-    // Get the sets.
-    ini::section::const_iterator it;
+	// Get the sets.
+	ini::section::const_iterator it;
 
-    if ((it = sc.find("servers")) != sc.end())
-        servers = toset(*it);
-    if ((it = sc.find("channels")) != sc.end())
-        channels = toset(*it);
-    if ((it = sc.find("origins")) != sc.end())
-        origins = toset(*it);
-    if ((it = sc.find("plugins")) != sc.end())
-        plugins = toset(*it);
-    if ((it = sc.find("channels")) != sc.end())
-        channels = toset(*it);
-    if ((it = sc.find("events")) != sc.end())
-        events = toset(*it);
+	if ((it = sc.find("servers")) != sc.end())
+		servers = toset(*it);
+	if ((it = sc.find("channels")) != sc.end())
+		channels = toset(*it);
+	if ((it = sc.find("origins")) != sc.end())
+		origins = toset(*it);
+	if ((it = sc.find("plugins")) != sc.end())
+		plugins = toset(*it);
+	if ((it = sc.find("channels")) != sc.end())
+		channels = toset(*it);
+	if ((it = sc.find("events")) != sc.end())
+		events = toset(*it);
 
-    // Get the action.
-    auto actionstr = sc.get("action").value();
+	// Get the action.
+	auto actionstr = sc.get("action").get_value();
 
-    if (actionstr == "drop")
-        action = rule::action::drop;
-    else if (actionstr == "accept")
-        action = rule::action::accept;
-    else
-        throw rule_error(rule_error::invalid_action);
+	if (actionstr == "drop")
+		action = rule::action_type::drop;
+	else if (actionstr == "accept")
+		action = rule::action_type::accept;
+	else
+		throw rule_error(rule_error::invalid_action);
 
-    return {
-        std::move(servers),
-        std::move(channels),
-        std::move(origins),
-        std::move(plugins),
-        std::move(events),
-        action
-    };
+	return {
+		std::move(servers),
+		std::move(channels),
+		std::move(origins),
+		std::move(plugins),
+		std::move(events),
+		action
+	};
 }
 
-rule from_json(const nlohmann::json& json)
+auto from_json(const nlohmann::json& json) -> rule
 {
-    const auto toset = [] (auto object, auto name) {
-        rule::set result;
+	const auto toset = [] (auto object, auto name) {
+		rule::set result;
 
-        for (const auto& s : object[name])
-            if (s.is_string())
-                result.insert(s.template get<std::string>());
+		for (const auto& s : object[name])
+			if (s.is_string())
+				result.insert(s.template get<std::string>());
 
-        return result;
-    };
-    const auto toaction = [] (const auto& object, const auto& name) {
-        const auto v = object.find(name);
+		return result;
+	};
+	const auto toaction = [] (const auto& object, const auto& name) {
+		const auto v = object.find(name);
 
-        if (v == object.end() || !v->is_string())
-            throw rule_error(rule_error::invalid_action);
+		if (v == object.end() || !v->is_string())
+			throw rule_error(rule_error::invalid_action);
 
-        const auto s = v->template get<std::string>();
+		const auto s = v->template get<std::string>();
 
-        if (s == "accept")
-            return rule::action::accept;
-        if (s == "drop")
-            return rule::action::drop;
+		if (s == "accept")
+			return rule::action_type::accept;
+		if (s == "drop")
+			return rule::action_type::drop;
 
-        throw rule_error(rule_error::invalid_action);
-    };
+		throw rule_error(rule_error::invalid_action);
+	};
 
-    return {
-        toset(json, "servers"),
-        toset(json, "channels"),
-        toset(json, "origins"),
-        toset(json, "plugins"),
-        toset(json, "events"),
-        toaction(json, "action")
-    };
+	return {
+		toset(json, "servers"),
+		toset(json, "channels"),
+		toset(json, "origins"),
+		toset(json, "plugins"),
+		toset(json, "events"),
+		toaction(json, "action")
+	};
 }
 
-unsigned get_index(const nlohmann::json& json, const std::string& key)
+auto get_index(const nlohmann::json& json, const std::string& key) -> unsigned
 {
-    const auto index = json.find(key);
+	const auto index = json.find(key);
 
-    if (index == json.end() || !index->is_number_integer() || index->get<int>() < 0)
-        throw rule_error(rule_error::invalid_index);
+	if (index == json.end() || !index->is_number_integer() || index->get<int>() < 0)
+		throw rule_error(rule_error::invalid_index);
 
-    return index->get<int>();
+	return index->get<int>();
 }
 
-nlohmann::json to_json(const rule& rule)
+auto to_json(const rule& rule) -> nlohmann::json
 {
-    const auto join = [] (const auto& set) {
-        auto array = nlohmann::json::array();
+	const auto join = [] (const auto& set) {
+		auto array = nlohmann::json::array();
 
-        for (const auto& entry : set)
-            array.push_back(entry);
+		for (const auto& entry : set)
+			array.push_back(entry);
 
-        return array;
-    };
-    const auto str = [] (auto action) {
-        switch (action) {
-        case rule::action::accept:
-            return "accept";
-        default:
-            return "drop";
-        }
-    };
+		return array;
+	};
+	const auto str = [] (auto action) {
+		switch (action) {
+		case rule::action_type::accept:
+			return "accept";
+		default:
+			return "drop";
+		}
+	};
 
-    return {
-        { "servers",    join(rule.get_servers())    },
-        { "channels",   join(rule.get_channels())   },
-        { "plugins",    join(rule.get_plugins())    },
-        { "events",     join(rule.get_events())     },
-        { "action",     str(rule.get_action())      }
-    };
+	return {
+		{ "servers",    join(rule.servers)      },
+		{ "channels",   join(rule.channels)     },
+		{ "plugins",    join(rule.plugins)      },
+		{ "events",     join(rule.events)       },
+		{ "action",     str(rule.action)        }
+	};
 }
 
-} // !rule_util
-
-} // !irccd
+} // !irccd::rule_util
--- a/libirccd/irccd/daemon/rule_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/rule_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,7 +35,8 @@
 } // !ini
 
 class config;
-class rule;
+
+struct rule;
 
 /**
  * \brief Rule utilities.
@@ -52,7 +53,7 @@
  * \return the new rule
  * \throw rule_error on errors
  */
-rule from_json(const nlohmann::json& json);
+auto from_json(const nlohmann::json& json) -> rule;
 
 /**
  * Load a rule from a INI section.
@@ -61,7 +62,7 @@
  * \return the rule
  * \throw rule_error on errors
  */
-rule from_config(const ini::section& sc);
+auto from_config(const ini::section& sc) -> rule;
 
 /**
  * Convert a rule into a JSON object.
@@ -69,7 +70,7 @@
  * \param rule the rule
  * \throw the JSON representation
  */
-nlohmann::json to_json(const rule& rule);
+auto to_json(const rule& rule) -> nlohmann::json;
 
 } // !rule_util
 
--- a/libirccd/irccd/daemon/server.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,10 +27,10 @@
 #include <stdexcept>
 
 #if !BOOST_OS_WINDOWS
-#  include <sys/types.h>
-#  include <netinet/in.h>
-#  include <arpa/nameser.h>
-#  include <resolv.h>
+#	include <sys/types.h>
+#	include <netinet/in.h>
+#	include <arpa/nameser.h>
+#	include <resolv.h>
 #endif
 
 #include <irccd/json_util.hpp>
@@ -55,14 +55,14 @@
  */
 auto clean_prefix(const std::map<channel_mode, char>& modes, std::string nickname) -> std::string
 {
-    if (nickname.length() == 0)
-        return nickname;
+	if (nickname.length() == 0)
+		return nickname;
 
-    for (const auto& pair : modes)
-        if (nickname[0] == pair.second)
-            nickname.erase(0, 1);
+	for (const auto& pair : modes)
+		if (nickname[0] == pair.second)
+			nickname.erase(0, 1);
 
-    return nickname;
+	return nickname;
 }
 
 /*
@@ -73,686 +73,686 @@
  */
 auto isupport_extract_prefixes(const std::string& line) -> std::map<channel_mode, char>
 {
-    // FIXME: what if line has different size?
-    std::pair<char, char> table[16];
-    std::string buf = line.substr(7);
-    std::map<channel_mode, char> modes;
+	// FIXME: what if line has different size?
+	std::pair<char, char> table[16];
+	std::string buf = line.substr(7);
+	std::map<channel_mode, char> modes;
 
-    for (int i = 0; i < 16; ++i)
-        table[i] = std::make_pair(-1, -1);
+	for (int i = 0; i < 16; ++i)
+		table[i] = std::make_pair(-1, -1);
 
-    int j = 0;
-    bool read_modes = true;
+	int j = 0;
+	bool read_modes = true;
 
-    for (size_t i = 0; i < buf.size(); ++i) {
-        if (buf[i] == '(')
-            continue;
-        if (buf[i] == ')') {
-            j = 0;
-            read_modes = false;
-            continue;
-        }
+	for (size_t i = 0; i < buf.size(); ++i) {
+		if (buf[i] == '(')
+			continue;
+		if (buf[i] == ')') {
+			j = 0;
+			read_modes = false;
+			continue;
+		}
 
-        if (read_modes)
-            table[j++].first = buf[i];
-        else
-            table[j++].second = buf[i];
-    }
+		if (read_modes)
+			table[j++].first = buf[i];
+		else
+			table[j++].second = buf[i];
+	}
 
-    // Put these as a map of mode to prefix.
-    for (int i = 0; i < 16; ++i) {
-        auto key = static_cast<channel_mode>(table[i].first);
-        auto value = table[i].second;
+	// Put these as a map of mode to prefix.
+	for (int i = 0; i < 16; ++i) {
+		auto key = static_cast<channel_mode>(table[i].first);
+		auto value = table[i].second;
 
-        modes.emplace(key, value);
-    }
+		modes.emplace(key, value);
+	}
 
-    return modes;
+	return modes;
 }
 
 } // !namespace
 
 auto server::dispatch_connect(const irc::message&, const recv_handler& handler) -> bool
 {
-    state_ = state::connected;
-    handler({}, connect_event{shared_from_this()});
+	state_ = state::connected;
+	handler({}, connect_event{shared_from_this()});
 
-    for (const auto& channel : rchannels_)
-        join(channel.name, channel.password);
+	for (const auto& channel : rchannels_)
+		join(channel.name, channel.password);
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_endofnames(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    /*
-     * Called when end of name listing has finished on a channel.
-     *
-     * params[0] == originator
-     * params[1] == channel
-     * params[2] == End of NAMES list
-     */
-    if (msg.args.size() < 3 || msg.get(1) == "")
-        return false;
+	/*
+	 * Called when end of name listing has finished on a channel.
+	 *
+	 * params[0] == originator
+	 * params[1] == channel
+	 * params[2] == End of NAMES list
+	 */
+	if (msg.args.size() < 3 || msg.get(1) == "")
+		return false;
 
-    const auto it = names_map_.find(msg.get(1));
+	const auto it = names_map_.find(msg.get(1));
 
-    if (it != names_map_.end()) {
-        handler({}, names_event{
-            shared_from_this(),
-            msg.get(1),
-            std::vector<std::string>(it->second.begin(), it->second.end())
-        });
+	if (it != names_map_.end()) {
+		handler({}, names_event{
+			shared_from_this(),
+			msg.get(1),
+			std::vector<std::string>(it->second.begin(), it->second.end())
+		});
 
-        names_map_.erase(it);
-    }
+		names_map_.erase(it);
+	}
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_endofwhois(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    /*
-     * Called when whois is finished.
-     *
-     * params[0] == originator
-     * params[1] == nickname
-     * params[2] == End of WHOIS list
-     */
-    const auto it = whois_map_.find(msg.get(1));
+	/*
+	 * Called when whois is finished.
+	 *
+	 * params[0] == originator
+	 * params[1] == nickname
+	 * params[2] == End of WHOIS list
+	 */
+	const auto it = whois_map_.find(msg.get(1));
 
-    if (it != whois_map_.end()) {
-        handler({}, whois_event{shared_from_this(), it->second});
-        whois_map_.erase(it);
-    }
+	if (it != whois_map_.end()) {
+		handler({}, whois_event{shared_from_this(), it->second});
+		whois_map_.erase(it);
+	}
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_invite(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    // If join-invite is set, join the channel.
-    if ((flags_ & options::join_invite) == options::join_invite && is_self(msg.get(0)))
-        join(msg.get(1));
+	// If join-invite is set, join the channel.
+	if ((flags_ & options::join_invite) == options::join_invite && is_self(msg.get(0)))
+		join(msg.get(1));
 
-    handler({}, invite_event{shared_from_this(), msg.prefix, msg.get(1), msg.get(0)});
+	handler({}, invite_event{shared_from_this(), msg.prefix, msg.get(1), msg.get(0)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_isupport(const irc::message& msg) -> bool
 {
-    for (unsigned int i = 0; i < msg.args.size(); ++i) {
-        if (msg.get(i).compare(0, 6, "PREFIX") == 0) {
-            modes_ = isupport_extract_prefixes(msg.get(i));
-            break;
-        }
-    }
+	for (unsigned int i = 0; i < msg.args.size(); ++i) {
+		if (msg.get(i).compare(0, 6, "PREFIX") == 0) {
+			modes_ = isupport_extract_prefixes(msg.get(i));
+			break;
+		}
+	}
 
-    return false;
+	return false;
 }
 
 auto server::dispatch_join(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    if (is_self(msg.prefix))
-        jchannels_.insert(msg.get(0));
+	if (is_self(msg.prefix))
+		jchannels_.insert(msg.get(0));
 
-    handler({}, join_event{shared_from_this(), msg.prefix, msg.get(0)});
+	handler({}, join_event{shared_from_this(), msg.prefix, msg.get(0)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_kick(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    if (is_self(msg.get(1))) {
-        // Remove the channel from the joined list.
-        jchannels_.erase(msg.get(0));
+	if (is_self(msg.get(1))) {
+		// Remove the channel from the joined list.
+		jchannels_.erase(msg.get(0));
 
-        // Rejoin the channel if the option has been set and I was kicked.
-        if ((flags_ & options::auto_rejoin) == options::auto_rejoin)
-            join(msg.get(0));
-    }
+		// Rejoin the channel if the option has been set and I was kicked.
+		if ((flags_ & options::auto_rejoin) == options::auto_rejoin)
+			join(msg.get(0));
+	}
 
-    handler({}, kick_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1), msg.get(2)});
+	handler({}, kick_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1), msg.get(2)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_mode(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    handler({}, mode_event{
-        shared_from_this(),
-        msg.prefix,
-        msg.get(0),
-        msg.get(1),
-        msg.get(2),
-        msg.get(3),
-        msg.get(4)
-    });
+	handler({}, mode_event{
+		shared_from_this(),
+		msg.prefix,
+		msg.get(0),
+		msg.get(1),
+		msg.get(2),
+		msg.get(3),
+		msg.get(4)
+	});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_namreply(const irc::message& msg) -> bool
 {
-    /*
-     * Called multiple times to list clients on a channel.
-     *
-     * params[0] == originator
-     * params[1] == '='
-     * params[2] == channel
-     * params[3] == list of users with their prefixes
-     *
-     * IDEA for the future: maybe give the appropriate mode as a second
-     * parameter in onNames.
-     */
-    if (msg.args.size() < 4 || msg.get(2) == "" || msg.get(3) == "")
-        return false;
+	/*
+	 * Called multiple times to list clients on a channel.
+	 *
+	 * params[0] == originator
+	 * params[1] == '='
+	 * params[2] == channel
+	 * params[3] == list of users with their prefixes
+	 *
+	 * IDEA for the future: maybe give the appropriate mode as a second
+	 * parameter in onNames.
+	 */
+	if (msg.args.size() < 4 || msg.get(2) == "" || msg.get(3) == "")
+		return false;
 
-    auto users = string_util::split(msg.get(3), " \t");
+	auto users = string_util::split(msg.get(3), " \t");
 
-    // The listing may add some prefixes, remove them if needed.
-    for (const auto& u : users)
-        names_map_[msg.get(2)].insert(clean_prefix(modes_, u));
+	// The listing may add some prefixes, remove them if needed.
+	for (const auto& u : users)
+		names_map_[msg.get(2)].insert(clean_prefix(modes_, u));
 
-    return false;
+	return false;
 }
 
 auto server::dispatch_nick(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    // Update our nickname.
-    if (is_self(msg.prefix))
-        nickname_ = msg.get(0);
+	// Update our nickname.
+	if (is_self(msg.prefix))
+		nickname_ = msg.get(0);
 
-    handler({}, nick_event{shared_from_this(), msg.prefix, msg.get(0)});
+	handler({}, nick_event{shared_from_this(), msg.prefix, msg.get(0)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_notice(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    handler({}, notice_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
+	handler({}, notice_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_part(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    // Remove the channel from the joined list if I left a channel.
-    if (is_self(msg.prefix))
-        jchannels_.erase(msg.get(1));
+	// Remove the channel from the joined list if I left a channel.
+	if (is_self(msg.prefix))
+		jchannels_.erase(msg.get(1));
 
-    handler({}, part_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
+	handler({}, part_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_ping(const irc::message& msg) -> bool
 {
-    assert(msg.command == "PING");
+	assert(msg.command == "PING");
 
-    send(str(format("PONG %1%") % msg.get(0)));
+	send(str(format("PONG %1%") % msg.get(0)));
 
-    return false;
+	return false;
 }
 
 auto server::dispatch_privmsg(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    assert(msg.command == "PRIVMSG");
+	assert(msg.command == "PRIVMSG");
 
-    if (msg.is_ctcp(1)) {
-        auto cmd = msg.ctcp(1);
+	if (msg.is_ctcp(1)) {
+		auto cmd = msg.ctcp(1);
 
-        if (cmd.compare(0, 6, "ACTION") == 0)
-            handler({}, me_event{shared_from_this(), msg.prefix, msg.get(0), cmd.substr(7)});
-        else
-            return false;
-    } else
-        handler({}, message_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
+		if (cmd.compare(0, 6, "ACTION") == 0)
+			handler({}, me_event{shared_from_this(), msg.prefix, msg.get(0), cmd.substr(7)});
+		else
+			return false;
+	} else
+		handler({}, message_event{shared_from_this(), msg.prefix, msg.get(0), msg.get(1)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_topic(const irc::message& msg, const recv_handler& handler) -> bool
 {
-    assert(msg.command == "TOPIC");
+	assert(msg.command == "TOPIC");
 
-    handler({}, topic_event{shared_from_this(), msg.get(0), msg.get(1), msg.get(2)});
+	handler({}, topic_event{shared_from_this(), msg.get(0), msg.get(1), msg.get(2)});
 
-    return true;
+	return true;
 }
 
 auto server::dispatch_whoischannels(const irc::message& msg) -> bool
 {
-    /*
-     * Called when we have received channels for one user.
-     *
-     * params[0] == originator
-     * params[1] == nickname
-     * params[2] == list of channels with their prefixes
-     */
-    if (msg.args.size() < 3 || msg.get(1) == "" || msg.get(2) == "")
-        return false;
+	/*
+	 * Called when we have received channels for one user.
+	 *
+	 * params[0] == originator
+	 * params[1] == nickname
+	 * params[2] == list of channels with their prefixes
+	 */
+	if (msg.args.size() < 3 || msg.get(1) == "" || msg.get(2) == "")
+		return false;
 
-    auto it = whois_map_.find(msg.get(1));
+	auto it = whois_map_.find(msg.get(1));
 
-    if (it != whois_map_.end()) {
-        auto channels = string_util::split(msg.get(2), " \t");
+	if (it != whois_map_.end()) {
+		auto channels = string_util::split(msg.get(2), " \t");
 
-        // Clean their prefixes.
-        for (auto& s : channels)
-            s = clean_prefix(modes_, s);
+		// Clean their prefixes.
+		for (auto& s : channels)
+			s = clean_prefix(modes_, s);
 
-        it->second.channels = std::move(channels);
-    }
+		it->second.channels = std::move(channels);
+	}
 
-    return false;
+	return false;
 }
 
 auto server::dispatch_whoisuser(const irc::message& msg) -> bool
 {
-    /*
-     * Called when whois information has been partially received.
-     *
-     * params[0] == originator
-     * params[1] == nickname
-     * params[2] == username
-     * params[3] == host
-     * params[4] == * (no idea what is that)
-     * params[5] == realname
-     */
-    if (msg.args.size() < 6 || msg.get(1) == "" || msg.get(2) == "" || msg.get(3) == "" || msg.get(5) == "")
-        return false;
+	/*
+	 * Called when whois information has been partially received.
+	 *
+	 * params[0] == originator
+	 * params[1] == nickname
+	 * params[2] == username
+	 * params[3] == host
+	 * params[4] == * (no idea what is that)
+	 * params[5] == realname
+	 */
+	if (msg.args.size() < 6 || msg.get(1) == "" || msg.get(2) == "" || msg.get(3) == "" || msg.get(5) == "")
+		return false;
 
-    whois_info info;
+	whois_info info;
 
-    info.nick = msg.get(1);
-    info.user = msg.get(2);
-    info.host = msg.get(3);
-    info.realname = msg.get(5);
+	info.nick = msg.get(1);
+	info.user = msg.get(2);
+	info.host = msg.get(3);
+	info.realname = msg.get(5);
 
-    whois_map_.emplace(info.nick, info);
+	whois_map_.emplace(info.nick, info);
 
-    return false;
+	return false;
 }
 
 auto server::dispatch(const irc::message& message, const recv_handler& handler) -> bool
 {
-    bool handled = false;
+	bool handled = false;
 
-    if (message.is(5))
-        handled = dispatch_isupport(message);
-    else if (message.is(irc::err::nomotd) || message.is(irc::rpl::endofmotd))
-        handled = dispatch_connect(message, handler);
-    else if (message.command == "INVITE")
-        handled = dispatch_invite(message, handler);
-    else if (message.command == "JOIN")
-        handled = dispatch_join(message, handler);
-    else if (message.command == "KICK")
-        handled = dispatch_kick(message, handler);
-    else if (message.command == "MODE")
-        handled = dispatch_mode(message, handler);
-    else if (message.command == "NICK")
-        handled = dispatch_nick(message, handler);
-    else if (message.command == "NOTICE")
-        handled = dispatch_notice(message, handler);
-    else if (message.command == "TOPIC")
-        handled = dispatch_topic(message, handler);
-    else if (message.command == "PART")
-        handled = dispatch_part(message, handler);
-    else if (message.command == "PING")
-        handled = dispatch_ping(message);
-    else if (message.command == "PRIVMSG")
-        handled = dispatch_privmsg(message, handler);
-    else if (message.is(irc::rpl::namreply))
-        handled = dispatch_namreply(message);
-    else if (message.is(irc::rpl::endofnames))
-        handled = dispatch_endofnames(message, handler);
-    else if (message.is(irc::rpl::endofwhois))
-        handled = dispatch_endofwhois(message, handler);
-    else if (message.is(irc::rpl::whoischannels))
-        handled = dispatch_whoischannels(message);
-    else if (message.is(irc::rpl::whoisuser))
-        handled = dispatch_whoisuser(message);
+	if (message.is(5))
+		handled = dispatch_isupport(message);
+	else if (message.is(irc::err::nomotd) || message.is(irc::rpl::endofmotd))
+		handled = dispatch_connect(message, handler);
+	else if (message.command == "INVITE")
+		handled = dispatch_invite(message, handler);
+	else if (message.command == "JOIN")
+		handled = dispatch_join(message, handler);
+	else if (message.command == "KICK")
+		handled = dispatch_kick(message, handler);
+	else if (message.command == "MODE")
+		handled = dispatch_mode(message, handler);
+	else if (message.command == "NICK")
+		handled = dispatch_nick(message, handler);
+	else if (message.command == "NOTICE")
+		handled = dispatch_notice(message, handler);
+	else if (message.command == "TOPIC")
+		handled = dispatch_topic(message, handler);
+	else if (message.command == "PART")
+		handled = dispatch_part(message, handler);
+	else if (message.command == "PING")
+		handled = dispatch_ping(message);
+	else if (message.command == "PRIVMSG")
+		handled = dispatch_privmsg(message, handler);
+	else if (message.is(irc::rpl::namreply))
+		handled = dispatch_namreply(message);
+	else if (message.is(irc::rpl::endofnames))
+		handled = dispatch_endofnames(message, handler);
+	else if (message.is(irc::rpl::endofwhois))
+		handled = dispatch_endofwhois(message, handler);
+	else if (message.is(irc::rpl::whoischannels))
+		handled = dispatch_whoischannels(message);
+	else if (message.is(irc::rpl::whoisuser))
+		handled = dispatch_whoisuser(message);
 
-    return handled;
+	return handled;
 }
 
 void server::handle_send(const std::error_code& code)
 {
-    /*
-     * We don't notify server_service in case of error because in any case the
-     * pending recv() will complete with an error.
-     */
-    queue_.pop_front();
+	/*
+	 * We don't notify server_service in case of error because in any case the
+	 * pending recv() will complete with an error.
+	 */
+	queue_.pop_front();
 
-    if (!code)
-        flush();
+	if (!code)
+		flush();
 }
 
 void server::handle_recv(const std::error_code& code,
-                         const irc::message& message,
-                         const recv_handler& handler)
+						 const irc::message& message,
+						 const recv_handler& handler)
 {
-    /*
-     * Once a message is received, dispatch it to individual dispatch_*
-     * functions. If the function calls handler by itself it returns true
-     * otherwise we call handler with no event to tell the caller the message
-     * has arrived and allowed to call recv() again.
-     */
-    if (code) {
-        disconnect();
-        handler(std::move(code), event(std::monostate()));
-    } else if (!dispatch(message, handler))
-        handler({}, std::monostate{});
+	/*
+	 * Once a message is received, dispatch it to individual dispatch_*
+	 * functions. If the function calls handler by itself it returns true
+	 * otherwise we call handler with no event to tell the caller the message
+	 * has arrived and allowed to call recv() again.
+	 */
+	if (code) {
+		disconnect();
+		handler(std::move(code), event(std::monostate()));
+	} else if (!dispatch(message, handler))
+		handler({}, std::monostate{});
 }
 
 void server::recv(recv_handler handler) noexcept
 {
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    conn_->recv([this, handler, self, c = conn_] (auto code, auto message) {
-        handle_recv(std::move(code), message, handler);
-    });
+	conn_->recv([this, handler, self, c = conn_] (auto code, auto message) {
+		handle_recv(std::move(code), message, handler);
+	});
 }
 
 void server::flush()
 {
-    if (queue_.empty())
-        return;
+	if (queue_.empty())
+		return;
 
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    conn_->send(queue_.front(), [this, self, c = conn_] (auto code) {
-        handle_send(std::move(code));
-    });
+	conn_->send(queue_.front(), [this, self, c = conn_] (auto code) {
+		handle_send(std::move(code));
+	});
 }
 
 void server::identify()
 {
-    state_ = state::identifying;
+	state_ = state::identifying;
 
-    if (!password_.empty())
-        send(str(format("PASS %1%") % password_));
+	if (!password_.empty())
+		send(str(format("PASS %1%") % password_));
 
-    send(str(format("NICK %1%") % nickname_));
-    send(str(format("USER %1% unknown unknown :%2%") % username_ % realname_));
+	send(str(format("NICK %1%") % nickname_));
+	send(str(format("USER %1% unknown unknown :%2%") % username_ % realname_));
 }
 
 void server::handle_wait(const std::error_code& code, const connect_handler& handler)
 {
-    if (code && code != std::errc::operation_canceled)
-        handler(code);
+	if (code && code != std::errc::operation_canceled)
+		handler(code);
 }
 
 void server::handle_connect(const std::error_code& code, const connect_handler& handler)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (code)
-        disconnect();
-    else
-        identify();
+	if (code)
+		disconnect();
+	else
+		identify();
 
-    handler(code);
+	handler(code);
 }
 
 server::server(boost::asio::io_service& service, std::string id, std::string host)
-    : id_(std::move(id))
-    , host_(std::move(host))
-    , service_(service)
-    , timer_(service)
+	: id_(std::move(id))
+	, host_(std::move(host))
+	, service_(service)
+	, timer_(service)
 {
-    assert(!host_.empty());
+	assert(!host_.empty());
 
-    // Initialize nickname and username.
-    auto user = sys::username();
+	// Initialize nickname and username.
+	auto user = sys::username();
 
-    nickname_ = user.empty() ? "irccd" : user;
-    username_ = user.empty() ? "irccd" : user;
+	nickname_ = user.empty() ? "irccd" : user;
+	username_ = user.empty() ? "irccd" : user;
 }
 
 server::~server()
 {
-    conn_ = nullptr;
-    state_ = state::disconnected;
+	conn_ = nullptr;
+	state_ = state::disconnected;
 }
 
 auto server::get_state() const noexcept -> state
 {
-    return state_;
+	return state_;
 }
 
 auto server::get_id() const noexcept -> const std::string&
 {
-    return id_;
+	return id_;
 }
 
 auto server::get_host() const noexcept -> const std::string&
 {
-    return host_;
+	return host_;
 }
 
 auto server::get_password() const noexcept -> const std::string&
 {
-    return password_;
+	return password_;
 }
 
 void server::set_password(std::string password) noexcept
 {
-    password_ = std::move(password);
+	password_ = std::move(password);
 }
 
 auto server::get_port() const noexcept -> std::uint16_t
 {
-    return port_;
+	return port_;
 }
 
 void server::set_port(std::uint16_t port) noexcept
 {
-    port_ = port;
+	port_ = port;
 }
 
 auto server::get_options() const noexcept -> options
 {
-    return flags_;
+	return flags_;
 }
 
 void server::set_options(options flags) noexcept
 {
 #if !defined(IRCCD_HAVE_SSL)
-    assert(!(flags & ssl));
+	assert(!(flags & ssl));
 #endif
 
-    flags_ = flags;
+	flags_ = flags;
 }
 
 auto server::get_nickname() const noexcept -> const std::string&
 {
-    return nickname_;
+	return nickname_;
 }
 
 void server::set_nickname(std::string nickname)
 {
-    if (state_ == state::connected)
-        send(str(format("NICK %1%") % nickname));
-    else
-        nickname_ = std::move(nickname);
+	if (state_ == state::connected)
+		send(str(format("NICK %1%") % nickname));
+	else
+		nickname_ = std::move(nickname);
 }
 
 auto server::get_username() const noexcept -> const std::string&
 {
-    return username_;
+	return username_;
 }
 
 void server::set_username(std::string name) noexcept
 {
-    username_ = std::move(name);
+	username_ = std::move(name);
 }
 
 auto server::get_realname() const noexcept -> const std::string&
 {
-    return realname_;
+	return realname_;
 }
 
 void server::set_realname(std::string realname) noexcept
 {
-    realname_ = std::move(realname);
+	realname_ = std::move(realname);
 }
 
 auto server::get_ctcp_version() const noexcept -> const std::string&
 {
-    return ctcpversion_;
+	return ctcpversion_;
 }
 
 void server::set_ctcp_version(std::string ctcpversion)
 {
-    ctcpversion_ = std::move(ctcpversion);
+	ctcpversion_ = std::move(ctcpversion);
 }
 
 auto server::get_command_char() const noexcept -> const std::string&
 {
-    return command_char_;
+	return command_char_;
 }
 
 void server::set_command_char(std::string command_char) noexcept
 {
-    assert(!command_char.empty());
+	assert(!command_char.empty());
 
-    command_char_ = std::move(command_char);
+	command_char_ = std::move(command_char);
 }
 
 auto server::get_reconnect_delay() const noexcept -> std::uint16_t
 {
-    return recodelay_;
+	return recodelay_;
 }
 
 void server::set_reconnect_delay(std::uint16_t reconnect_delay) noexcept
 {
-    recodelay_ = reconnect_delay;
+	recodelay_ = reconnect_delay;
 }
 
 auto server::get_ping_timeout() const noexcept -> std::uint16_t
 {
-    return timeout_;
+	return timeout_;
 }
 
 void server::set_ping_timeout(std::uint16_t ping_timeout) noexcept
 {
-    timeout_ = ping_timeout;
+	timeout_ = ping_timeout;
 }
 
 auto server::get_channels() const noexcept -> const std::set<std::string>&
 {
-    return jchannels_;
+	return jchannels_;
 }
 
 auto server::is_self(std::string_view target) const noexcept -> bool
 {
-    return nickname_ == irc::user::parse(target).nick;
+	return nickname_ == irc::user::parse(target).nick;
 }
 
 void server::connect(connect_handler handler) noexcept
 {
-    assert(state_ == state::disconnected);
+	assert(state_ == state::disconnected);
 
-    /*
-     * This is needed if irccd is started before DHCP or if DNS cache is
-     * outdated.
-     */
+	/*
+	 * This is needed if irccd is started before DHCP or if DNS cache is
+	 * outdated.
+	 */
 #if !BOOST_OS_WINDOWS
-    (void)res_init();
+	(void)res_init();
 #endif
 
-    if ((flags_ & options::ssl) == options::ssl) {
+	if ((flags_ & options::ssl) == options::ssl) {
 #if defined(IRCCD_HAVE_SSL)
-        conn_ = std::make_unique<irc::tls_connection>(service_);
+		conn_ = std::make_unique<irc::tls_connection>(service_);
 #else
-        /*
-         * If SSL is not compiled in, the caller is responsible of not setting
-         * the flag.
-         */
-        assert((flags_ & options::ssl) != options::ssl);
+		/*
+		 * If SSL is not compiled in, the caller is responsible of not setting
+		 * the flag.
+		 */
+		assert((flags_ & options::ssl) != options::ssl);
 #endif
-    } else
-        conn_ = std::make_unique<irc::ip_connection>(service_);
+	} else
+		conn_ = std::make_unique<irc::ip_connection>(service_);
 
-    jchannels_.clear();
-    state_ = state::connecting;
+	jchannels_.clear();
+	state_ = state::connecting;
 
-    timer_.expires_from_now(boost::posix_time::seconds(timeout_));
-    timer_.async_wait([this, handler] (auto code) {
-        handle_wait(code, handler);
-    });
+	timer_.expires_from_now(boost::posix_time::seconds(timeout_));
+	timer_.async_wait([this, handler] (auto code) {
+		handle_wait(code, handler);
+	});
 
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    conn_->connect(host_, std::to_string(port_), [this, handler, c = conn_] (auto code) {
-        handle_connect(code, handler);
-    });
+	conn_->connect(host_, std::to_string(port_), [this, handler, c = conn_] (auto code) {
+		handle_connect(code, handler);
+	});
 }
 
 void server::disconnect() noexcept
 {
-    conn_ = nullptr;
-    state_ = state::disconnected;
-    queue_.clear();
+	conn_ = nullptr;
+	state_ = state::disconnected;
+	queue_.clear();
 }
 
 void server::invite(std::string_view target, std::string_view channel)
 {
-    assert(!target.empty());
-    assert(!channel.empty());
+	assert(!target.empty());
+	assert(!channel.empty());
 
-    send(str(format("INVITE %1% %2%") % target % channel));
+	send(str(format("INVITE %1% %2%") % target % channel));
 }
 
 void server::join(std::string_view channel, std::string_view password)
 {
-    assert(!channel.empty());
+	assert(!channel.empty());
 
-    auto it = std::find_if(rchannels_.begin(), rchannels_.end(), [&] (const auto& c) {
-        return c.name == channel;
-    });
+	auto it = std::find_if(rchannels_.begin(), rchannels_.end(), [&] (const auto& c) {
+		return c.name == channel;
+	});
 
-    if (it == rchannels_.end())
-        rchannels_.push_back({ std::string(channel), std::string(password) });
-    else
-        *it = { std::string(channel), std::string(password) };
+	if (it == rchannels_.end())
+		rchannels_.push_back({ std::string(channel), std::string(password) });
+	else
+		*it = { std::string(channel), std::string(password) };
 
-    if (state_ == state::connected) {
-        if (password.empty())
-            send(str(format("JOIN %1%") % channel));
-        else
-            send(str(format("JOIN %1% :%2%") % channel % password));
-    }
+	if (state_ == state::connected) {
+		if (password.empty())
+			send(str(format("JOIN %1%") % channel));
+		else
+			send(str(format("JOIN %1% :%2%") % channel % password));
+	}
 }
 
 void server::kick(std::string_view target, std::string_view channel, std::string_view reason)
 {
-    assert(!target.empty());
-    assert(!channel.empty());
+	assert(!target.empty());
+	assert(!channel.empty());
 
-    if (!reason.empty())
-        send(str(format("KICK %1% %2% :%3%") % channel % target % reason));
-    else
-        send(str(format("KICK %1% %2%") % channel % target));
+	if (!reason.empty())
+		send(str(format("KICK %1% %2% :%3%") % channel % target % reason));
+	else
+		send(str(format("KICK %1% %2%") % channel % target));
 }
 
 void server::me(std::string_view target, std::string_view message)
 {
-    assert(!target.empty());
-    assert(!message.empty());
+	assert(!target.empty());
+	assert(!message.empty());
 
-    send(str(format("PRIVMSG %1% :\x01" "ACTION %2%\x01") % target % message));
+	send(str(format("PRIVMSG %1% :\x01" "ACTION %2%\x01") % target % message));
 }
 
 void server::message(std::string_view target, std::string_view message)
 {
-    assert(!target.empty());
-    assert(!message.empty());
+	assert(!target.empty());
+	assert(!message.empty());
 
-    send(str(format("PRIVMSG %1% :%2%") % target % message));
+	send(str(format("PRIVMSG %1% :%2%") % target % message));
 }
 
 void server::mode(std::string_view channel,
@@ -761,147 +761,147 @@
                   std::string_view user,
                   std::string_view mask)
 {
-    assert(!channel.empty());
-    assert(!mode.empty());
+	assert(!channel.empty());
+	assert(!mode.empty());
 
-    std::ostringstream oss;
+	std::ostringstream oss;
 
-    oss << "MODE " << channel << " " << mode;
+	oss << "MODE " << channel << " " << mode;
 
-    if (!limit.empty())
-        oss << " " << limit;
-    if (!user.empty())
-        oss << " " << user;
-    if (!mask.empty())
-        oss << " " << mask;
+	if (!limit.empty())
+		oss << " " << limit;
+	if (!user.empty())
+		oss << " " << user;
+	if (!mask.empty())
+		oss << " " << mask;
 
-    send(oss.str());
+	send(oss.str());
 }
 
 void server::names(std::string_view channel)
 {
-    assert(!channel.empty());
+	assert(!channel.empty());
 
-    send(str(format("NAMES %1%") % channel));
+	send(str(format("NAMES %1%") % channel));
 }
 
 void server::notice(std::string_view target, std::string_view message)
 {
-    assert(!target.empty());
-    assert(!message.empty());
+	assert(!target.empty());
+	assert(!message.empty());
 
-    send(str(format("NOTICE %1% :%2%") % target % message));
+	send(str(format("NOTICE %1% :%2%") % target % message));
 }
 
 void server::part(std::string_view channel, std::string_view reason)
 {
-    assert(!channel.empty());
+	assert(!channel.empty());
 
-    if (!reason.empty())
-        send(str(format("PART %1% :%2%") % channel % reason));
-    else
-        send(str(format("PART %1%") % channel));
+	if (!reason.empty())
+		send(str(format("PART %1% :%2%") % channel % reason));
+	else
+		send(str(format("PART %1%") % channel));
 }
 
 void server::send(std::string_view raw)
 {
-    assert(!raw.empty());
+	assert(!raw.empty());
 
-    if (state_ == state::identifying || state_ == state::connected) {
-        const auto in_progress = queue_.size() > 0;
+	if (state_ == state::identifying || state_ == state::connected) {
+		const auto in_progress = queue_.size() > 0;
 
-        queue_.push_back(std::string(raw));
+		queue_.push_back(std::string(raw));
 
-        if (!in_progress)
-            flush();
-    } else
-        queue_.push_back(std::string(raw));
+		if (!in_progress)
+			flush();
+	} else
+		queue_.push_back(std::string(raw));
 }
 
 void server::topic(std::string_view channel, std::string_view topic)
 {
-    assert(!channel.empty());
+	assert(!channel.empty());
 
-    if (!topic.empty())
-        send(str(format("TOPIC %1% :%2%") % channel % topic));
-    else
-        send(str(format("TOPIC %1%") % channel));
+	if (!topic.empty())
+		send(str(format("TOPIC %1% :%2%") % channel % topic));
+	else
+		send(str(format("TOPIC %1%") % channel));
 }
 
 void server::whois(std::string_view target)
 {
-    assert(!target.empty());
+	assert(!target.empty());
 
-    send(str(format("WHOIS %1% %2%") % target % target));
+	send(str(format("WHOIS %1% %2%") % target % target));
 }
 
 server_error::server_error(error code) noexcept
-    : system_error(make_error_code(code))
+	: system_error(make_error_code(code))
 {
 }
 
 auto server_category() -> const std::error_category&
 {
-    static const class category : public std::error_category {
-    public:
-        const char* name() const noexcept override
-        {
-            return "server";
-        }
+	static const class category : public std::error_category {
+	public:
+		const char* name() const noexcept override
+		{
+			return "server";
+		}
 
-        std::string message(int e) const override
-        {
-            switch (static_cast<server_error::error>(e)) {
-            case server_error::not_found:
-                return "server not found";
-            case server_error::invalid_identifier:
-                return "invalid server identifier";
-            case server_error::not_connected:
-                return "server is not connected";
-            case server_error::already_connected:
-                return "server is already connected";
-            case server_error::already_exists:
-                return "server already exists";
-            case server_error::invalid_port:
-                return "invalid port number specified";
-            case server_error::invalid_reconnect_delay:
-                return "invalid reconnect delay number";
-            case server_error::invalid_hostname:
-                return "invalid hostname";
-            case server_error::invalid_channel:
-                return "invalid or empty channel";
-            case server_error::invalid_mode:
-                return "invalid or empty mode";
-            case server_error::invalid_nickname:
-                return "invalid nickname";
-            case server_error::invalid_username:
-                return "invalid username";
-            case server_error::invalid_realname:
-                return "invalid realname";
-            case server_error::invalid_password:
-                return "invalid password";
-            case server_error::invalid_ping_timeout:
-                return "invalid ping timeout";
-            case server_error::invalid_ctcp_version:
-                return "invalid CTCP VERSION";
-            case server_error::invalid_command_char:
-                return "invalid character command";
-            case server_error::invalid_message:
-                return "invalid message";
-            case server_error::ssl_disabled:
-                return "ssl is not enabled";
-            default:
-                return "no error";
-            }
-        }
-    } category;
+		std::string message(int e) const override
+		{
+			switch (static_cast<server_error::error>(e)) {
+			case server_error::not_found:
+				return "server not found";
+			case server_error::invalid_identifier:
+				return "invalid server identifier";
+			case server_error::not_connected:
+				return "server is not connected";
+			case server_error::already_connected:
+				return "server is already connected";
+			case server_error::already_exists:
+				return "server already exists";
+			case server_error::invalid_port:
+				return "invalid port number specified";
+			case server_error::invalid_reconnect_delay:
+				return "invalid reconnect delay number";
+			case server_error::invalid_hostname:
+				return "invalid hostname";
+			case server_error::invalid_channel:
+				return "invalid or empty channel";
+			case server_error::invalid_mode:
+				return "invalid or empty mode";
+			case server_error::invalid_nickname:
+				return "invalid nickname";
+			case server_error::invalid_username:
+				return "invalid username";
+			case server_error::invalid_realname:
+				return "invalid realname";
+			case server_error::invalid_password:
+				return "invalid password";
+			case server_error::invalid_ping_timeout:
+				return "invalid ping timeout";
+			case server_error::invalid_ctcp_version:
+				return "invalid CTCP VERSION";
+			case server_error::invalid_command_char:
+				return "invalid character command";
+			case server_error::invalid_message:
+				return "invalid message";
+			case server_error::ssl_disabled:
+				return "ssl is not enabled";
+			default:
+				return "no error";
+			}
+		}
+	} category;
 
-    return category;
+	return category;
 }
 
 auto make_error_code(server_error::error e) -> std::error_code
 {
-    return {static_cast<int>(e), server_category()};
+	return {static_cast<int>(e), server_category()};
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/server.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -48,184 +48,184 @@
  * \brief Prefixes for nicknames.
  */
 enum class channel_mode {
-    creator         = 'O',                  //!< Channel creator
-    half_op         = 'h',                  //!< Half operator
-    op              = 'o',                  //!< Channel operator
-    protection      = 'a',                  //!< Unkillable
-    voiced          = 'v'                   //!< Voice power
+	creator         = 'O',                  //!< Channel creator
+	half_op         = 'h',                  //!< Half operator
+	op              = 'o',                  //!< Channel operator
+	protection      = 'a',                  //!< Unkillable
+	voiced          = 'v'                   //!< Voice power
 };
 
 /**
  * \brief A channel to join with an optional password.
  */
 struct channel {
-    std::string name;                       //!< the channel to join
-    std::string password;                   //!< the optional password
+	std::string name;                       //!< the channel to join
+	std::string password;                   //!< the optional password
 };
 
 /**
  * \brief Describe a whois information.
  */
 struct whois_info {
-    std::string nick;                       //!< user's nickname
-    std::string user;                       //!< user's user
-    std::string host;                       //!< hostname
-    std::string realname;                   //!< realname
-    std::vector<std::string> channels;      //!< the channels where the user is
+	std::string nick;                       //!< user's nickname
+	std::string user;                       //!< user's user
+	std::string host;                       //!< hostname
+	std::string realname;                   //!< realname
+	std::vector<std::string> channels;      //!< the channels where the user is
 };
 
 /**
  * \brief Connection success event.
  */
 struct connect_event {
-    std::shared_ptr<class server> server;   //!< The server.
+	std::shared_ptr<class server> server;   //!< The server.
 };
 
 /**
  * \brief Connection success event.
  */
 struct disconnect_event {
-    std::shared_ptr<class server> server;   //!< The server.
+	std::shared_ptr<class server> server;   //!< The server.
 };
 
 /**
  * \brief Invite event.
  */
 struct invite_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string nickname;                   //!< The nickname (you).
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string nickname;                   //!< The nickname (you).
 };
 
 /**
  * \brief Join event.
  */
 struct join_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
 };
 
 /**
  * \brief Kick event.
  */
 struct kick_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string target;                     //!< The target.
-    std::string reason;                     //!< The reason (Optional).
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string target;                     //!< The target.
+	std::string reason;                     //!< The reason (Optional).
 };
 
 /**
  * \brief Message event.
  */
 struct message_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string message;                    //!< The message.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string message;                    //!< The message.
 };
 
 /**
  * \brief CTCP action event.
  */
 struct me_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string message;                    //!< The message.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string message;                    //!< The message.
 };
 
 /**
  * \brief Mode event.
  */
 struct mode_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel or target.
-    std::string mode;                       //!< The mode.
-    std::string limit;                      //!< The optional limit.
-    std::string user;                       //!< The optional user.
-    std::string mask;                       //!< The optional ban mask.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel or target.
+	std::string mode;                       //!< The mode.
+	std::string limit;                      //!< The optional limit.
+	std::string user;                       //!< The optional user.
+	std::string mask;                       //!< The optional ban mask.
 };
 
 /**
  * \brief Names listing event.
  */
 struct names_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string channel;                    //!< The channel.
-    std::vector<std::string> names;         //!< The names.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string channel;                    //!< The channel.
+	std::vector<std::string> names;         //!< The names.
 };
 
 /**
  * \brief Nick change event.
  */
 struct nick_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string nickname;                   //!< The new nickname.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string nickname;                   //!< The new nickname.
 };
 
 /**
  * \brief Notice event.
  */
 struct notice_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel or target.
-    std::string message;                    //!< The message.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel or target.
+	std::string message;                    //!< The message.
 };
 
 /**
  * \brief Part event.
  */
 struct part_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string reason;                     //!< The reason.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string reason;                     //!< The reason.
 };
 
 /**
  * \brief Topic event.
  */
 struct topic_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    std::string origin;                     //!< The originator.
-    std::string channel;                    //!< The channel.
-    std::string topic;                      //!< The topic message.
+	std::shared_ptr<class server> server;   //!< The server.
+	std::string origin;                     //!< The originator.
+	std::string channel;                    //!< The channel.
+	std::string topic;                      //!< The topic message.
 };
 
 /**
  * \brief Whois event.
  */
 struct whois_event {
-    std::shared_ptr<class server> server;   //!< The server.
-    whois_info whois;                       //!< The whois information.
+	std::shared_ptr<class server> server;   //!< The server.
+	whois_info whois;                       //!< The whois information.
 };
 
 /**
  * \brief Store all possible events.
  */
 using event = std::variant<
-    std::monostate,
-    connect_event,
-    disconnect_event,
-    invite_event,
-    join_event,
-    kick_event,
-    me_event,
-    message_event,
-    mode_event,
-    names_event,
-    nick_event,
-    notice_event,
-    part_event,
-    topic_event,
-    whois_event
+	std::monostate,
+	connect_event,
+	disconnect_event,
+	invite_event,
+	join_event,
+	kick_event,
+	me_event,
+	message_event,
+	mode_event,
+	names_event,
+	nick_event,
+	notice_event,
+	part_event,
+	topic_event,
+	whois_event
 >;
 
 /**
@@ -236,446 +236,445 @@
  */
 class server : public std::enable_shared_from_this<server> {
 public:
-    /**
-     * Completion handler once network connection is complete.
-     */
-    using connect_handler = std::function<void (std::error_code)>;
+	/**
+	 * Completion handler once network connection is complete.
+	 */
+	using connect_handler = std::function<void (std::error_code)>;
 
-    /**
-     * Completion handler once a network message has arrived.
-     */
-    using recv_handler = std::function<void (std::error_code, event)>;
+	/**
+	 * Completion handler once a network message has arrived.
+	 */
+	using recv_handler = std::function<void (std::error_code, event)>;
 
-    /**
-     * \brief Various options for server.
-     */
-    enum class options : std::uint8_t {
-        none            = 0,            //!< No options
-        ipv6            = (1 << 0),     //!< Connect using IPv6
-        ssl             = (1 << 1),     //!< Use SSL
-        ssl_verify      = (1 << 2),     //!< Verify SSL
-        auto_rejoin     = (1 << 3),     //!< Auto rejoin a kick
-        auto_reconnect  = (1 << 4),     //!< Auto reconnect on disconnection
-        join_invite     = (1 << 5)      //!< Join a channel on invitation
-    };
+	/**
+	 * \brief Various options for server.
+	 */
+	enum class options : std::uint8_t {
+		none            = 0,            //!< No options
+		ipv6            = (1 << 0),     //!< Connect using IPv6
+		ssl             = (1 << 1),     //!< Use SSL
+		ssl_verify      = (1 << 2),     //!< Verify SSL
+		auto_rejoin     = (1 << 3),     //!< Auto rejoin a kick
+		auto_reconnect  = (1 << 4),     //!< Auto reconnect on disconnection
+		join_invite     = (1 << 5)      //!< Join a channel on invitation
+	};
 
-    /**
-     * \brief Describe current server state.
-     */
-    enum class state : std::uint8_t {
-        disconnected,                   //!< not connected at all,
-        connecting,                     //!< network connection in progress,
-        identifying,                    //!< sending nick, user and password commands,
-        connected                       //!< ready for use.
-    };
-
+	/**
+	 * \brief Describe current server state.
+	 */
+	enum class state : std::uint8_t {
+		disconnected,                   //!< not connected at all,
+		connecting,                     //!< network connection in progress,
+		identifying,                    //!< sending nick, user and password commands,
+		connected                       //!< ready for use.
+	};
 protected:
-    /*
-     * \brief Server state.
-     */
-    state state_{state::disconnected};
+	/*
+	 * \brief Server state.
+	 */
+	state state_{state::disconnected};
 
 private:
-    // Requested and joined channels.
-    std::vector<channel> rchannels_;
-    std::set<std::string> jchannels_;
+	// Requested and joined channels.
+	std::vector<channel> rchannels_;
+	std::set<std::string> jchannels_;
 
-    // Identifier.
-    std::string id_;
+	// Identifier.
+	std::string id_;
 
-    // Connection information.
-    std::string host_;
-    std::string password_;
-    std::uint16_t port_{6667};
-    options flags_{options::none};
+	// Connection information.
+	std::string host_;
+	std::string password_;
+	std::uint16_t port_{6667};
+	options flags_{options::none};
 
-    // Identity.
-    std::string nickname_;
-    std::string username_;
-    std::string realname_{"IRC Client Daemon"};
-    std::string ctcpversion_{"IRC Client Daemon"};
+	// Identity.
+	std::string nickname_;
+	std::string username_;
+	std::string realname_{"IRC Client Daemon"};
+	std::string ctcpversion_{"IRC Client Daemon"};
 
-    // Settings.
-    std::string command_char_{"!"};
-    std::uint16_t recodelay_{30};
-    std::uint16_t timeout_{1000};
+	// Settings.
+	std::string command_char_{"!"};
+	std::uint16_t recodelay_{30};
+	std::uint16_t timeout_{1000};
 
-    // Server information.
-    std::map<channel_mode, char> modes_;
+	// Server information.
+	std::map<channel_mode, char> modes_;
 
-    // Misc.
-    boost::asio::io_service& service_;
-    boost::asio::deadline_timer timer_;
-    std::shared_ptr<irc::connection> conn_;
-    std::deque<std::string> queue_;
-    std::map<std::string, std::set<std::string>> names_map_;
-    std::map<std::string, whois_info> whois_map_;
+	// Misc.
+	boost::asio::io_service& service_;
+	boost::asio::deadline_timer timer_;
+	std::shared_ptr<irc::connection> conn_;
+	std::deque<std::string> queue_;
+	std::map<std::string, std::set<std::string>> names_map_;
+	std::map<std::string, whois_info> whois_map_;
 
-    auto dispatch_connect(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_endofnames(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_endofwhois(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_invite(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_isupport(const irc::message&) -> bool;
-    auto dispatch_join(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_kick(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_mode(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_namreply(const irc::message&) -> bool;
-    auto dispatch_nick(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_notice(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_part(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_ping(const irc::message&) -> bool;
-    auto dispatch_privmsg(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_topic(const irc::message&, const recv_handler&) -> bool;
-    auto dispatch_whoischannels(const irc::message&) -> bool;
-    auto dispatch_whoisuser(const irc::message&) -> bool;
-    auto dispatch(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_connect(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_endofnames(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_endofwhois(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_invite(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_isupport(const irc::message&) -> bool;
+	auto dispatch_join(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_kick(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_mode(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_namreply(const irc::message&) -> bool;
+	auto dispatch_nick(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_notice(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_part(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_ping(const irc::message&) -> bool;
+	auto dispatch_privmsg(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_topic(const irc::message&, const recv_handler&) -> bool;
+	auto dispatch_whoischannels(const irc::message&) -> bool;
+	auto dispatch_whoisuser(const irc::message&) -> bool;
+	auto dispatch(const irc::message&, const recv_handler&) -> bool;
 
-    // I/O and connection.
-    void flush();
-    void identify();
-    void handle_send(const std::error_code&);
-    void handle_recv(const std::error_code&, const irc::message&, const recv_handler&);
-    void handle_wait(const std::error_code&, const connect_handler&);
-    void handle_connect(const std::error_code&, const connect_handler&);
+	// I/O and connection.
+	void flush();
+	void identify();
+	void handle_send(const std::error_code&);
+	void handle_recv(const std::error_code&, const irc::message&, const recv_handler&);
+	void handle_wait(const std::error_code&, const connect_handler&);
+	void handle_connect(const std::error_code&, const connect_handler&);
 
 public:
-    /**
-     * Construct a server.
-     *
-     * \pre !host.empty()
-     * \param service the service
-     * \param name the identifier
-     * \param host the hostname
-     */
-    server(boost::asio::io_service& service, std::string id, std::string host = "localhost");
+	/**
+	 * Construct a server.
+	 *
+	 * \pre !host.empty()
+	 * \param service the service
+	 * \param name the identifier
+	 * \param host the hostname
+	 */
+	server(boost::asio::io_service& service, std::string id, std::string host = "localhost");
 
-    /**
-     * Destructor. Close the connection if needed.
-     */
-    virtual ~server();
+	/**
+	 * Destructor. Close the connection if needed.
+	 */
+	virtual ~server();
 
-    /**
-     * Get the current server state.
-     *
-     * \return the state
-     */
-    auto get_state() const noexcept -> state;
+	/**
+	 * Get the current server state.
+	 *
+	 * \return the state
+	 */
+	auto get_state() const noexcept -> state;
 
-    /**
-     * Get the server identifier.
-     *
-     * \return the id
-     */
-    auto get_id() const noexcept -> const std::string&;
+	/**
+	 * Get the server identifier.
+	 *
+	 * \return the id
+	 */
+	auto get_id() const noexcept -> const std::string&;
 
-    /**
-     * Get the hostname.
-     *
-     * \return the hostname
-     */
-    auto get_host() const noexcept -> const std::string&;
+	/**
+	 * Get the hostname.
+	 *
+	 * \return the hostname
+	 */
+	auto get_host() const noexcept -> const std::string&;
 
-    /**
-     * Get the password.
-     *
-     * \return the password
-     */
-    auto get_password() const noexcept -> const std::string&;
+	/**
+	 * Get the password.
+	 *
+	 * \return the password
+	 */
+	auto get_password() const noexcept -> const std::string&;
 
-    /**
-     * Set the password.
-     *
-     * An empty password means no password.
-     *
-     * \param password the password
-     */
-    void set_password(std::string password) noexcept;
+	/**
+	 * Set the password.
+	 *
+	 * An empty password means no password.
+	 *
+	 * \param password the password
+	 */
+	void set_password(std::string password) noexcept;
 
-    /**
-     * Get the port.
-     *
-     * \return the port
-     */
-    auto get_port() const noexcept -> std::uint16_t;
+	/**
+	 * Get the port.
+	 *
+	 * \return the port
+	 */
+	auto get_port() const noexcept -> std::uint16_t;
 
-    /**
-     * Set the port.
-     *
-     * \param port the port
-     */
-    void set_port(std::uint16_t port) noexcept;
+	/**
+	 * Set the port.
+	 *
+	 * \param port the port
+	 */
+	void set_port(std::uint16_t port) noexcept;
 
-    /**
-     * Get the options flags.
-     *
-     * \return the flags
-     */
-    auto get_options() const noexcept -> options;
+	/**
+	 * Get the options flags.
+	 *
+	 * \return the flags
+	 */
+	auto get_options() const noexcept -> options;
 
-    /**
-     * Set the options flags.
-     *
-     * \param flags the flags
-     */
-    void set_options(options flags) noexcept;
+	/**
+	 * Set the options flags.
+	 *
+	 * \param flags the flags
+	 */
+	void set_options(options flags) noexcept;
 
-    /**
-     * Get the nickname.
-     *
-     * \return the nickname
-     */
-    auto get_nickname() const noexcept -> const std::string&;
+	/**
+	 * Get the nickname.
+	 *
+	 * \return the nickname
+	 */
+	auto get_nickname() const noexcept -> const std::string&;
 
-    /**
-     * Set the nickname.
-     *
-     * If the server is connected, send a nickname command to the IRC server,
-     * otherwise change it instantly.
-     *
-     * \param nickname the nickname
-     */
-    void set_nickname(std::string nickname);
+	/**
+	 * Set the nickname.
+	 *
+	 * If the server is connected, send a nickname command to the IRC server,
+	 * otherwise change it instantly.
+	 *
+	 * \param nickname the nickname
+	 */
+	virtual void set_nickname(std::string nickname);
 
-    /**
-     * Get the username.
-     *
-     * \return the username
-     */
-    auto get_username() const noexcept -> const std::string&;
+	/**
+	 * Get the username.
+	 *
+	 * \return the username
+	 */
+	auto get_username() const noexcept -> const std::string&;
 
-    /**
-     * Set the username.
-     *
-     * \param name the username
-     * \note the username will be changed on the next connection
-     */
-    void set_username(std::string name) noexcept;
+	/**
+	 * Set the username.
+	 *
+	 * \param name the username
+	 * \note the username will be changed on the next connection
+	 */
+	void set_username(std::string name) noexcept;
 
-    /**
-     * Get the realname.
-     *
-     * \return the realname
-     */
-    auto get_realname() const noexcept -> const std::string&;
+	/**
+	 * Get the realname.
+	 *
+	 * \return the realname
+	 */
+	auto get_realname() const noexcept -> const std::string&;
 
-    /**
-     * Set the realname.
-     *
-     * \param realname the username
-     * \note the username will be changed on the next connection
-     */
-    void set_realname(std::string realname) noexcept;
+	/**
+	 * Set the realname.
+	 *
+	 * \param realname the username
+	 * \note the username will be changed on the next connection
+	 */
+	void set_realname(std::string realname) noexcept;
 
-    /**
-     * Get the CTCP version.
-     *
-     * \return the CTCP version
-     */
-    auto get_ctcp_version() const noexcept -> const std::string&;
+	/**
+	 * Get the CTCP version.
+	 *
+	 * \return the CTCP version
+	 */
+	auto get_ctcp_version() const noexcept -> const std::string&;
 
-    /**
-     * Set the CTCP version.
-     *
-     * \param ctcpversion the version
-     */
-    void set_ctcp_version(std::string ctcpversion);
+	/**
+	 * Set the CTCP version.
+	 *
+	 * \param ctcpversion the version
+	 */
+	void set_ctcp_version(std::string ctcpversion);
 
-    /**
-     * Get the command character.
-     *
-     * \return the character
-     */
-    auto get_command_char() const noexcept -> const std::string&;
+	/**
+	 * Get the command character.
+	 *
+	 * \return the character
+	 */
+	auto get_command_char() const noexcept -> const std::string&;
 
-    /**
-     * Set the command character.
-     *
-     * \pre !command_char_.empty()
-     * \param command_char the command character
-     */
-    void set_command_char(std::string command_char) noexcept;
+	/**
+	 * Set the command character.
+	 *
+	 * \pre !command_char_.empty()
+	 * \param command_char the command character
+	 */
+	void set_command_char(std::string command_char) noexcept;
 
-    /**
-     * Get the reconnection delay before retrying.
-     *
-     * \return the number of seconds
-     */
-    auto get_reconnect_delay() const noexcept -> std::uint16_t;
+	/**
+	 * Get the reconnection delay before retrying.
+	 *
+	 * \return the number of seconds
+	 */
+	auto get_reconnect_delay() const noexcept -> std::uint16_t;
 
-    /**
-     * Set the number of seconds before retrying.
-     *
-     * \param reconnect_delay the number of seconds
-     */
-    void set_reconnect_delay(std::uint16_t reconnect_delay) noexcept;
+	/**
+	 * Set the number of seconds before retrying.
+	 *
+	 * \param reconnect_delay the number of seconds
+	 */
+	void set_reconnect_delay(std::uint16_t reconnect_delay) noexcept;
 
-    /**
-     * Get the ping timeout.
-     *
-     * \return the ping timeout
-     */
-    auto get_ping_timeout() const noexcept -> std::uint16_t;
+	/**
+	 * Get the ping timeout.
+	 *
+	 * \return the ping timeout
+	 */
+	auto get_ping_timeout() const noexcept -> std::uint16_t;
 
-    /**
-     * Set the ping timeout before considering a server as dead.
-     *
-     * \param ping_timeout the delay in seconds
-     */
-    void set_ping_timeout(std::uint16_t ping_timeout) noexcept;
+	/**
+	 * Set the ping timeout before considering a server as dead.
+	 *
+	 * \param ping_timeout the delay in seconds
+	 */
+	void set_ping_timeout(std::uint16_t ping_timeout) noexcept;
 
-    /**
-     * Get the list of channels joined.
-     *
-     * \return the channels
-     */
-    auto get_channels() const noexcept -> const std::set<std::string>&;
+	/**
+	 * Get the list of channels joined.
+	 *
+	 * \return the channels
+	 */
+	auto get_channels() const noexcept -> const std::set<std::string>&;
 
-    /**
-     * Determine if the nickname is the bot itself.
-     *
-     * \param nick the nickname to check
-     * \return true if it is the bot
-     */
-    auto is_self(std::string_view nick) const noexcept -> bool;
+	/**
+	 * Determine if the nickname is the bot itself.
+	 *
+	 * \param nick the nickname to check
+	 * \return true if it is the bot
+	 */
+	auto is_self(std::string_view nick) const noexcept -> bool;
 
-    /**
-     * Start connecting.
-     *
-     * This only initiate TCP connection and/or SSL handshaking, the identifying
-     * process may take some time and you must repeatedly call recv() to wait
-     * for connect_event.
-     *
-     * \pre handler != nullptr
-     * \param handler the completion handler
-     * \note the server must be kept alive until completion
-     */
-    virtual void connect(connect_handler handler) noexcept;
+	/**
+	 * Start connecting.
+	 *
+	 * This only initiate TCP connection and/or SSL handshaking, the identifying
+	 * process may take some time and you must repeatedly call recv() to wait
+	 * for connect_event.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the completion handler
+	 * \note the server must be kept alive until completion
+	 */
+	virtual void connect(connect_handler handler) noexcept;
 
-    /**
-     * Force disconnection.
-     */
-    virtual void disconnect() noexcept;
+	/**
+	 * Force disconnection.
+	 */
+	virtual void disconnect() noexcept;
 
-    /**
-     * Receive next event.
-     *
-     * \pre handler != nullptr
-     * \param handler the handler
-     * \note the server must be kept alive until completion
-     */
-    virtual void recv(recv_handler handler) noexcept;
+	/**
+	 * Receive next event.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the handler
+	 * \note the server must be kept alive until completion
+	 */
+	virtual void recv(recv_handler handler) noexcept;
 
-    /**
-     * Invite a user to a channel.
-     *
-     * \param target the target nickname
-     * \param channel the channel
-     */
-    virtual void invite(std::string_view target, std::string_view channel);
+	/**
+	 * Invite a user to a channel.
+	 *
+	 * \param target the target nickname
+	 * \param channel the channel
+	 */
+	virtual void invite(std::string_view target, std::string_view channel);
 
-    /**
-     * Join a channel, the password is optional and can be kept empty.
-     *
-     * \param channel the channel to join
-     * \param password the optional password
-     */
-    virtual void join(std::string_view channel, std::string_view password = "");
+	/**
+	 * Join a channel, the password is optional and can be kept empty.
+	 *
+	 * \param channel the channel to join
+	 * \param password the optional password
+	 */
+	virtual void join(std::string_view channel, std::string_view password = "");
 
-    /**
-     * Kick someone from the channel. Please be sure to have the rights
-     * on that channel because errors won't be reported.
-     *
-     * \param target the target to kick
-     * \param channel from which channel
-     * \param reason the optional reason
-     */
-    virtual void kick(std::string_view target,
-                      std::string_view channel,
-                      std::string_view reason = "");
+	/**
+	 * Kick someone from the channel. Please be sure to have the rights
+	 * on that channel because errors won't be reported.
+	 *
+	 * \param target the target to kick
+	 * \param channel from which channel
+	 * \param reason the optional reason
+	 */
+	virtual void kick(std::string_view target,
+	                  std::string_view channel,
+	                  std::string_view reason = "");
 
-    /**
-     * Send a CTCP Action as known as /me. The target may be either a
-     * channel or a nickname.
-     *
-     * \param target the nickname or the channel
-     * \param message the message
-     */
-    virtual void me(std::string_view target, std::string_view message);
+	/**
+	 * Send a CTCP Action as known as /me. The target may be either a
+	 * channel or a nickname.
+	 *
+	 * \param target the nickname or the channel
+	 * \param message the message
+	 */
+	virtual void me(std::string_view target, std::string_view message);
 
-    /**
-     * Send a message to the specified target or channel.
-     *
-     * \param target the target
-     * \param message the message
-     */
-    virtual void message(std::string_view target, std::string_view message);
+	/**
+	 * Send a message to the specified target or channel.
+	 *
+	 * \param target the target
+	 * \param message the message
+	 */
+	virtual void message(std::string_view target, std::string_view message);
 
-    /**
-     * Change channel/user mode.
-     *
-     * \param channel the channel or nickname
-     * \param mode the mode
-     * \param limit the optional limit
-     * \param user the optional user
-     * \param mask the optional ban mask
-     */
-    virtual void mode(std::string_view channel,
-                      std::string_view mode,
-                      std::string_view limit = "",
-                      std::string_view user = "",
-                      std::string_view mask = "");
+	/**
+	 * Change channel/user mode.
+	 *
+	 * \param channel the channel or nickname
+	 * \param mode the mode
+	 * \param limit the optional limit
+	 * \param user the optional user
+	 * \param mask the optional ban mask
+	 */
+	virtual void mode(std::string_view channel,
+	                  std::string_view mode,
+	                  std::string_view limit = "",
+	                  std::string_view user = "",
+	                  std::string_view mask = "");
 
-    /**
-     * Request the list of names.
-     *
-     * \param channel the channel
-     */
-    virtual void names(std::string_view channel);
+	/**
+	 * Request the list of names.
+	 *
+	 * \param channel the channel
+	 */
+	virtual void names(std::string_view channel);
 
-    /**
-     * Send a private notice.
-     *
-     * \param target the target
-     * \param message the notice message
-     */
-    virtual void notice(std::string_view target, std::string_view message);
+	/**
+	 * Send a private notice.
+	 *
+	 * \param target the target
+	 * \param message the notice message
+	 */
+	virtual void notice(std::string_view target, std::string_view message);
 
-    /**
-     * Part from a channel.
-     *
-     * Please note that the reason is not supported on all servers so if you
-     * want portability, don't provide it.
-     *
-     * \param channel the channel to leave
-     * \param reason the optional reason
-     */
-    virtual void part(std::string_view channel, std::string_view reason = "");
+	/**
+	 * Part from a channel.
+	 *
+	 * Please note that the reason is not supported on all servers so if you
+	 * want portability, don't provide it.
+	 *
+	 * \param channel the channel to leave
+	 * \param reason the optional reason
+	 */
+	virtual void part(std::string_view channel, std::string_view reason = "");
 
-    /**
-     * Send a raw message to the IRC server. You don't need to add
-     * message terminators.
-     *
-     * If the server is not yet connected, the command is postponed and will be
-     * ran when ready.
-     *
-     * \param raw the raw message (without `\r\n\r\n`)
-     */
-    virtual void send(std::string_view raw);
+	/**
+	 * Send a raw message to the IRC server. You don't need to add
+	 * message terminators.
+	 *
+	 * If the server is not yet connected, the command is postponed and will be
+	 * ran when ready.
+	 *
+	 * \param raw the raw message (without `\r\n\r\n`)
+	 */
+	virtual void send(std::string_view raw);
 
-    /**
-     * Change the channel topic.
-     *
-     * \param channel the channel
-     * \param topic the desired topic
-     */
-    virtual void topic(std::string_view channel, std::string_view topic);
+	/**
+	 * Change the channel topic.
+	 *
+	 * \param channel the channel
+	 * \param topic the desired topic
+	 */
+	virtual void topic(std::string_view channel, std::string_view topic);
 
-    /**
-     * Request for whois information.
-     *
-     * \param target the target nickname
-     */
-    virtual void whois(std::string_view target);
+	/**
+	 * Request for whois information.
+	 *
+	 * \param target the target nickname
+	 */
+	virtual void whois(std::string_view target);
 };
 
 /**
@@ -691,7 +690,7 @@
  */
 inline auto operator^(server::options v1, server::options v2) noexcept -> server::options
 {
-    return static_cast<server::options>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+	return static_cast<server::options>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
 }
 
 /**
@@ -703,7 +702,7 @@
  */
 inline auto operator&(server::options v1, server::options v2) noexcept -> server::options
 {
-    return static_cast<server::options>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
+	return static_cast<server::options>(static_cast<unsigned>(v1) & static_cast<unsigned>(v2));
 }
 
 /**
@@ -715,7 +714,7 @@
  */
 inline auto operator|(server::options v1, server::options v2) noexcept -> server::options
 {
-    return static_cast<server::options>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+	return static_cast<server::options>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
 }
 
 /**
@@ -726,7 +725,7 @@
  */
 inline auto operator~(server::options v) noexcept -> server::options
 {
-    return static_cast<server::options>(~static_cast<unsigned>(v));
+	return static_cast<server::options>(~static_cast<unsigned>(v));
 }
 
 /**
@@ -738,7 +737,7 @@
  */
 inline auto operator|=(server::options& v1, server::options v2) noexcept -> server::options&
 {
-    return v1 = v1 | v2;
+	return v1 = v1 | v2;
 }
 
 /**
@@ -750,7 +749,7 @@
  */
 inline auto operator&=(server::options& v1, server::options v2) noexcept -> server::options&
 {
-    return v1 = v1 & v2;
+	return v1 = v1 & v2;
 }
 
 /**
@@ -762,7 +761,7 @@
  */
 inline auto operator^=(server::options& v1, server::options v2) noexcept -> server::options&
 {
-    return v1 = v1 ^ v2;
+	return v1 = v1 ^ v2;
 }
 
 /**
@@ -774,78 +773,78 @@
  */
 class server_error : public std::system_error {
 public:
-    /**
-     * \brief Server related errors.
-     */
-    enum error {
-        //!< No error.
-        no_error = 0,
+	/**
+	 * \brief Server related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
 
-        //!< The specified server was not found.
-        not_found,
+		//!< The specified server was not found.
+		not_found,
 
-        //!< The specified identifier is invalid.
-        invalid_identifier,
+		//!< The specified identifier is invalid.
+		invalid_identifier,
 
-        //!< The server is not connected.
-        not_connected,
+		//!< The server is not connected.
+		not_connected,
 
-        //!< The server is already connected.
-        already_connected,
+		//!< The server is already connected.
+		already_connected,
 
-        //!< Server with same name already exists.
-        already_exists,
+		//!< Server with same name already exists.
+		already_exists,
 
-        //!< The specified port number is invalid.
-        invalid_port,
+		//!< The specified port number is invalid.
+		invalid_port,
 
-        //!< The specified reconnect delay number is invalid.
-        invalid_reconnect_delay,
+		//!< The specified reconnect delay number is invalid.
+		invalid_reconnect_delay,
 
-        //!< The specified host was invalid.
-        invalid_hostname,
+		//!< The specified host was invalid.
+		invalid_hostname,
 
-        //!< The channel was empty or invalid.
-        invalid_channel,
+		//!< The channel was empty or invalid.
+		invalid_channel,
 
-        //!< The mode given was empty.
-        invalid_mode,
+		//!< The mode given was empty.
+		invalid_mode,
 
-        //!< The nickname was empty or invalid.
-        invalid_nickname,
+		//!< The nickname was empty or invalid.
+		invalid_nickname,
 
-        //!< The username was empty or invalid.
-        invalid_username,
+		//!< The username was empty or invalid.
+		invalid_username,
 
-        //!< The realname was empty or invalid.
-        invalid_realname,
+		//!< The realname was empty or invalid.
+		invalid_realname,
 
-        //!< Invalid password property.
-        invalid_password,
+		//!< Invalid password property.
+		invalid_password,
 
-        //!< Invalid ping timeout.
-        invalid_ping_timeout,
+		//!< Invalid ping timeout.
+		invalid_ping_timeout,
 
-        //!< Invalid ctcp version.
-        invalid_ctcp_version,
+		//!< Invalid ctcp version.
+		invalid_ctcp_version,
 
-        //!< Invalid command character.
-        invalid_command_char,
+		//!< Invalid command character.
+		invalid_command_char,
 
-        //!< Message (PRIVMSG) was invalid
-        invalid_message,
+		//!< Message (PRIVMSG) was invalid
+		invalid_message,
 
-        //!< SSL was requested but is disabled.
-        ssl_disabled,
-    };
+		//!< SSL was requested but is disabled.
+		ssl_disabled,
+	};
 
 public:
-    /**
-     * Constructor.
-     *
-     * \param code the error code
-     */
-    server_error(error code) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \param code the error code
+	 */
+	server_error(error code) noexcept;
 };
 
 /**
--- a/libirccd/irccd/daemon/server_service.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server_service.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,28 +34,28 @@
 
 class dispatcher {
 private:
-    irccd& irccd_;
+	irccd& irccd_;
 
-    template <typename EventNameFunc, typename ExecFunc>
-    void dispatch(std::string_view, std::string_view, std::string_view, EventNameFunc&&, ExecFunc);
+	template <typename EventNameFunc, typename ExecFunc>
+	void dispatch(std::string_view, std::string_view, std::string_view, EventNameFunc&&, ExecFunc);
 
 public:
-    dispatcher(irccd& irccd);
-    void operator()(const std::monostate&);
-    void operator()(const connect_event&);
-    void operator()(const disconnect_event&);
-    void operator()(const invite_event&);
-    void operator()(const join_event&);
-    void operator()(const kick_event&);
-    void operator()(const message_event&);
-    void operator()(const me_event&);
-    void operator()(const mode_event&);
-    void operator()(const names_event&);
-    void operator()(const nick_event&);
-    void operator()(const notice_event&);
-    void operator()(const part_event&);
-    void operator()(const topic_event&);
-    void operator()(const whois_event&);
+	dispatcher(irccd& irccd);
+	void operator()(const std::monostate&);
+	void operator()(const connect_event&);
+	void operator()(const disconnect_event&);
+	void operator()(const invite_event&);
+	void operator()(const join_event&);
+	void operator()(const kick_event&);
+	void operator()(const message_event&);
+	void operator()(const me_event&);
+	void operator()(const mode_event&);
+	void operator()(const names_event&);
+	void operator()(const nick_event&);
+	void operator()(const notice_event&);
+	void operator()(const part_event&);
+	void operator()(const topic_event&);
+	void operator()(const whois_event&);
 };
 
 template <typename EventNameFunc, typename ExecFunc>
@@ -65,27 +65,27 @@
                           EventNameFunc&& name_func,
                           ExecFunc exec_func)
 {
-    for (const auto& plugin : irccd_.plugins().all()) {
-        const auto eventname = name_func(*plugin);
-        const auto allowed = irccd_.rules().solve(server, target, origin, plugin->get_name(), eventname);
+	for (const auto& plugin : irccd_.plugins().all()) {
+		const auto eventname = name_func(*plugin);
+		const auto allowed = irccd_.rules().solve(server, target, origin, plugin->get_name(), eventname);
 
-        if (!allowed) {
-            irccd_.get_log().debug("rule", "") << "event skipped on match" << std::endl;
-            continue;
-        }
+		if (!allowed) {
+			irccd_.get_log().debug("rule", "") << "event skipped on match" << std::endl;
+			continue;
+		}
 
-        irccd_.get_log().debug("rule", "") << "event allowed" << std::endl;
+		irccd_.get_log().debug("rule", "") << "event allowed" << std::endl;
 
-        try {
-            exec_func(*plugin);
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning(*plugin) << ex.what() << std::endl;
-        }
-    }
+		try {
+			exec_func(*plugin);
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning(*plugin) << ex.what() << std::endl;
+		}
+	}
 }
 
 dispatcher::dispatcher(irccd& irccd)
-    : irccd_(irccd)
+	: irccd_(irccd)
 {
 }
 
@@ -95,363 +95,363 @@
 
 void dispatcher::operator()(const connect_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onConnect" << std::endl;
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onConnect"         },
-        { "server",     ev.server->get_id() }
-    }));
+	irccd_.get_log().debug(*ev.server) << "event onConnect" << std::endl;
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onConnect"             },
+		{ "server",     ev.server->get_id()     }
+	}));
 
-    dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
-        [=] (plugin&) -> std::string {
-            return "onConnect";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_connect(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
+		[=] (plugin&) -> std::string {
+			return "onConnect";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_connect(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const disconnect_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onDisconnect" << std::endl;
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onDisconnect"      },
-        { "server",     ev.server->get_id() }
-    }));
+	irccd_.get_log().debug(*ev.server) << "event onDisconnect" << std::endl;
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onDisconnect"          },
+		{ "server",     ev.server->get_id()     }
+	}));
 
-    dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
-        [=] (plugin&) -> std::string {
-            return "onDisconnect";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_disconnect(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
+		[=] (plugin&) -> std::string {
+			return "onDisconnect";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_disconnect(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const invite_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onInvite:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  target: " << ev.nickname << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onInvite:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  target: " << ev.nickname << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onInvite"          },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onInvite"              },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onInvite";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_invite(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onInvite";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_invite(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const join_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onJoin:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onJoin:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onJoin"            },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onJoin"                },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onJoin";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_join(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onJoin";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_join(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const kick_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onKick:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  target: " << ev.target << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  reason: " << ev.reason << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onKick:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  target: " << ev.target << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  reason: " << ev.reason << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onKick"            },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "target",     ev.target           },
-        { "reason",     ev.reason           }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onKick"                },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "target",     ev.target               },
+		{ "reason",     ev.reason               }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onKick";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_kick(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onKick";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_kick(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const message_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onMessage:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onMessage:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onMessage"         },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "message",    ev.message          }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onMessage"             },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "message",    ev.message              }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin& plugin) -> std::string {
-            return server_util::message_type::parse(
-                ev.message,
-                ev.server->get_command_char(),
-                plugin.get_id()
-            ).type == server_util::message_type::type::command ? "onCommand" : "onMessage";
-        },
-        [=] (plugin& plugin) mutable {
-            auto copy = ev;
-            auto pack = server_util::message_type::parse(
-                copy.message,
-                copy.server->get_command_char(),
-                plugin.get_id()
-            );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin& plugin) -> std::string {
+			return server_util::message_type::parse(
+				ev.message,
+				ev.server->get_command_char(),
+				plugin.get_id()
+			).type == server_util::message_type::type::command ? "onCommand" : "onMessage";
+		},
+		[=] (plugin& plugin) mutable {
+			auto copy = ev;
+			auto pack = server_util::message_type::parse(
+				copy.message,
+				copy.server->get_command_char(),
+				plugin.get_id()
+			);
 
-            copy.message = pack.message;
+			copy.message = pack.message;
 
-            if (pack.type == server_util::message_type::type::command)
-                plugin.handle_command(irccd_, copy);
-            else
-                plugin.handle_message(irccd_, copy);
-        }
-    );
+			if (pack.type == server_util::message_type::type::command)
+				plugin.handle_command(irccd_, copy);
+			else
+				plugin.handle_message(irccd_, copy);
+		}
+	);
 }
 
 void dispatcher::operator()(const me_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onMe:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  target: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onMe:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  target: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onMe"              },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "target",     ev.channel          },
-        { "message",    ev.message          }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onMe"                  },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "target",     ev.channel              },
+		{ "message",    ev.message              }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onMe";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_me(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onMe";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_me(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const mode_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onMode" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  mode: " << ev.mode << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  limit: " << ev.limit << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  user: " << ev.user << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  mask: " << ev.mask << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onMode" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  mode: " << ev.mode << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  limit: " << ev.limit << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  user: " << ev.user << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  mask: " << ev.mask << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onMode"            },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "mode",       ev.mode             },
-        { "limit",      ev.limit            },
-        { "user",       ev.user             },
-        { "mask",       ev.mask             }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onMode"                },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "mode",       ev.mode                 },
+		{ "limit",      ev.limit                },
+		{ "user",       ev.user                 },
+		{ "mask",       ev.mask                 }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
-        [=] (plugin &) -> std::string {
-            return "onMode";
-        },
-        [=] (plugin &plugin) {
-            plugin.handle_mode(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
+		[=] (plugin &) -> std::string {
+			return "onMode";
+		},
+		[=] (plugin &plugin) {
+			plugin.handle_mode(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const names_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onNames:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  names: " << string_util::join(ev.names.begin(), ev.names.end(), ", ") << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onNames:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  names: " << string_util::join(ev.names.begin(), ev.names.end(), ", ") << std::endl;
 
-    auto names = nlohmann::json::array();
+	auto names = nlohmann::json::array();
 
-    for (const auto& v : ev.names)
-        names.push_back(v);
+	for (const auto& v : ev.names)
+		names.push_back(v);
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onNames"           },
-        { "server",     ev.server->get_id() },
-        { "channel",    ev.channel          },
-        { "names",      std::move(names)    }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onNames"               },
+		{ "server",     ev.server->get_id()     },
+		{ "channel",    ev.channel              },
+		{ "names",      std::move(names)        }
+	}));
 
-    dispatch(ev.server->get_id(), /* origin */ "", ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onNames";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_names(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), /* origin */ "", ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onNames";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_names(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const nick_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onNick:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  nickname: " << ev.nickname << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onNick:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  nickname: " << ev.nickname << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onNick"            },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "nickname",   ev.nickname         }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onNick"                },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "nickname",   ev.nickname             }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
-        [=] (plugin&) -> std::string {
-            return "onNick";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_nick(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
+		[=] (plugin&) -> std::string {
+			return "onNick";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_nick(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const notice_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onNotice:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onNotice:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  message: " << ev.message << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onNotice"          },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "message",    ev.message          }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onNotice"              },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "message",    ev.message              }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
-        [=] (plugin&) -> std::string {
-            return "onNotice";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_notice(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, /* channel */ "",
+		[=] (plugin&) -> std::string {
+			return "onNotice";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_notice(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const part_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onPart:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  reason: " << ev.reason << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onPart:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  reason: " << ev.reason << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onPart"            },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "reason",     ev.reason           }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onPart"                },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "reason",     ev.reason               }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onPart";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_part(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onPart";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_part(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const topic_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onTopic:" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  topic: " << ev.topic << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onTopic:" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  origin: " << ev.origin << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channel: " << ev.channel << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  topic: " << ev.topic << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onTopic"           },
-        { "server",     ev.server->get_id() },
-        { "origin",     ev.origin           },
-        { "channel",    ev.channel          },
-        { "topic",      ev.topic            }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onTopic"               },
+		{ "server",     ev.server->get_id()     },
+		{ "origin",     ev.origin               },
+		{ "channel",    ev.channel              },
+		{ "topic",      ev.topic                }
+	}));
 
-    dispatch(ev.server->get_id(), ev.origin, ev.channel,
-        [=] (plugin&) -> std::string {
-            return "onTopic";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_topic(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), ev.origin, ev.channel,
+		[=] (plugin&) -> std::string {
+			return "onTopic";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_topic(irccd_, ev);
+		}
+	);
 }
 
 void dispatcher::operator()(const whois_event& ev)
 {
-    irccd_.get_log().debug(*ev.server) << "event onWhois" << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  nickname: " << ev.whois.nick << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  username: " << ev.whois.user << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  host: " << ev.whois.host << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  realname: " << ev.whois.realname << std::endl;
-    irccd_.get_log().debug(*ev.server) << "  channels: " << string_util::join(ev.whois.channels, ", ") << std::endl;
+	irccd_.get_log().debug(*ev.server) << "event onWhois" << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  nickname: " << ev.whois.nick << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  username: " << ev.whois.user << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  host: " << ev.whois.host << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  realname: " << ev.whois.realname << std::endl;
+	irccd_.get_log().debug(*ev.server) << "  channels: " << string_util::join(ev.whois.channels, ", ") << std::endl;
 
-    irccd_.transports().broadcast(nlohmann::json::object({
-        { "event",      "onWhois"           },
-        { "server",     ev.server->get_id() },
-        { "nickname",   ev.whois.nick       },
-        { "username",   ev.whois.user       },
-        { "host",       ev.whois.host       },
-        { "realname",   ev.whois.realname   }
-    }));
+	irccd_.transports().broadcast(nlohmann::json::object({
+		{ "event",      "onWhois"               },
+		{ "server",     ev.server->get_id()     },
+		{ "nickname",   ev.whois.nick           },
+		{ "username",   ev.whois.user           },
+		{ "host",       ev.whois.host           },
+		{ "realname",   ev.whois.realname       }
+	}));
 
-    dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
-        [=] (plugin&) -> std::string {
-            return "onWhois";
-        },
-        [=] (plugin& plugin) {
-            plugin.handle_whois(irccd_, ev);
-        }
-    );
+	dispatch(ev.server->get_id(), /* origin */ "", /* channel */ "",
+		[=] (plugin&) -> std::string {
+			return "onWhois";
+		},
+		[=] (plugin& plugin) {
+			plugin.handle_whois(irccd_, ev);
+		}
+	);
 }
 
 } // !namespace
@@ -459,230 +459,230 @@
 void server_service::handle_error(const std::shared_ptr<server>& server,
                                   const std::error_code& code)
 {
-    assert(server);
+	assert(server);
 
-    irccd_.get_log().warning(*server) << code.message() << std::endl;
+	irccd_.get_log().warning(*server) << code.message() << std::endl;
 
-    irccd_.get_log().warning(*server) << int(server->get_options()) << std::endl;
+	irccd_.get_log().warning(*server) << int(server->get_options()) << std::endl;
 
-    if ((server->get_options() & server::options::auto_reconnect) != server::options::auto_reconnect)
-        remove(server->get_id());
-    else {
-        irccd_.get_log().info(*server) << "reconnecting in "
-            << server->get_reconnect_delay() << " second(s)" << std::endl;
-        wait(server);
-    }
+	if ((server->get_options() & server::options::auto_reconnect) != server::options::auto_reconnect)
+		remove(server->get_id());
+	else {
+		irccd_.get_log().info(*server) << "reconnecting in "
+			<< server->get_reconnect_delay() << " second(s)" << std::endl;
+		wait(server);
+	}
 }
 
 void server_service::handle_wait(const std::shared_ptr<server>& server, const std::error_code& code)
 {
-    /*
-     * The timer runs on his own control, it will complete either if the delay
-     * was reached, there was an error or if the io_context was called to cancel
-     * all pending operations.
-     *
-     * This means while the timer is running someone may already have ask a
-     * server for explicit reconnection (e.g. remote command, plugin). Thus we
-     * check for server state and if it is still present in service.
-     */
-    if (code && code != std::errc::operation_canceled) {
-        irccd_.get_log().warning(*server) << code.message() << std::endl;
-        return;
-    }
+	/*
+	 * The timer runs on his own control, it will complete either if the delay
+	 * was reached, there was an error or if the io_context was called to cancel
+	 * all pending operations.
+	 *
+	 * This means while the timer is running someone may already have ask a
+	 * server for explicit reconnection (e.g. remote command, plugin). Thus we
+	 * check for server state and if it is still present in service.
+	 */
+	if (code && code != std::errc::operation_canceled) {
+		irccd_.get_log().warning(*server) << code.message() << std::endl;
+		return;
+	}
 
-    if (server->get_state() == server::state::connected || !has(server->get_id()))
-        return;
+	if (server->get_state() == server::state::connected || !has(server->get_id()))
+		return;
 
-    connect(server);
+	connect(server);
 }
 
 void server_service::handle_recv(const std::shared_ptr<server>& server,
                                  const std::error_code& code,
                                  const event& event)
 {
-    assert(server);
+	assert(server);
 
-    if (code)
-        handle_error(server, code);
-    else {
-        recv(server);
-        std::visit(dispatcher(irccd_), event);
-    }
+	if (code)
+		handle_error(server, code);
+	else {
+		recv(server);
+		std::visit(dispatcher(irccd_), event);
+	}
 }
 
 void server_service::handle_connect(const std::shared_ptr<server>& server, const std::error_code& code)
 {
-    if (code)
-        handle_error(server, code);
-    else
-        recv(server);
+	if (code)
+		handle_error(server, code);
+	else
+		recv(server);
 }
 
 void server_service::wait(const std::shared_ptr<server>& server)
 {
-    assert(server);
+	assert(server);
 
-    auto timer = std::make_shared<boost::asio::deadline_timer>(irccd_.get_service());
+	auto timer = std::make_shared<boost::asio::deadline_timer>(irccd_.get_service());
 
-    timer->expires_from_now(boost::posix_time::seconds(server->get_reconnect_delay()));
-    timer->async_wait([this, server, timer] (auto code) {
-        handle_wait(server, code);
-    });
+	timer->expires_from_now(boost::posix_time::seconds(server->get_reconnect_delay()));
+	timer->async_wait([this, server, timer] (auto code) {
+		handle_wait(server, code);
+	});
 }
 
 void server_service::recv(const std::shared_ptr<server>& server)
 {
-    assert(server);
+	assert(server);
 
-    server->recv([this, server] (auto code, auto event) {
-        handle_recv(server, code, event);
-    });
+	server->recv([this, server] (auto code, auto event) {
+		handle_recv(server, code, event);
+	});
 }
 
 void server_service::connect(const std::shared_ptr<server>& server)
 {
-    assert(server);
+	assert(server);
 
-    server->connect([this, server] (auto code) {
-        handle_connect(server, code);
-    });
+	server->connect([this, server] (auto code) {
+		handle_connect(server, code);
+	});
 }
 
 server_service::server_service(irccd &irccd)
-    : irccd_(irccd)
+	: irccd_(irccd)
 {
 }
 
 auto server_service::all() const noexcept -> const std::vector<std::shared_ptr<server>>&
 {
-    return servers_;
+	return servers_;
 }
 
 auto server_service::has(const std::string& name) const noexcept -> bool
 {
-    return std::count_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
-        return server->get_id() == name;
-    }) > 0;
+	return std::count_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
+		return server->get_id() == name;
+	}) > 0;
 }
 
 void server_service::add(std::shared_ptr<server> server)
 {
-    assert(server);
-    assert(!has(server->get_id()));
+	assert(server);
+	assert(!has(server->get_id()));
 
-    servers_.push_back(server);
-    connect(server);
+	servers_.push_back(server);
+	connect(server);
 }
 
 auto server_service::get(std::string_view name) const noexcept -> std::shared_ptr<server>
 {
-    const auto it = std::find_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
-        return server->get_id() == name;
-    });
+	const auto it = std::find_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
+		return server->get_id() == name;
+	});
 
-    if (it == servers_.end())
-        return nullptr;
+	if (it == servers_.end())
+		return nullptr;
 
-    return *it;
+	return *it;
 }
 
 auto server_service::require(std::string_view name) const -> std::shared_ptr<server>
 {
-    if (!string_util::is_identifier(name))
-        throw server_error(server_error::invalid_identifier);
+	if (!string_util::is_identifier(name))
+		throw server_error(server_error::invalid_identifier);
 
-    const auto s = get(name);
+	const auto s = get(name);
 
-    if (!s)
-        throw server_error(server_error::not_found);
+	if (!s)
+		throw server_error(server_error::not_found);
 
-    return s;
+	return s;
 }
 
 void server_service::disconnect(std::string_view id)
 {
-    const auto s = require(id);
+	const auto s = require(id);
 
-    s->disconnect();
-    dispatcher{irccd_}(disconnect_event{s});
+	s->disconnect();
+	dispatcher{irccd_}(disconnect_event{s});
 }
 
 void server_service::reconnect(std::string_view id)
 {
-    disconnect(id);
-    connect(require(id));
+	disconnect(id);
+	connect(require(id));
 }
 
 void server_service::reconnect()
 {
-    for (const auto& s : servers_) {
-        try {
-            s->disconnect();
-            dispatcher{irccd_}(disconnect_event{s});
-            connect(s);
-        } catch (const server_error& ex) {
-            irccd_.get_log().warning(*s) << ex.what() << std::endl;
-        }
-    }
+	for (const auto& s : servers_) {
+		try {
+			s->disconnect();
+			dispatcher{irccd_}(disconnect_event{s});
+			connect(s);
+		} catch (const server_error& ex) {
+			irccd_.get_log().warning(*s) << ex.what() << std::endl;
+		}
+	}
 }
 
 void server_service::remove(std::string_view name)
 {
-    const auto it = std::find_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
-        return server->get_id() == name;
-    });
+	const auto it = std::find_if(servers_.begin(), servers_.end(), [&] (const auto& server) {
+		return server->get_id() == name;
+	});
 
-    if (it != servers_.end()) {
-        (*it)->disconnect();
-        servers_.erase(it);
-    }
+	if (it != servers_.end()) {
+		(*it)->disconnect();
+		servers_.erase(it);
+	}
 }
 
 void server_service::clear() noexcept
 {
-    /*
-     * Copy the array, because disconnect() may trigger on_die signal which
-     * erase the server from itself.
-     */
-    const auto save = servers_;
+	/*
+	 * Copy the array, because disconnect() may trigger on_die signal which
+	 * erase the server from itself.
+	 */
+	const auto save = servers_;
 
-    for (const auto& server : save)
-        server->disconnect();
+	for (const auto& server : save)
+		server->disconnect();
 
-    servers_.clear();
+	servers_.clear();
 }
 
 void server_service::load(const config& cfg) noexcept
 {
-    for (const auto& section : cfg) {
-        if (section.key() != "server")
-            continue;
+	for (const auto& section : cfg) {
+		if (section.get_key() != "server")
+			continue;
 
-        const auto id = section.get("name").value();
+		const auto id = section.get("name").get_value();
 
-        try {
-            auto server = server_util::from_config(irccd_.get_service(), cfg, section);
+		try {
+			auto server = server_util::from_config(irccd_.get_service(), cfg, section);
 
-            if (has(server->get_id()))
-                throw server_error(server_error::already_exists);
+			if (has(server->get_id()))
+				throw server_error(server_error::already_exists);
 
-            add(std::move(server));
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning("server", id) << ex.what() << std::endl;
-        }
-    }
+			add(std::move(server));
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning("server", id) << ex.what() << std::endl;
+		}
+	}
 }
 
 namespace logger {
 
 auto loggable_traits<server>::get_category(const server&) -> std::string_view
 {
-    return "server";
+	return "server";
 }
 
 auto loggable_traits<server>::get_component(const server& sv) -> std::string_view
 {
-    return sv.get_id();
+	return sv.get_id();
 }
 
 } // !logger
--- a/libirccd/irccd/daemon/server_service.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server_service.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -41,108 +41,108 @@
  */
 class server_service {
 private:
-    irccd& irccd_;
-    std::vector<std::shared_ptr<server>> servers_;
+	irccd& irccd_;
+	std::vector<std::shared_ptr<server>> servers_;
 
-    void handle_error(const std::shared_ptr<server>&, const std::error_code&);
-    void handle_wait(const std::shared_ptr<server>&, const std::error_code&);
-    void handle_recv(const std::shared_ptr<server>&, const std::error_code&, const event&);
-    void handle_connect(const std::shared_ptr<server>&, const std::error_code&);
+	void handle_error(const std::shared_ptr<server>&, const std::error_code&);
+	void handle_wait(const std::shared_ptr<server>&, const std::error_code&);
+	void handle_recv(const std::shared_ptr<server>&, const std::error_code&, const event&);
+	void handle_connect(const std::shared_ptr<server>&, const std::error_code&);
 
-    void wait(const std::shared_ptr<server>&);
-    void recv(const std::shared_ptr<server>&);
-    void connect(const std::shared_ptr<server>&);
+	void wait(const std::shared_ptr<server>&);
+	void recv(const std::shared_ptr<server>&);
+	void connect(const std::shared_ptr<server>&);
 
 public:
-    /**
-     * Create the server service.
-     */
-    server_service(irccd& instance);
+	/**
+	 * Create the server service.
+	 */
+	server_service(irccd& instance);
 
-    /**
-     * Get the list of servers
-     *
-     * \return the servers
-     */
-    auto all() const noexcept -> const std::vector<std::shared_ptr<server>>&;
+	/**
+	 * Get the list of servers
+	 *
+	 * \return the servers
+	 */
+	auto all() const noexcept -> const std::vector<std::shared_ptr<server>>&;
 
-    /**
-     * Check if a server exists.
-     *
-     * \param name the name
-     * \return true if exists
-     */
-    auto has(const std::string& name) const noexcept -> bool;
+	/**
+	 * Check if a server exists.
+	 *
+	 * \param name the name
+	 * \return true if exists
+	 */
+	auto has(const std::string& name) const noexcept -> bool;
 
-    /**
-     * Add a new server to the application.
-     *
-     * \pre hasServer must return false
-     * \param sv the server
-     */
-    void add(std::shared_ptr<server> sv);
+	/**
+	 * Add a new server to the application.
+	 *
+	 * \pre hasServer must return false
+	 * \param sv the server
+	 */
+	void add(std::shared_ptr<server> sv);
 
-    /**
-     * Get a server or empty one if not found
-     *
-     * \param name the server name
-     * \return the server or empty one if not found
-     */
-    auto get(std::string_view name) const noexcept -> std::shared_ptr<server>;
+	/**
+	 * Get a server or empty one if not found
+	 *
+	 * \param name the server name
+	 * \return the server or empty one if not found
+	 */
+	auto get(std::string_view name) const noexcept -> std::shared_ptr<server>;
 
-    /**
-     * Find a server from a JSON object.
-     *
-     * \param name the server name
-     * \return the server
-     * \throw server_error on errors
-     */
-    auto require(std::string_view name) const -> std::shared_ptr<server>;
+	/**
+	 * Find a server from a JSON object.
+	 *
+	 * \param name the server name
+	 * \return the server
+	 * \throw server_error on errors
+	 */
+	auto require(std::string_view name) const -> std::shared_ptr<server>;
 
-    /**
-     * Force disconnection, this also call plugin::handle_disconnect handler.
-     *
-     * \param id the server id
-     * \throw server_error on errors
-     */
-    void disconnect(std::string_view id);
+	/**
+	 * Force disconnection, this also call plugin::handle_disconnect handler.
+	 *
+	 * \param id the server id
+	 * \throw server_error on errors
+	 */
+	void disconnect(std::string_view id);
 
-    /**
-     * Force reconnection, this also call plugin::handle_disconnect handler.
-     *
-     * \param id the server id
-     * \return the server
-     * \throw server_error on errors
-     */
-    void reconnect(std::string_view id);
+	/**
+	 * Force reconnection, this also call plugin::handle_disconnect handler.
+	 *
+	 * \param id the server id
+	 * \return the server
+	 * \throw server_error on errors
+	 */
+	void reconnect(std::string_view id);
 
-    /**
-     * Force reconnection of all servers.
-     */
-    void reconnect();
+	/**
+	 * Force reconnection of all servers.
+	 */
+	void reconnect();
 
-    /**
-     * Remove a server from the irccd instance.
-     *
-     * The server if any, will be disconnected.
-     *
-     * \param name the server name
-     */
-    void remove(std::string_view name);
+	/**
+	 * Remove a server from the irccd instance.
+	 *
+	 * The server if any, will be disconnected.
+	 *
+	 * \param name the server name
+	 */
+	void remove(std::string_view name);
 
-    /**
-     * Remove all servers.
-     *
-     * All servers will be disconnected.
-     */
-    void clear() noexcept;
+	/**
+	 * Remove all servers.
+	 *
+	 * All servers will be disconnected.
+	 */
+	void clear() noexcept;
 
-    /**
-     * Load servers from the configuration.
-     *
-     * \param cfg the config
-     */
-    void load(const config& cfg) noexcept;
+	/**
+	 * Load servers from the configuration.
+	 *
+	 * \param cfg the config
+	 */
+	void load(const config& cfg) noexcept;
 };
 
 namespace logger {
@@ -152,9 +152,9 @@
 
 template <>
 struct loggable_traits<server> {
-    static auto get_category(const server& server) -> std::string_view;
+	static auto get_category(const server& server) -> std::string_view;
 
-    static auto get_component(const server& server) -> std::string_view;
+	static auto get_component(const server& server) -> std::string_view;
 };
 
 } // !logger
--- a/libirccd/irccd/daemon/server_util.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,152 +28,154 @@
 
 namespace irccd::server_util {
 
+using json_util::deserializer;
+
 namespace {
 
 void from_config_load_identity(server& sv, const ini::section& sc)
 {
-    const auto username = ini_util::optional_string(sc, "username", sv.get_username());
-    const auto realname = ini_util::optional_string(sc, "realname", sv.get_realname());
-    const auto nickname = ini_util::optional_string(sc, "nickname", sv.get_nickname());
-    const auto ctcp_version = ini_util::optional_string(sc, "ctcp-version", sv.get_ctcp_version());
+	const auto username = ini_util::optional_string(sc, "username", sv.get_username());
+	const auto realname = ini_util::optional_string(sc, "realname", sv.get_realname());
+	const auto nickname = ini_util::optional_string(sc, "nickname", sv.get_nickname());
+	const auto ctcp_version = ini_util::optional_string(sc, "ctcp-version", sv.get_ctcp_version());
 
-    if (username.empty())
-        throw server_error(server_error::invalid_username);
-    if (realname.empty())
-        throw server_error(server_error::invalid_realname);
-    if (nickname.empty())
-        throw server_error(server_error::invalid_nickname);
-    if (ctcp_version.empty())
-        throw server_error(server_error::invalid_ctcp_version);
+	if (username.empty())
+		throw server_error(server_error::invalid_username);
+	if (realname.empty())
+		throw server_error(server_error::invalid_realname);
+	if (nickname.empty())
+		throw server_error(server_error::invalid_nickname);
+	if (ctcp_version.empty())
+		throw server_error(server_error::invalid_ctcp_version);
 
-    sv.set_username(username);
-    sv.set_realname(realname);
-    sv.set_nickname(nickname);
-    sv.set_ctcp_version(ctcp_version);
+	sv.set_username(username);
+	sv.set_realname(realname);
+	sv.set_nickname(nickname);
+	sv.set_ctcp_version(ctcp_version);
 }
 
 void from_config_load_channels(server& sv, const ini::section& sc)
 {
-    for (const auto& s : sc.get("channels")) {
-        channel channel;
+	for (const auto& s : sc.get("channels")) {
+		channel channel;
 
-        if (auto pos = s.find(":") != std::string::npos) {
-            channel.name = s.substr(0, pos);
-            channel.password = s.substr(pos + 1);
-        } else
-            channel.name = s;
+		if (auto pos = s.find(":") != std::string::npos) {
+			channel.name = s.substr(0, pos);
+			channel.password = s.substr(pos + 1);
+		} else
+			channel.name = s;
 
-        sv.join(channel.name, channel.password);
-    }
+		sv.join(channel.name, channel.password);
+	}
 }
 
 void from_config_load_flags(server& sv, const ini::section& sc)
 {
-    const auto ipv6 = sc.get("ipv6");
-    const auto ssl = sc.get("ssl");
-    const auto ssl_verify = sc.get("ssl-verify");
-    const auto auto_rejoin = sc.get("auto-rejoin");
-    const auto auto_reconnect = sc.get("auto-reconnect");
-    const auto join_invite = sc.get("join-invite");
+	const auto ipv6 = sc.get("ipv6");
+	const auto ssl = sc.get("ssl");
+	const auto ssl_verify = sc.get("ssl-verify");
+	const auto auto_rejoin = sc.get("auto-rejoin");
+	const auto auto_reconnect = sc.get("auto-reconnect");
+	const auto join_invite = sc.get("join-invite");
 
-    if (string_util::is_boolean(ipv6.value()))
-        sv.set_options(sv.get_options() | server::options::ipv6);
-    if (string_util::is_boolean(ssl.value()))
-        sv.set_options(sv.get_options() | server::options::ssl);
-    if (string_util::is_boolean(ssl_verify.value()))
-        sv.set_options(sv.get_options() | server::options::ssl_verify);
-    if (string_util::is_boolean(auto_rejoin.value()))
-        sv.set_options(sv.get_options() | server::options::auto_rejoin);
-    if (string_util::is_boolean(auto_reconnect.value()))
-        sv.set_options(sv.get_options() | server::options::auto_reconnect);
-    if (string_util::is_boolean(join_invite.value()))
-        sv.set_options(sv.get_options() | server::options::join_invite);
+	if (string_util::is_boolean(ipv6.get_value()))
+		sv.set_options(sv.get_options() | server::options::ipv6);
+	if (string_util::is_boolean(ssl.get_value()))
+		sv.set_options(sv.get_options() | server::options::ssl);
+	if (string_util::is_boolean(ssl_verify.get_value()))
+		sv.set_options(sv.get_options() | server::options::ssl_verify);
+	if (string_util::is_boolean(auto_rejoin.get_value()))
+		sv.set_options(sv.get_options() | server::options::auto_rejoin);
+	if (string_util::is_boolean(auto_reconnect.get_value()))
+		sv.set_options(sv.get_options() | server::options::auto_reconnect);
+	if (string_util::is_boolean(join_invite.get_value()))
+		sv.set_options(sv.get_options() | server::options::join_invite);
 }
 
 void from_config_load_numeric_parameters(server& sv, const ini::section& sc)
 {
-    const auto port = ini_util::optional_uint<std::uint16_t>(sc, "port", sv.get_port());
-    const auto ping_timeout = ini_util::optional_uint<uint16_t>(sc, "ping-timeout", sv.get_ping_timeout());
-    const auto reco_timeout = ini_util::optional_uint<uint16_t>(sc, "auto-reconnect-delay", sv.get_reconnect_delay());
+	const auto port = ini_util::optional_uint<std::uint16_t>(sc, "port", sv.get_port());
+	const auto ping_timeout = ini_util::optional_uint<uint16_t>(sc, "ping-timeout", sv.get_ping_timeout());
+	const auto reco_timeout = ini_util::optional_uint<uint16_t>(sc, "auto-reconnect-delay", sv.get_reconnect_delay());
 
-    if (!port)
-        throw server_error(server_error::invalid_port);
-    if (!ping_timeout)
-        throw server_error(server_error::invalid_ping_timeout);
-    if (!reco_timeout)
-        throw server_error(server_error::invalid_reconnect_delay);
+	if (!port)
+		throw server_error(server_error::invalid_port);
+	if (!ping_timeout)
+		throw server_error(server_error::invalid_ping_timeout);
+	if (!reco_timeout)
+		throw server_error(server_error::invalid_reconnect_delay);
 
-    sv.set_port(*port);
-    sv.set_ping_timeout(*ping_timeout);
-    sv.set_reconnect_delay(*reco_timeout);
+	sv.set_port(*port);
+	sv.set_ping_timeout(*ping_timeout);
+	sv.set_reconnect_delay(*reco_timeout);
 }
 
 void from_config_load_options(server& sv, const ini::section& sc)
 {
-    const auto password = ini_util::optional_string(sc, "password", "");
-    const auto command_char = ini_util::optional_string(sc, "command-char", sv.get_command_char());
+	const auto password = ini_util::optional_string(sc, "password", "");
+	const auto command_char = ini_util::optional_string(sc, "command-char", sv.get_command_char());
 
-    sv.set_password(password);
-    sv.set_command_char(command_char);
+	sv.set_password(password);
+	sv.set_command_char(command_char);
 }
 
-void from_json_load_options(server& sv, const json_util::document& parser)
+void from_json_load_options(server& sv, const deserializer& parser)
 {
-    const auto port = parser.optional<std::uint16_t>("port", sv.get_port());
-    const auto nickname = parser.optional<std::string>("nickname", sv.get_nickname());
-    const auto realname = parser.optional<std::string>("realname", sv.get_realname());
-    const auto username = parser.optional<std::string>("username", sv.get_username());
-    const auto ctcp_version = parser.optional<std::string>("ctcpVersion", sv.get_ctcp_version());
-    const auto command = parser.optional<std::string>("commandChar", sv.get_command_char());
-    const auto password = parser.optional<std::string>("password", sv.get_password());
+	const auto port = parser.optional<std::uint16_t>("port", sv.get_port());
+	const auto nickname = parser.optional<std::string>("nickname", sv.get_nickname());
+	const auto realname = parser.optional<std::string>("realname", sv.get_realname());
+	const auto username = parser.optional<std::string>("username", sv.get_username());
+	const auto ctcp_version = parser.optional<std::string>("ctcpVersion", sv.get_ctcp_version());
+	const auto command = parser.optional<std::string>("commandChar", sv.get_command_char());
+	const auto password = parser.optional<std::string>("password", sv.get_password());
 
-    if (!port || *port > std::numeric_limits<std::uint16_t>::max())
-        throw server_error(server_error::invalid_port);
-    if (!nickname)
-        throw server_error(server_error::invalid_nickname);
-    if (!realname)
-        throw server_error(server_error::invalid_realname);
-    if (!username)
-        throw server_error(server_error::invalid_username);
-    if (!ctcp_version)
-        throw server_error(server_error::invalid_ctcp_version);
-    if (!command)
-        throw server_error(server_error::invalid_command_char);
-    if (!password)
-        throw server_error(server_error::invalid_password);
+	if (!port || *port > std::numeric_limits<std::uint16_t>::max())
+		throw server_error(server_error::invalid_port);
+	if (!nickname)
+		throw server_error(server_error::invalid_nickname);
+	if (!realname)
+		throw server_error(server_error::invalid_realname);
+	if (!username)
+		throw server_error(server_error::invalid_username);
+	if (!ctcp_version)
+		throw server_error(server_error::invalid_ctcp_version);
+	if (!command)
+		throw server_error(server_error::invalid_command_char);
+	if (!password)
+		throw server_error(server_error::invalid_password);
 
-    sv.set_port(*port);
-    sv.set_nickname(*nickname);
-    sv.set_realname(*realname);
-    sv.set_username(*username);
-    sv.set_ctcp_version(*ctcp_version);
-    sv.set_command_char(*command);
-    sv.set_password(*password);
+	sv.set_port(*port);
+	sv.set_nickname(*nickname);
+	sv.set_realname(*realname);
+	sv.set_username(*username);
+	sv.set_ctcp_version(*ctcp_version);
+	sv.set_command_char(*command);
+	sv.set_password(*password);
 }
 
-void from_json_load_flags(server& sv, const json_util::document& parser)
+void from_json_load_flags(server& sv, const deserializer& parser)
 {
-    const auto ipv6 = parser.get<bool>("ipv6");
-    const auto auto_rejoin = parser.get<bool>("autoRejoin");
-    const auto join_invite = parser.get<bool>("joinInvite");
-    const auto ssl = parser.get<bool>("ssl");
-    const auto ssl_verify = parser.get<bool>("sslVerify");
+	const auto ipv6 = parser.get<bool>("ipv6");
+	const auto auto_rejoin = parser.get<bool>("autoRejoin");
+	const auto join_invite = parser.get<bool>("joinInvite");
+	const auto ssl = parser.get<bool>("ssl");
+	const auto ssl_verify = parser.get<bool>("sslVerify");
 
-    if (ipv6.value_or(false))
-        sv.set_options(sv.get_options() | server::options::ipv6);
-    if (auto_rejoin.value_or(false))
-        sv.set_options(sv.get_options() | server::options::auto_rejoin);
-    if (join_invite.value_or(false))
-        sv.set_options(sv.get_options() | server::options::join_invite);
+	if (ipv6.value_or(false))
+		sv.set_options(sv.get_options() | server::options::ipv6);
+	if (auto_rejoin.value_or(false))
+		sv.set_options(sv.get_options() | server::options::auto_rejoin);
+	if (join_invite.value_or(false))
+		sv.set_options(sv.get_options() | server::options::join_invite);
 
-    if (ssl.value_or(false))
+	if (ssl.value_or(false))
 #if !defined(IRCCD_HAVE_SSL)
-        throw server_error(server_error::ssl_disabled);
+		throw server_error(server_error::ssl_disabled);
 #else
-        sv.set_options(sv.get_options() | server::options::ssl);
+		sv.set_options(sv.get_options() | server::options::ssl);
 #endif
-    if (ssl_verify.value_or(false))
-        sv.set_options(sv.get_options() | server::options::ssl_verify);
+	if (ssl_verify.value_or(false))
+		sv.set_options(sv.get_options() | server::options::ssl_verify);
 }
 
 } // !namespace
@@ -182,101 +184,101 @@
                          std::string_view cchar,
                          std::string_view plugin) -> message_type
 {
-    auto result = std::string(message);
-    auto cc = std::string(cchar);
-    auto name = std::string(plugin);
-    auto iscommand = false;
+	auto result = std::string(message);
+	auto cc = std::string(cchar);
+	auto name = std::string(plugin);
+	auto iscommand = false;
 
-    // handle special commands "!<plugin> command"
-    if (cc.length() > 0) {
-        auto pos = result.find_first_of(" \t");
-        auto fullcommand = cc + name;
+	// handle special commands "!<plugin> command"
+	if (cc.length() > 0) {
+		auto pos = result.find_first_of(" \t");
+		auto fullcommand = cc + name;
 
-        /*
-         * If the message that comes is "!foo" without spaces we
-         * compare the command char + the plugin name. If there
-         * is a space, we check until we find a space, if not
-         * typing "!foo123123" will trigger foo plugin.
-         */
-        if (pos == std::string::npos)
-            iscommand = result == fullcommand;
-        else
-            iscommand = result.length() >= fullcommand.length() && result.compare(0, pos, fullcommand) == 0;
+		/*
+		 * If the message that comes is "!foo" without spaces we
+		 * compare the command char + the plugin name. If there
+		 * is a space, we check until we find a space, if not
+		 * typing "!foo123123" will trigger foo plugin.
+		 */
+		if (pos == std::string::npos)
+			iscommand = result == fullcommand;
+		else
+			iscommand = result.length() >= fullcommand.length() && result.compare(0, pos, fullcommand) == 0;
 
-        if (iscommand) {
-            /*
-             * If no space is found we just set the message to "" otherwise
-             * the plugin name will be passed through onCommand
-             */
-            if (pos == std::string::npos)
-                result = "";
-            else
-                result = message.substr(pos + 1);
-        }
-    }
+		if (iscommand) {
+			/*
+			 * If no space is found we just set the message to "" otherwise
+			 * the plugin name will be passed through onCommand
+			 */
+			if (pos == std::string::npos)
+				result = "";
+			else
+				result = message.substr(pos + 1);
+		}
+	}
 
-    return {
-        iscommand ? message_type::type::command : message_type::type::message,
-        result
-    };
+	return {
+		iscommand ? message_type::type::command : message_type::type::message,
+		result
+	};
 }
 
 auto from_json(boost::asio::io_service& service, const nlohmann::json& object) -> std::shared_ptr<server>
 {
-    // Mandatory parameters.
-    const json_util::document parser(object);
-    const auto id = parser.get<std::string>("name");
-    const auto host = parser.get<std::string>("host");
+	// Mandatory parameters.
+	const deserializer parser(object);
+	const auto id = parser.get<std::string>("name");
+	const auto host = parser.get<std::string>("host");
 
-    if (!id || !string_util::is_identifier(*id))
-        throw server_error(server_error::invalid_identifier);
-    if (!host || host->empty())
-        throw server_error(server_error::invalid_hostname);
+	if (!id || !string_util::is_identifier(*id))
+		throw server_error(server_error::invalid_identifier);
+	if (!host || host->empty())
+		throw server_error(server_error::invalid_hostname);
 
-    const auto sv = std::make_shared<server>(service, *id, *host);
+	const auto sv = std::make_shared<server>(service, *id, *host);
 
-    from_json_load_options(*sv, parser);
-    from_json_load_flags(*sv, parser);
+	from_json_load_options(*sv, parser);
+	from_json_load_flags(*sv, parser);
 
-    return sv;
+	return sv;
 }
 
 auto from_config(boost::asio::io_service& service,
                  const config& cfg,
                  const ini::section& sc) -> std::shared_ptr<server>
 {
-    // Mandatory parameters.
-    const auto id = sc.get("name");
-    const auto host = sc.get("hostname");
+	// Mandatory parameters.
+	const auto id = sc.get("name");
+	const auto host = sc.get("hostname");
 
-    if (!string_util::is_identifier(id.value()))
-        throw server_error(server_error::invalid_identifier);
-    if (host.value().empty())
-        throw server_error(server_error::invalid_hostname);
+	if (!string_util::is_identifier(id.get_value()))
+		throw server_error(server_error::invalid_identifier);
+	if (host.get_value().empty())
+		throw server_error(server_error::invalid_hostname);
 
-    const auto sv = std::make_shared<server>(service, id.value(), host.value());
+	const auto sv = std::make_shared<server>(service, id.get_value(), host.get_value());
 
-    from_config_load_channels(*sv, sc);
-    from_config_load_flags(*sv, sc);
-    from_config_load_numeric_parameters(*sv, sc);
-    from_config_load_options(*sv, sc);
+	from_config_load_channels(*sv, sc);
+	from_config_load_flags(*sv, sc);
+	from_config_load_numeric_parameters(*sv, sc);
+	from_config_load_options(*sv, sc);
 
-    // Identity is in a separate section.
-    const auto identity = sc.get("identity");
+	// Identity is in a separate section
+	const auto identity = sc.get("identity");
 
-    if (identity.value().size() > 0) {
-        const auto it = std::find_if(cfg.begin(), cfg.end(), [&] (const auto& i) {
-            if (i.key() != "identity")
-                return false;
+	if (identity.get_value().size() > 0) {
+		const auto it = std::find_if(cfg.begin(), cfg.end(), [&] (const auto& i) {
+			if (i.get_key() != "identity")
+				return false;
 
-            return i.get("name").value() == identity.value();
-        });
+			return i.get("name").get_value() == identity.get_value();
+		});
 
-        if (it != cfg.end())
-            from_config_load_identity(*sv, *it);
-    }
+		if (it != cfg.end())
+			from_config_load_identity(*sv, *it);
+	}
 
-    return sv;
+	return sv;
 }
 
 } // !irccd::server_util
--- a/libirccd/irccd/daemon/server_util.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/server_util.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -57,33 +57,33 @@
  * exists.
  */
 struct message_type {
-    /**
-     * \brief Describe which type of message has been received
-     */
-    enum class type {
-        command,                        //!< special command
-        message                         //!< standard message
-    } type;
+	/**
+	 * \brief Describe which type of message has been received
+	 */
+	enum class type {
+		command,        //!< special command
+		message         //!< standard message
+	} type;
 
-    /**
-     * Message content.
-     */
-    std::string message;
+	/**
+	 * Message content.
+	 */
+	std::string message;
 
-    /**
-     * Parse IRC message and determine if it's a command or a simple message.
-     *
-     * If it's a command, the plugin invocation command is removed from the
-     * original message, otherwise it is copied verbatime.
-     *
-     * \param message the message line
-     * \param cchar the command char (e.g '!')
-     * \param plugin the plugin name
-     * \return the pair
-     */
-    static auto parse(std::string_view message,
-                      std::string_view cchar,
-                      std::string_view plugin) -> message_type;
+	/**
+	 * Parse IRC message and determine if it's a command or a simple message.
+	 *
+	 * If it's a command, the plugin invocation command is removed from the
+	 * original message, otherwise it is copied verbatime.
+	 *
+	 * \param message the message line
+	 * \param cchar the command char (e.g '!')
+	 * \param plugin the plugin name
+	 * \return the pair
+	 */
+	static auto parse(std::string_view message,
+	                  std::string_view cchar,
+	                  std::string_view plugin) -> message_type;
 };
 
 /**
--- a/libirccd/irccd/daemon/transport_client.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_client.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -25,111 +25,112 @@
 
 void transport_client::flush()
 {
-    if (queue_.empty())
-        return;
+	if (queue_.empty())
+		return;
 
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    stream_->write(queue_.front().first, [this, self] (auto code) {
-        if (queue_.front().second)
-            queue_.front().second(code);
+	stream_->write(queue_.front().first, [this, self] (auto code) {
+		if (queue_.front().second)
+			queue_.front().second(code);
 
-        queue_.pop_front();
+		queue_.pop_front();
 
-        if (code)
-            erase();
-        else
-            flush();
-    });
+		if (code)
+			erase();
+		else
+			flush();
+	});
 }
 
 void transport_client::erase()
 {
-    state_ = state::closing;
+	state_ = state::closing;
 
-    if (auto parent = parent_.lock())
-        parent->get_clients().erase(shared_from_this());
+	if (auto parent = parent_.lock())
+		parent->get_clients().erase(shared_from_this());
 }
 
-transport_client::transport_client(std::weak_ptr<transport_server> server, std::shared_ptr<io::stream> stream) noexcept
-    : parent_(server)
-    , stream_(std::move(stream))
+transport_client::transport_client(std::weak_ptr<transport_server> server,
+                                   std::shared_ptr<stream> stream) noexcept
+	: parent_(server)
+	, stream_(std::move(stream))
 {
-    assert(stream_);
+	assert(stream_);
 }
 
 auto transport_client::get_state() const noexcept -> state
 {
-    return state_;
+	return state_;
 }
 
 void transport_client::set_state(state state) noexcept
 {
-    state_ = state;
+	state_ = state;
 }
 
-void transport_client::read(io::read_handler handler)
+void transport_client::read(stream::read_handler handler)
 {
-    assert(handler);
+	assert(handler);
 
-    if (state_ != state::closing) {
-        const auto self = shared_from_this();
+	if (state_ != state::closing) {
+		const auto self = shared_from_this();
 
-        stream_->read([this, self, handler] (auto code, auto msg) {
-            handler(code, msg);
+		stream_->read([this, self, handler] (auto code, auto msg) {
+			handler(code, msg);
 
-            if (code)
-                erase();
-        });
-    }
+			if (code)
+				erase();
+		});
+	}
 }
 
-void transport_client::write(nlohmann::json json, io::write_handler handler)
+void transport_client::write(nlohmann::json json, stream::write_handler handler)
 {
-    const auto in_progress = queue_.size() > 0;
+	const auto in_progress = queue_.size() > 0;
 
-    queue_.emplace_back(std::move(json), std::move(handler));
+	queue_.emplace_back(std::move(json), std::move(handler));
 
-    if (!in_progress)
-        flush();
+	if (!in_progress)
+		flush();
 }
 
-void transport_client::success(const std::string& cname, io::write_handler handler)
+void transport_client::success(const std::string& cname, stream::write_handler handler)
 {
-    assert(!cname.empty());
+	assert(!cname.empty());
 
-    write({{ "command", cname }}, std::move(handler));
+	write({{ "command", cname }}, std::move(handler));
 }
 
-void transport_client::error(std::error_code code, io::write_handler handler)
+void transport_client::error(std::error_code code, stream::write_handler handler)
 {
-    error(std::move(code), "", std::move(handler));
+	error(std::move(code), "", std::move(handler));
 }
 
-void transport_client::error(std::error_code code, std::string_view cname, io::write_handler handler)
+void transport_client::error(std::error_code code, std::string_view cname, stream::write_handler handler)
 {
-    assert(code);
+	assert(code);
 
-    auto json = nlohmann::json::object({
-        { "error",          code.value()            },
-        { "errorCategory",  code.category().name()  },
-        { "errorMessage",   code.message()          }
-    });
+	auto json = nlohmann::json::object({
+		{ "error",              code.value()            },
+		{ "errorCategory",      code.category().name()  },
+		{ "errorMessage",       code.message()          }
+	});
 
-    // TODO: check newer version of JSON for string_view support.
-    if (!cname.empty())
-        json["command"] = std::string(cname);
+	// TODO: check newer version of JSON for string_view support.
+	if (!cname.empty())
+		json["command"] = std::string(cname);
 
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    write(std::move(json), [this, handler, self] (auto code) {
-        erase();
+	write(std::move(json), [this, handler, self] (auto code) {
+		erase();
 
-        if (handler)
-            handler(code);
-    });
+		if (handler)
+			handler(code);
+	});
 
-    state_ = state::closing;
+	state_ = state::closing;
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/transport_client.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_client.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,106 +36,107 @@
  */
 class transport_client : public std::enable_shared_from_this<transport_client> {
 public:
-    /**
-     * Client state.
-     */
-    enum class state {
-        authenticating,                     //!< client is authenticating
-        ready,                              //!< client is ready
-        closing                             //!< client is closing
-    };
+	/**
+	 * Client state.
+	 */
+	enum class state {
+		authenticating,         //!< client is authenticating
+		ready,                  //!< client is ready
+		closing                 //!< client is closing
+	};
 
 private:
-    state state_{state::authenticating};
-    std::weak_ptr<transport_server> parent_;
-    std::shared_ptr<io::stream> stream_;
-    std::deque<std::pair<nlohmann::json, io::write_handler>> queue_;
+	state state_{state::authenticating};
+	std::weak_ptr<transport_server> parent_;
+	std::shared_ptr<stream> stream_;
+	std::deque<std::pair<nlohmann::json, stream::write_handler>> queue_;
 
-    void flush();
-    void erase();
+	void flush();
+	void erase();
 
 public:
-    /**
-     * Constructor.
-     *
-     * \pre stream != nullptr
-     * \param server the parent
-     * \param stream the I/O stream
-     */
-    transport_client(std::weak_ptr<transport_server> server, std::shared_ptr<io::stream> stream) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \pre stream != nullptr
+	 * \param server the parent
+	 * \param stream the I/O stream
+	 */
+	transport_client(std::weak_ptr<transport_server> server,
+	                 std::shared_ptr<stream> stream) noexcept;
 
-    /**
-     * Get the current client state.
-     *
-     * \return the state
-     */
-    auto get_state() const noexcept -> state;
+	/**
+	 * Get the current client state.
+	 *
+	 * \return the state
+	 */
+	auto get_state() const noexcept -> state;
 
-    /**
-     * Set the client state.
-     *
-     * \param state the new state
-     */
-    void set_state(state state) noexcept;
+	/**
+	 * Set the client state.
+	 *
+	 * \param state the new state
+	 */
+	void set_state(state state) noexcept;
 
-    /**
-     * Start receiving if not closed.
-     *
-     * Possible error codes:
-     *
-     *   - std::errc::network_down in case of errors,
-     *   - std::errc::invalid_argument if the JSON message is invalid,
-     *   - std::errc::not_enough_memory in case of memory failure.
-     *
-     * \pre handler != nullptr
-     * \param handler the handler
-     * \warning Another read operation MUST NOT be running.
-     */
-    void read(io::read_handler handler);
+	/**
+	 * Start receiving if not closed.
+	 *
+	 * Possible error codes:
+	 *
+	 *   - std::errc::network_down in case of errors,
+	 *   - std::errc::invalid_argument if the JSON message is invalid,
+	 *   - std::errc::not_enough_memory in case of memory failure.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the handler
+	 * \warning Another read operation MUST NOT be running.
+	 */
+	void read(stream::read_handler handler);
 
-    /**
-     * Start sending if not closed.
-     *
-     * Possible error codes:
-     *
-     *   - boost::system::errc::network_down in case of errors,
-     *
-     * \pre json.is_object()
-     * \param json the json message
-     * \param handler the optional handler
-     * \note If a write operation is running, it is postponed once ready.
-     */
-    void write(nlohmann::json json, io::write_handler handler = nullptr);
+	/**
+	 * Start sending if not closed.
+	 *
+	 * Possible error codes:
+	 *
+	 *   - boost::system::errc::network_down in case of errors,
+	 *
+	 * \pre json.is_object()
+	 * \param json the json message
+	 * \param handler the optional handler
+	 * \note If a write operation is running, it is postponed once ready.
+	 */
+	void write(nlohmann::json json, stream::write_handler handler = nullptr);
 
-    /**
-     * Convenient success message.
-     *
-     * \param command the command name
-     * \param handler the optional handler
-     * \note If a write operation is running, it is postponed once ready.
-     */
-    void success(const std::string& command, io::write_handler handler = nullptr);
+	/**
+	 * Convenient success message.
+	 *
+	 * \param command the command name
+	 * \param handler the optional handler
+	 * \note If a write operation is running, it is postponed once ready.
+	 */
+	void success(const std::string& command, stream::write_handler handler = nullptr);
 
-    /**
-     * Send an error code to the client.
-     *
-     * \pre code is not 0
-     * \param code the error code
-     * \param handler the optional handler
-     * \note If a write operation is running, it is postponed once ready.
-     */
-    void error(std::error_code code, io::write_handler handler = nullptr);
+	/**
+	 * Send an error code to the client.
+	 *
+	 * \pre code is not 0
+	 * \param code the error code
+	 * \param handler the optional handler
+	 * \note If a write operation is running, it is postponed once ready.
+	 */
+	void error(std::error_code code, stream::write_handler handler = nullptr);
 
-    /**
-     * Send an error code to the client.
-     *
-     * \pre code is not 0
-     * \param code the error code
-     * \param command the command name
-     * \param handler the optional handler
-     * \note If a write operation is running, it is postponed once ready.
-     */
-    void error(std::error_code code, std::string_view command, io::write_handler handler = nullptr);
+	/**
+	 * Send an error code to the client.
+	 *
+	 * \pre code is not 0
+	 * \param code the error code
+	 * \param command the command name
+	 * \param handler the optional handler
+	 * \note If a write operation is running, it is postponed once ready.
+	 */
+	void error(std::error_code code, std::string_view command, stream::write_handler handler = nullptr);
 };
 
 } // !irccd
--- a/libirccd/irccd/daemon/transport_server.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_server.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,162 +31,162 @@
 
 void transport_server::do_auth(std::shared_ptr<transport_client> client, accept_handler handler)
 {
-    assert(client);
-    assert(handler);
+	assert(client);
+	assert(handler);
 
-    client->read([this, client, handler] (auto code, auto message) {
-        if (code) {
-            handler(std::move(code), std::move(client));
-            return;
-        }
+	client->read([this, client, handler] (auto code, auto message) {
+		if (code) {
+			handler(std::move(code), std::move(client));
+			return;
+		}
 
-        const json_util::document doc(message);
-        const auto command = doc.get<std::string>("command");
-        const auto password = doc.get<std::string>("password");
+		const json_util::deserializer doc(message);
+		const auto command = doc.get<std::string>("command");
+		const auto password = doc.get<std::string>("password");
 
-        if (!command || *command != "auth") {
-            client->error(irccd_error::auth_required);
-            code = irccd_error::auth_required;
-        } else if (!password || *password != password_) {
-            client->error(irccd_error::invalid_auth);
-            code = irccd_error::invalid_auth;
-        } else {
-            clients_.insert(client);
-            client->set_state(transport_client::state::ready);
-            client->success("auth");
-            code = irccd_error::no_error;
-        }
+		if (!command || *command != "auth") {
+			client->error(irccd_error::auth_required);
+			code = irccd_error::auth_required;
+		} else if (!password || *password != password_) {
+			client->error(irccd_error::invalid_auth);
+			code = irccd_error::invalid_auth;
+		} else {
+			clients_.insert(client);
+			client->set_state(transport_client::state::ready);
+			client->success("auth");
+			code = irccd_error::no_error;
+		}
 
-        handler(std::move(code), std::move(client));
-    });
+		handler(std::move(code), std::move(client));
+	});
 }
 
 void transport_server::do_greetings(std::shared_ptr<transport_client> client, accept_handler handler)
 {
-    assert(client);
-    assert(handler);
+	assert(client);
+	assert(handler);
 
-    const auto greetings = nlohmann::json({
-        { "program",    "irccd"             },
-        { "major",      IRCCD_VERSION_MAJOR },
-        { "minor",      IRCCD_VERSION_MINOR },
-        { "patch",      IRCCD_VERSION_PATCH },
+	const auto greetings = nlohmann::json({
+		{ "program",    "irccd"                 },
+		{ "major",      IRCCD_VERSION_MAJOR     },
+		{ "minor",      IRCCD_VERSION_MINOR     },
+		{ "patch",      IRCCD_VERSION_PATCH     },
 #if defined(IRCCD_HAVE_JS)
-        { "javascript", true                },
+		{ "javascript", true                    },
 #endif
 #if defined(IRCCD_HAVE_SSL)
-        { "ssl",        true                },
+		{ "ssl",        true                    },
 #endif
-    });
+	});
 
-    client->write(greetings, [this, client, handler] (auto code) {
-        if (code) {
-            handler(std::move(code), std::move(client));
-            return;
-        }
+	client->write(greetings, [this, client, handler] (auto code) {
+		if (code) {
+			handler(std::move(code), std::move(client));
+			return;
+		}
 
-        if (!password_.empty())
-            do_auth(std::move(client), std::move(handler));
-        else {
-            clients_.insert(client);
-            client->set_state(transport_client::state::ready);
-            handler(std::move(code), std::move(client));
-        }
-    });
+		if (!password_.empty())
+			do_auth(std::move(client), std::move(handler));
+		else {
+			clients_.insert(client);
+			client->set_state(transport_client::state::ready);
+			handler(std::move(code), std::move(client));
+		}
+	});
 }
 
-transport_server::transport_server(std::unique_ptr<io::acceptor> acceptor) noexcept
-    : acceptor_(std::move(acceptor))
+transport_server::transport_server(std::unique_ptr<acceptor> acceptor) noexcept
+	: acceptor_(std::move(acceptor))
 {
-    assert(acceptor_);
+	assert(acceptor_);
 }
 
 auto transport_server::get_clients() const noexcept -> const client_set&
 {
-    return clients_;
+	return clients_;
 }
 
 auto transport_server::get_clients() noexcept -> client_set&
 {
-    return clients_;
+	return clients_;
 }
 
 auto transport_server::get_password() const noexcept -> const std::string&
 {
-    return password_;
+	return password_;
 }
 
 void transport_server::set_password(std::string password) noexcept
 {
-    password_ = std::move(password);
+	password_ = std::move(password);
 }
 
 void transport_server::accept(accept_handler handler)
 {
-    acceptor_->accept([this, handler] (auto code, auto stream) {
-        if (code) {
-            handler(code, nullptr);
-            return;
-        }
+	acceptor_->accept([this, handler] (auto code, auto stream) {
+		if (code) {
+			handler(code, nullptr);
+			return;
+		}
 
-        do_greetings(
-            std::make_shared<transport_client>(shared_from_this(), std::move(stream)),
-            std::move(handler)
-        );
-    });
+		do_greetings(
+			std::make_shared<transport_client>(shared_from_this(), std::move(stream)),
+			std::move(handler)
+		);
+	});
 }
 
 transport_error::transport_error(error code) noexcept
-    : system_error(make_error_code(code))
+	: system_error(make_error_code(code))
 {
 }
 
 auto transport_category() noexcept -> const std::error_category&
 {
-    static const class category : public std::error_category {
-    public:
-        const char* name() const noexcept override
-        {
-            return "transport";
-        }
+	static const class category : public std::error_category {
+	public:
+		const char* name() const noexcept override
+		{
+			return "transport";
+		}
 
-        std::string message(int e) const override
-        {
-            switch (static_cast<transport_error::error>(e)) {
-            case transport_error::auth_required:
-                return "authentication required";
-            case transport_error::invalid_auth:
-                return "invalid authentication";
-            case transport_error::invalid_port:
-                return "invalid port";
-            case transport_error::invalid_address:
-                return "invalid address";
-            case transport_error::invalid_hostname:
-                return "invalid hostname";
-            case transport_error::invalid_path:
-                return "invalid socket path";
-            case transport_error::invalid_family:
-                return "invalid family";
-            case transport_error::invalid_certificate:
-                return "invalid certificate";
-            case transport_error::invalid_private_key:
-                return "invalid private key";
-            case transport_error::ssl_disabled:
-                return "ssl is not enabled";
-            case transport_error::not_supported:
-                return "transport not supported";
-            default:
-                return "no error";
-            }
-        }
-    } category;
+		std::string message(int e) const override
+		{
+			switch (static_cast<transport_error::error>(e)) {
+			case transport_error::auth_required:
+				return "authentication required";
+			case transport_error::invalid_auth:
+				return "invalid authentication";
+			case transport_error::invalid_port:
+				return "invalid port";
+			case transport_error::invalid_address:
+				return "invalid address";
+			case transport_error::invalid_hostname:
+				return "invalid hostname";
+			case transport_error::invalid_path:
+				return "invalid socket path";
+			case transport_error::invalid_family:
+				return "invalid family";
+			case transport_error::invalid_certificate:
+				return "invalid certificate";
+			case transport_error::invalid_private_key:
+				return "invalid private key";
+			case transport_error::ssl_disabled:
+				return "ssl is not enabled";
+			case transport_error::not_supported:
+				return "transport not supported";
+			default:
+				return "no error";
+			}
+		}
+	} category;
 
-    return category;
+	return category;
 };
 
 auto make_error_code(transport_error::error e) noexcept -> std::error_code
 {
-    return {static_cast<int>(e), transport_category()};
+	return { static_cast<int>(e), transport_category() };
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/transport_server.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_server.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -128,71 +128,71 @@
  */
 class transport_server : public std::enable_shared_from_this<transport_server> {
 public:
-    /**
-     * Set of clients.
-     */
-    using client_set = std::unordered_set<std::shared_ptr<transport_client>>;
+	/**
+	 * Set of clients.
+	 */
+	using client_set = std::unordered_set<std::shared_ptr<transport_client>>;
 
-    /**
-     * Accept completion handler.
-     */
-    using accept_handler = std::function<void (std::error_code, std::shared_ptr<transport_client>)>;
+	/**
+	 * Accept completion handler.
+	 */
+	using accept_handler = std::function<void (std::error_code, std::shared_ptr<transport_client>)>;
 
 private:
-    client_set clients_;
-    std::unique_ptr<io::acceptor> acceptor_;
-    std::string password_;
+	client_set clients_;
+	std::unique_ptr<acceptor> acceptor_;
+	std::string password_;
 
-    void do_auth(std::shared_ptr<transport_client>, accept_handler);
-    void do_greetings(std::shared_ptr<transport_client>, accept_handler);
+	void do_auth(std::shared_ptr<transport_client>, accept_handler);
+	void do_greetings(std::shared_ptr<transport_client>, accept_handler);
 
 public:
-    /**
-     * Constructor.
-     *
-     * \pre acceptor != nullptr
-     * \param acceptor the stream acceptor
-     */
-    transport_server(std::unique_ptr<io::acceptor> acceptor) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \pre acceptor != nullptr
+	 * \param acceptor the stream acceptor
+	 */
+	transport_server(std::unique_ptr<acceptor> acceptor) noexcept;
 
-    /**
-     * Get the clients.
-     *
-     * \return the clients
-     */
-    auto get_clients() const noexcept -> const client_set&;
+	/**
+	 * Get the clients.
+	 *
+	 * \return the clients
+	 */
+	auto get_clients() const noexcept -> const client_set&;
 
-    /**
-     * Overloaded function.
-     *
-     * \return the clients
-     */
-    auto get_clients() noexcept -> client_set&;
+	/**
+	 * Overloaded function.
+	 *
+	 * \return the clients
+	 */
+	auto get_clients() noexcept -> client_set&;
 
-    /**
-     * Get the current password, empty string means no password.
-     *
-     * \return the password
-     */
-    auto get_password() const noexcept -> const std::string&;
+	/**
+	 * Get the current password, empty string means no password.
+	 *
+	 * \return the password
+	 */
+	auto get_password() const noexcept -> const std::string&;
 
-    /**
-     * Set an optional password, empty string means no password.
-     *
-     * \param password the password
-     */
-    void set_password(std::string password) noexcept;
+	/**
+	 * Set an optional password, empty string means no password.
+	 *
+	 * \param password the password
+	 */
+	void set_password(std::string password) noexcept;
 
-    /**
-     * Accept a client.
-     *
-     * Also perform greetings and authentication under the hood. On success, the
-     * client is added into the server and is ready to use.
-     *
-     * \pre handler != nullptr
-     * \param handler the completion handler
-     */
-    void accept(accept_handler handler);
+	/**
+	 * Accept a client.
+	 *
+	 * Also perform greetings and authentication under the hood. On success, the
+	 * client is added into the server and is ready to use.
+	 *
+	 * \pre handler != nullptr
+	 * \param handler the completion handler
+	 */
+	void accept(accept_handler handler);
 };
 
 /**
@@ -200,53 +200,53 @@
  */
 class transport_error : public std::system_error {
 public:
-    /**
-     * \brief Transport related errors.
-     */
-    enum error {
-        //!< No error.
-        no_error = 0,
+	/**
+	 * \brief Transport related errors.
+	 */
+	enum error {
+		//!< No error.
+		no_error = 0,
 
-        //!< Authentication is required.
-        auth_required,
+		//!< Authentication is required.
+		auth_required,
 
-        //!< Authentication was invalid.
-        invalid_auth,
+		//!< Authentication was invalid.
+		invalid_auth,
 
-        //!< Invalid TCP/IP port.
-        invalid_port,
+		//!< Invalid TCP/IP port.
+		invalid_port,
 
-        //!< Invalid TCP/IP address.
-        invalid_address,
+		//!< Invalid TCP/IP address.
+		invalid_address,
 
-        //!< The specified host was invalid.
-        invalid_hostname,
+		//!< The specified host was invalid.
+		invalid_hostname,
 
-        //!< Invalid unix local path.
-        invalid_path,
+		//!< Invalid unix local path.
+		invalid_path,
 
-        //!< Invalid IPv4/IPv6 family.
-        invalid_family,
+		//!< Invalid IPv4/IPv6 family.
+		invalid_family,
 
-        //!< Invalid certificate given.
-        invalid_certificate,
+		//!< Invalid certificate given.
+		invalid_certificate,
 
-        //!< Invalid private key given.
-        invalid_private_key,
+		//!< Invalid private key given.
+		invalid_private_key,
 
-        //!< SSL was requested but is disabled.
-        ssl_disabled,
+		//!< SSL was requested but is disabled.
+		ssl_disabled,
 
-        //!< Kind of transport not supported on this platform.
-        not_supported
-    };
+		//!< Kind of transport not supported on this platform.
+		not_supported
+	};
 
-    /**
-     * Constructor.
-     *
-     * \param code the error code
-     */
-    transport_error(error code) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \param code the error code
+	 */
+	transport_error(error code) noexcept;
 };
 
 /**
--- a/libirccd/irccd/daemon/transport_service.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_service.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,73 +34,73 @@
 
 void transport_service::handle_command(std::shared_ptr<transport_client> tc, const nlohmann::json& object)
 {
-    assert(object.is_object());
+	assert(object.is_object());
 
-    const json_util::document doc(object);
-    const auto name = doc.get<std::string>("command");
+	const json_util::deserializer doc(object);
+	const auto name = doc.get<std::string>("command");
 
-    if (!name) {
-        tc->error(irccd_error::invalid_message);
-        return;
-    }
+	if (!name) {
+		tc->error(irccd_error::invalid_message);
+		return;
+	}
 
-    const auto cmd = std::find_if(commands_.begin(), commands_.end(), [&] (const auto& cptr) {
-        return cptr->get_name() == *name;
-    });
+	const auto cmd = std::find_if(commands_.begin(), commands_.end(), [&] (const auto& cptr) {
+		return cptr->get_name() == *name;
+	});
 
-    if (cmd == commands_.end())
-        tc->error(irccd_error::invalid_command, *name);
-    else {
-        try {
-            (*cmd)->exec(irccd_, *tc, doc);
-        } catch (const std::system_error& ex) {
-            tc->error(ex.code(), (*cmd)->get_name());
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning("transport", "")
-                << "unknown error not reported: "
-                << ex.what() << std::endl;
-        }
-    }
+	if (cmd == commands_.end())
+		tc->error(irccd_error::invalid_command, *name);
+	else {
+		try {
+			(*cmd)->exec(irccd_, *tc, doc);
+		} catch (const std::system_error& ex) {
+			tc->error(ex.code(), (*cmd)->get_name());
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning("transport", "")
+				<< "unknown error not reported: "
+				<< ex.what() << std::endl;
+		}
+	}
 }
 
 void transport_service::do_recv(std::shared_ptr<transport_client> tc)
 {
-    tc->read([this, tc] (auto code, auto json) {
-        switch (static_cast<std::errc>(code.value())) {
-        case std::errc::not_connected:
-            irccd_.get_log().info("transport", "") << "client disconnected" << std::endl;
-            break;
-        case std::errc::invalid_argument:
-            tc->error(irccd_error::invalid_message);
-            break;
-        default:
-            // Other errors.
-            if (!code) {
-                handle_command(tc, json);
+	tc->read([this, tc] (auto code, auto json) {
+		switch (static_cast<std::errc>(code.value())) {
+		case std::errc::not_connected:
+			irccd_.get_log().info("transport", "") << "client disconnected" << std::endl;
+			break;
+		case std::errc::invalid_argument:
+			tc->error(irccd_error::invalid_message);
+			break;
+		default:
+			// Other errors.
+			if (!code) {
+				handle_command(tc, json);
 
-                if (tc->get_state() == transport_client::state::ready)
-                    do_recv(std::move(tc));
-            }
+				if (tc->get_state() == transport_client::state::ready)
+					do_recv(std::move(tc));
+			}
 
-            break;
-        }
-    });
+			break;
+		}
+	});
 }
 
 void transport_service::do_accept(transport_server& ts)
 {
-    ts.accept([this, &ts] (auto code, auto client) {
-        if (!code) {
-            do_accept(ts);
-            do_recv(std::move(client));
+	ts.accept([this, &ts] (auto code, auto client) {
+		if (!code) {
+			do_accept(ts);
+			do_recv(std::move(client));
 
-            irccd_.get_log().info("transport", "") << "new client connected" << std::endl;
-        }
-    });
+			irccd_.get_log().info("transport", "") << "new client connected" << std::endl;
+		}
+	});
 }
 
 transport_service::transport_service(irccd& irccd) noexcept
-    : irccd_(irccd)
+	: irccd_(irccd)
 {
 }
 
@@ -108,43 +108,43 @@
 
 auto transport_service::get_commands() const noexcept -> const commands&
 {
-    return commands_;
+	return commands_;
 }
 
 auto transport_service::get_commands() noexcept -> commands&
 {
-    return commands_;
+	return commands_;
 }
 
 void transport_service::add(std::shared_ptr<transport_server> ts)
 {
-    assert(ts);
+	assert(ts);
 
-    do_accept(*ts);
-    servers_.push_back(std::move(ts));
+	do_accept(*ts);
+	servers_.push_back(std::move(ts));
 }
 
 void transport_service::broadcast(const nlohmann::json& json)
 {
-    assert(json.is_object());
+	assert(json.is_object());
 
-    for (const auto& servers : servers_)
-        for (const auto& client : servers->get_clients())
-            client->write(json);
+	for (const auto& servers : servers_)
+		for (const auto& client : servers->get_clients())
+			client->write(json);
 }
 
 void transport_service::load(const config& cfg) noexcept
 {
-    for (const auto& section : cfg) {
-        if (section.key() != "transport")
-            continue;
+	for (const auto& section : cfg) {
+		if (section.get_key() != "transport")
+			continue;
 
-        try {
-            add(transport_util::from_config(irccd_.get_service(), section));
-        } catch (const std::exception& ex) {
-            irccd_.get_log().warning("transport", "") << ex.what() << std::endl;
-        }
-    }
+		try {
+			add(transport_util::from_config(irccd_.get_service(), section));
+		} catch (const std::exception& ex) {
+			irccd_.get_log().warning("transport", "") << ex.what() << std::endl;
+		}
+	}
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/transport_service.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_service.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,66 +38,66 @@
  */
 class transport_service {
 public:
-    using commands = std::vector<std::unique_ptr<command>>;
-    using servers = std::vector<std::shared_ptr<transport_server>>;
+	using commands = std::vector<std::unique_ptr<command>>;
+	using servers = std::vector<std::shared_ptr<transport_server>>;
 
 private:
-    irccd& irccd_;
-    commands commands_;
-    servers servers_;
+	irccd& irccd_;
+	commands commands_;
+	servers servers_;
 
-    void handle_command(std::shared_ptr<transport_client>, const nlohmann::json&);
-    void do_recv(std::shared_ptr<transport_client>);
-    void do_accept(transport_server&);
+	void handle_command(std::shared_ptr<transport_client>, const nlohmann::json&);
+	void do_recv(std::shared_ptr<transport_client>);
+	void do_accept(transport_server&);
 
 public:
-    /**
-     * Create the transport service.
-     *
-     * \param irccd the irccd instance
-     */
-    transport_service(irccd& irccd) noexcept;
+	/**
+	 * Create the transport service.
+	 *
+	 * \param irccd the irccd instance
+	 */
+	transport_service(irccd& irccd) noexcept;
 
-    /**
-     * Default destructor.
-     */
-    ~transport_service() noexcept;
+	/**
+	 * Default destructor.
+	 */
+	~transport_service() noexcept;
 
-    /**
-     * Get underlying commands.
-     *
-     * \return the commands
-     */
-    auto get_commands() const noexcept -> const commands&;
+	/**
+	 * Get underlying commands.
+	 *
+	 * \return the commands
+	 */
+	auto get_commands() const noexcept -> const commands&;
 
-    /**
-     * Get underlying commands.
-     *
-     * \return the commands
-     */
-    auto get_commands() noexcept -> commands&;
+	/**
+	 * Get underlying commands.
+	 *
+	 * \return the commands
+	 */
+	auto get_commands() noexcept -> commands&;
 
-    /**
-     * Add a transport server.
-     *
-     * \param ts the transport server
-     */
-    void add(std::shared_ptr<transport_server> ts);
+	/**
+	 * Add a transport server.
+	 *
+	 * \param ts the transport server
+	 */
+	void add(std::shared_ptr<transport_server> ts);
 
-    /**
-     * Send data to all clients.
-     *
-     * \pre object.is_object()
-     * \param object the json object
-     */
-    void broadcast(const nlohmann::json& object);
+	/**
+	 * Send data to all clients.
+	 *
+	 * \pre object.is_object()
+	 * \param object the json object
+	 */
+	void broadcast(const nlohmann::json& object);
 
-    /**
-     * Load transports from the configuration.
-     *
-     * \param cfg the config
-     */
-    void load(const config& cfg) noexcept;
+	/**
+	 * Load transports from the configuration.
+	 *
+	 * \param cfg the config
+	 */
+	void load(const config& cfg) noexcept;
 };
 
 } // !irccd
--- a/libirccd/irccd/daemon/transport_util.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/libirccd/irccd/daemon/transport_util.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,7 +27,7 @@
 #include <irccd/socket_acceptor.hpp>
 
 #if defined(IRCCD_HAVE_SSL)
-#   include <irccd/tls_acceptor.hpp>
+#	include <irccd/tls_acceptor.hpp>
 #endif
 
 #include "transport_util.hpp"
@@ -41,113 +41,113 @@
 
 auto from_config_load_ip_protocol(const ini::section& sc) -> asio::ip::tcp
 {
-    bool ipv4 = true, ipv6 = false;
+	bool ipv4 = true, ipv6 = false;
 
-    /*
-     * Documentation stated family but code checked for 'domain' option.
-     *
-     * As irccdctl uses domain, accept both and unify the option name to 'family'.
-     *
-     * See #637
-     */
-    ini::section::const_iterator it;
+	/*
+	 * Documentation stated family but code checked for 'domain' option.
+	 *
+	 * As irccdctl uses domain, accept both and unify the option name to 'family'.
+	 *
+	 * See #637
+	 */
+	ini::section::const_iterator it;
 
-    if ((it = sc.find("domain")) != sc.end() || (it = sc.find("family")) != sc.end()) {
-        ipv4 = ipv6 = false;
+	if ((it = sc.find("domain")) != sc.end() || (it = sc.find("family")) != sc.end()) {
+		ipv4 = ipv6 = false;
 
-        for (const auto& v : *it) {
-            if (v == "ipv4")
-                ipv4 = true;
-            if (v == "ipv6")
-                ipv6 = true;
-        }
-    }
+		for (const auto& v : *it) {
+			if (v == "ipv4")
+				ipv4 = true;
+			if (v == "ipv6")
+				ipv6 = true;
+		}
+	}
 
-    if (!ipv4 && !ipv6)
-        throw transport_error(transport_error::invalid_family);
+	if (!ipv4 && !ipv6)
+		throw transport_error(transport_error::invalid_family);
 
-    return ipv4 ? asio::ip::tcp::v4() : asio::ip::tcp::v6();
+	return ipv4 ? asio::ip::tcp::v4() : asio::ip::tcp::v6();
 }
 
 auto from_config_load_ip_endpoint(const ini::section& sc) -> asio::ip::tcp::endpoint
 {
-    const auto port = ini_util::get_uint<std::uint16_t>(sc, "port");
-    const auto address = ini_util::optional_string(sc, "address", "*");
+	const auto port = ini_util::get_uint<std::uint16_t>(sc, "port");
+	const auto address = ini_util::optional_string(sc, "address", "*");
 
-    if (!port)
-        throw transport_error(transport_error::invalid_port);
-    if (address.empty())
-        throw transport_error(transport_error::invalid_address);
+	if (!port)
+		throw transport_error(transport_error::invalid_port);
+	if (address.empty())
+		throw transport_error(transport_error::invalid_address);
 
-    const auto protocol = from_config_load_ip_protocol(sc);
+	const auto protocol = from_config_load_ip_protocol(sc);
 
-    return address == "*"
-        ? asio::ip::tcp::endpoint(protocol, *port)
-        : asio::ip::tcp::endpoint(asio::ip::address::from_string(address), *port);
+	return address == "*"
+		? asio::ip::tcp::endpoint(protocol, *port)
+		: asio::ip::tcp::endpoint(asio::ip::address::from_string(address), *port);
 }
 
 auto from_config_load_ip_acceptor(asio::io_service& service, const ini::section& sc) -> asio::ip::tcp::acceptor
 {
-    return asio::ip::tcp::acceptor(service, from_config_load_ip_endpoint(sc), true);
+	return asio::ip::tcp::acceptor(service, from_config_load_ip_endpoint(sc), true);
 }
 
 auto from_config_load_ip(asio::io_service& service, const ini::section& sc) -> std::unique_ptr<transport_server>
 {
-    assert(sc.key() == "transport");
+	assert(sc.get_key() == "transport");
 
-    auto acceptor = from_config_load_ip_acceptor(service, sc);
+	auto acceptor = from_config_load_ip_acceptor(service, sc);
 
-    if (string_util::is_boolean(sc.get("ssl").value())) {
+	if (string_util::is_boolean(sc.get("ssl").get_value())) {
 #if !defined(IRCCD_HAVE_SSL)
-        throw transport_error(transport_error::ssl_disabled);
+		throw transport_error(transport_error::ssl_disabled);
 #else
-        const auto key = sc.get("key").value();
-        const auto cert = sc.get("certificate").value();
+		const auto key = sc.get("key").get_value();
+		const auto cert = sc.get("certificate").get_value();
 
-        if (key.empty())
-            throw transport_error(transport_error::invalid_private_key);
-        if (cert.empty())
-            throw transport_error(transport_error::invalid_certificate);
+		if (key.empty())
+			throw transport_error(transport_error::invalid_private_key);
+		if (cert.empty())
+			throw transport_error(transport_error::invalid_certificate);
 
-        boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
+		boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
 
-        ctx.use_private_key_file(key, boost::asio::ssl::context::pem);
-        ctx.use_certificate_file(cert, boost::asio::ssl::context::pem);
+		ctx.use_private_key_file(key, boost::asio::ssl::context::pem);
+		ctx.use_certificate_file(cert, boost::asio::ssl::context::pem);
 
-        return std::make_unique<transport_server>(
-            std::make_unique<io::tls_acceptor<>>(std::move(ctx), std::move(acceptor)));
+		return std::make_unique<transport_server>(
+			std::make_unique<tls_acceptor<>>(std::move(ctx), std::move(acceptor)));
 #endif
-    }
+	}
 
-    return std::make_unique<transport_server>(
-        std::make_unique<io::ip_acceptor>(std::move(acceptor)));
+	return std::make_unique<transport_server>(
+		std::make_unique<ip_acceptor>(std::move(acceptor)));
 }
 
 auto from_config_load_unix(asio::io_service& service, const ini::section& sc) -> std::unique_ptr<transport_server>
 {
-    assert(sc.key() == "transport");
+	assert(sc.get_key() == "transport");
 
 #if !BOOST_OS_WINDOWS
-    using boost::asio::local::stream_protocol;
+	using boost::asio::local::stream_protocol;
 
-    const auto path = sc.get("path").value();
+	const auto path = sc.get("path").get_value();
 
-    if (path.empty())
-        throw transport_error(transport_error::invalid_path);
+	if (path.empty())
+		throw transport_error(transport_error::invalid_path);
 
-    // Remove the file first.
-    std::remove(path.c_str());
+	// Remove the file first.
+	std::remove(path.c_str());
 
-    stream_protocol::endpoint endpoint(path);
-    stream_protocol::acceptor acceptor(service, std::move(endpoint));
+	stream_protocol::endpoint endpoint(path);
+	stream_protocol::acceptor acceptor(service, std::move(endpoint));
 
-    return std::make_unique<transport_server>(
-        std::make_unique<io::local_acceptor>(std::move(acceptor)));
+	return std::make_unique<transport_server>(
+		std::make_unique<local_acceptor>(std::move(acceptor)));
 #else
-    (void)service;
-    (void)sc;
+	(void)service;
+	(void)sc;
 
-    throw transport_error(transport_error::not_supported);
+	throw transport_error(transport_error::not_supported);
 #endif
 }
 
@@ -155,26 +155,26 @@
 
 auto from_config(asio::io_service& service, const ini::section& sc) -> std::unique_ptr<transport_server>
 {
-    assert(sc.key() == "transport");
+	assert(sc.get_key() == "transport");
 
-    const auto type = sc.get("type").value();
-    const auto password = sc.get("password").value();
+	const auto type = sc.get("type").get_value();
+	const auto password = sc.get("password").get_value();
 
-    if (type.empty())
-        throw transport_error(transport_error::not_supported);
+	if (type.empty())
+		throw transport_error(transport_error::not_supported);
 
-    std::unique_ptr<transport_server> transport;
+	std::unique_ptr<transport_server> transport;
 
-    if (type == "ip")
-        transport = from_config_load_ip(service, sc);
-    else if (type == "unix")
-        transport = from_config_load_unix(service, sc);
-    else
-        throw transport_error(transport_error::not_supported);
+	if (type == "ip")
+		transport = from_config_load_ip(service, sc);
+	else if (type == "unix")
+		transport = from_config_load_unix(service, sc);
+	else
+		throw transport_error(transport_error::not_supported);
 
-    transport->set_password(password);
+	transport->set_password(password);
 
-    return transport;
+	return transport;
 }
 
 } // !irccd::transport_util
--- a/plugins/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,37 +19,37 @@
 project(plugins)
 
 set(
-    IRCCD_JAVASCRIPT_PLUGINS
-    ask
-    auth
-    hangman
-    history
-    joke
-    logger
-    plugin
-    roulette
-    tictactoe
+	IRCCD_JAVASCRIPT_PLUGINS
+	ask
+	auth
+	hangman
+	history
+	joke
+	logger
+	plugin
+	roulette
+	tictactoe
 )
 
 set(
-    IRCCD_NATIVE_PLUGINS
-    links
+	IRCCD_NATIVE_PLUGINS
+	links
 )
 
 set(
-    IRCCD_PLUGINS
-    ${IRCCD_JAVASCRIPT_PLUGINS}
-    ${IRCCD_NATIVE_PLUGINS}
-    CACHE INTERNAL ""
+	IRCCD_PLUGINS
+	${IRCCD_JAVASCRIPT_PLUGINS}
+	${IRCCD_NATIVE_PLUGINS}
+	CACHE INTERNAL ""
 )
 
 foreach (plugin ${IRCCD_JAVASCRIPT_PLUGINS})
-    irccd_define_plugin(
-        NAME ${plugin}
-        TYPE JS
-        SCRIPT ${plugins_SOURCE_DIR}/${plugin}/${plugin}.js
-        DOCS ${plugins_SOURCE_DIR}/${plugin}/${plugin}.md
-    )
+	irccd_define_plugin(
+		NAME ${plugin}
+		TYPE JS
+		SCRIPT ${plugins_SOURCE_DIR}/${plugin}/${plugin}.js
+		DOCS ${plugins_SOURCE_DIR}/${plugin}/${plugin}.md
+	)
 endforeach ()
 
 add_subdirectory(links)
--- a/plugins/ask/ask.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/ask/ask.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "ask",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "Crazy module for asking a medium",
-    version: "@IRCCD_VERSION@"
+	name: "ask",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "Crazy module for asking a medium",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -33,41 +33,41 @@
 
 /* List of answers */
 var answers = [
-    "Yes",
-    "No"
+	"Yes",
+	"No"
 ];
 
 function onLoad()
 {
-    try {
-        // User specified file?
-        if (Plugin.config["file"])
-            path = Plugin.config["file"];
-        else
-            path = Plugin.paths.config + "/answers.conf";
+	try {
+		// User specified file?
+		if (Plugin.config["file"])
+			path = Plugin.config["file"];
+		else
+			path = Plugin.paths.config + "/answers.conf";
 
-        var file = new File(path, "r");
-        var line;
+		var file = new File(path, "r");
+		var line;
 
-        // Reset.
-        answers = [];
+		// Reset.
+		answers = [];
 
-        while ((line = file.readline()))
-            // Skip empty lines.
-            if (line.length > 0)
-                answers.push(line);
-    } catch (e) {
-        Logger.warning(path + ": " + e.message);
-        Logger.warning("using default answers");
-    }
+		while ((line = file.readline()))
+			// Skip empty lines.
+			if (line.length > 0)
+				answers.push(line);
+	} catch (e) {
+		Logger.warning(path + ": " + e.message);
+		Logger.warning("using default answers");
+	}
 }
 
 function onCommand(server, origin, channel)
 {
-    var target = Util.splituser(origin);
-    var response = answers[Math.floor(Math.random() * answers.length)];
+	var target = Util.splituser(origin);
+	var response = answers[Math.floor(Math.random() * answers.length)];
 
-    server.message(channel, target + ", " + response);
+	server.message(channel, target + ", " + response);
 }
 
 onReload = onLoad;
--- a/plugins/auth/auth.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/auth/auth.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "auth",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "Generic plugin to authenticate to services",
-    version: "@IRCCD_VERSION@"
+	name: "auth",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "Generic plugin to authenticate to services",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -33,53 +33,53 @@
 
 function authenticateNickserv(server, password)
 {
-    Logger.info("authenticating to NickServ on " + server.toString());
+	Logger.info("authenticating to NickServ on " + server.toString());
 
-    var username = Plugin.config[server.toString() + ".username"];
-    var str = Util.format("identify #{username}#{password}", {
-        "username": username ? (username + " ") : "",
-        "password": password
-    });
+	var username = Plugin.config[server.toString() + ".username"];
+	var str = Util.format("identify #{username}#{password}", {
+		"username": username ? (username + " ") : "",
+		"password": password
+	});
 
-    server.message("NickServ", str);
+	server.message("NickServ", str);
 }
 
 function authenticateQuakenet(server, password)
 {
-    var username = Plugin.config[server.toString() + ".username"];
+	var username = Plugin.config[server.toString() + ".username"];
 
-    if (!username)
-        Logger.warning("missing username for quakenet backend on " + server.toString());
-    else {
-        Logger.info("authenticating to Q on " + server.toString());
-        server.message("Q@CServe.quakenet.org", Util.format("AUTH #{username} #{password}", {
-            "username": username,
-            "password": password
-        }));
-    }
+	if (!username)
+		Logger.warning("missing username for quakenet backend on " + server.toString());
+	else {
+		Logger.info("authenticating to Q on " + server.toString());
+		server.message("Q@CServe.quakenet.org", Util.format("AUTH #{username} #{password}", {
+			"username": username,
+			"password": password
+		}));
+	}
 }
 
 function onConnect(server)
 {
-    var type = Plugin.config[server.toString() + ".type"];
+	var type = Plugin.config[server.toString() + ".type"];
 
-    if (type) {
-        // Password is mandatory.
-        var password = Plugin.config[server.toString() + ".password"];
+	if (type) {
+		// Password is mandatory.
+		var password = Plugin.config[server.toString() + ".password"];
 
-        if (!password)
-            Logger.warning("missing password for " + server.toString());
+		if (!password)
+			Logger.warning("missing password for " + server.toString());
 
-        switch (type) {
-        case "nickserv":
-            authenticateNickserv(server, password);
-            break;
-        case "quakenet":
-            authenticateQuakenet(server, password);
-            break;
-        default:
-            Logger.warning("unknown '" + type + "' backend");
-            break;
-        }
-    }
+		switch (type) {
+		case "nickserv":
+			authenticateNickserv(server, password);
+			break;
+		case "quakenet":
+			authenticateQuakenet(server, password);
+			break;
+		default:
+			Logger.warning("unknown '" + type + "' backend");
+			break;
+		}
+	}
 }
--- a/plugins/hangman/hangman.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/hangman/hangman.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "hangman",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "A hangman game for IRC",
-    version: "@IRCCD_VERSION@"
+	name: "hangman",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "A hangman game for IRC",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -38,23 +38,23 @@
 
 // Formats.
 Plugin.format = {
-    "asked":        "#{nickname}, '#{letter}' was already asked.",
-    "dead":         "#{nickname}, fail the word was: #{word}.",
-    "found":        "#{nickname}, nice! the word is now #{word}",
-    "running":      "#{nickname}, the game is already running and the word is: #{word}",
-    "start":        "#{nickname}, the game is started, the word to find is: #{word}",
-    "win":          "#{nickname}, congratulations, the word is #{word}.",
-    "wrong-word":   "#{nickname}, this is not the word.",
-    "wrong-player": "#{nickname}, please wait until someone else proposes.",
-    "wrong-letter": "#{nickname}, there is no '#{letter}'."
+	"asked":        "#{nickname}, '#{letter}' was already asked.",
+	"dead":         "#{nickname}, fail the word was: #{word}.",
+	"found":        "#{nickname}, nice! the word is now #{word}",
+	"running":      "#{nickname}, the game is already running and the word is: #{word}",
+	"start":        "#{nickname}, the game is started, the word to find is: #{word}",
+	"win":          "#{nickname}, congratulations, the word is #{word}.",
+	"wrong-word":   "#{nickname}, this is not the word.",
+	"wrong-player": "#{nickname}, please wait until someone else proposes.",
+	"wrong-letter": "#{nickname}, there is no '#{letter}'."
 };
 
 function Hangman(server, channel)
 {
-    this.server = server;
-    this.channel = channel;
-    this.tries = 10;
-    this.select();
+	this.server = server;
+	this.channel = channel;
+	this.tries = 10;
+	this.select();
 }
 
 /**
@@ -66,8 +66,8 @@
  * List of words.
  */
 Hangman.words = {
-    all: [],        //!< All words,
-    registry: {}    //!< Words list per server/channel.
+	all: [],        //!< All words,
+	registry: {}    //!< Words list per server/channel.
 };
 
 /**
@@ -79,7 +79,7 @@
  */
 Hangman.find = function (server, channel)
 {
-    return Hangman.map[server.toString() + '@' + channel];
+	return Hangman.map[server.toString() + '@' + channel];
 }
 
 /**
@@ -91,7 +91,7 @@
  */
 Hangman.create = function (server, channel)
 {
-    return Hangman.map[server.toString() + "@" + channel] = new Hangman(server, channel);
+	return Hangman.map[server.toString() + "@" + channel] = new Hangman(server, channel);
 }
 
 /**
@@ -101,7 +101,7 @@
  */
 Hangman.remove = function (game)
 {
-    delete Hangman.map[game.server + "@" + game.channel];
+	delete Hangman.map[game.server + "@" + game.channel];
 }
 
 /**
@@ -112,14 +112,14 @@
  */
 Hangman.isWord = function (word)
 {
-    if (word.length === 0)
-        return false;
+	if (word.length === 0)
+		return false;
 
-    for (var i = 0; i < word.length; ++i)
-        if (!Unicode.isLetter(word.charCodeAt(i)))
-            return false;
+	for (var i = 0; i < word.length; ++i)
+		if (!Unicode.isLetter(word.charCodeAt(i)))
+			return false;
 
-    return true;
+	return true;
 }
 
 /**
@@ -127,58 +127,31 @@
  */
 Hangman.loadWords = function ()
 {
-    var path;
-
-    // User specified file?
-    if (Plugin.config["file"])
-        path = Plugin.config["file"];
-    else
-        path = Plugin.paths.config + "/words.conf";
-
-    try {
-        Logger.info("loading words...");
+	var path;
 
-        var file = new File(path, "r");
-        var line;
+	// User specified file?
+	if (Plugin.config["file"])
+		path = Plugin.config["file"];
+	else
+		path = Plugin.paths.config + "/words.conf";
 
-        while ((line = file.readline()) !== undefined)
-            if (Hangman.isWord(line))
-                Hangman.words.all.push(line);
-    } catch (e) {
-        throw new Error("could not open '" + path + "'");
-    }
-
-    if (Hangman.words.all.length === 0)
-        throw new Error("empty word database");
+	try {
+		Logger.info("loading words...");
 
-    Logger.info("number of words in database: " + Hangman.words.all.length);
-}
+		var file = new File(path, "r");
+		var line;
 
-/**
- * Load all formats.
- */
-Hangman.loadFormats = function ()
-{
-    // --- DEPRECATED -------------------------------------------
-    //
-    // This code will be removed.
-    //
-    // Since:    2.1.0
-    // Until:    3.0.0
-    // Reason:    new [format] section replaces it.
-    //
-    // ----------------------------------------------------------
-    for (var key in Plugin.format) {
-        var optname = "format-" + key;
+		while ((line = file.readline()) !== undefined)
+			if (Hangman.isWord(line))
+				Hangman.words.all.push(line);
+	} catch (e) {
+		throw new Error("could not open '" + path + "'");
+	}
 
-        if (typeof (Plugin.config[optname]) !== "string")
-            continue;
+	if (Hangman.words.all.length === 0)
+		throw new Error("empty word database");
 
-        if (Plugin.config[optname].length === 0)
-            Logger.warning("skipping empty '" + optname + "' format");
-        else
-            Plugin.format[key] = Plugin.config[optname];
-    }
+	Logger.info("number of words in database: " + Hangman.words.all.length);
 }
 
 /**
@@ -186,24 +159,24 @@
  */
 Hangman.prototype.select = function ()
 {
-    var id = this.server.toString() + "@" + this.channel;
+	var id = this.server.toString() + "@" + this.channel;
 
-    // Reload the words if empty.
-    if (!Hangman.words.registry[id] || Hangman.words.registry[id].length === 0)
-        Hangman.words.registry[id] = Hangman.words.all.slice(0);
+	// Reload the words if empty.
+	if (!Hangman.words.registry[id] || Hangman.words.registry[id].length === 0)
+		Hangman.words.registry[id] = Hangman.words.all.slice(0);
 
-    var i = Math.floor(Math.random() * Hangman.words.registry[id].length);
+	var i = Math.floor(Math.random() * Hangman.words.registry[id].length);
 
-    this.word = Hangman.words.registry[id][i];
+	this.word = Hangman.words.registry[id][i];
 
-    // Erase words from the registry.
-    Hangman.words.registry[id].splice(i, 1);
+	// Erase words from the registry.
+	Hangman.words.registry[id].splice(i, 1);
 
-    // Fill table.
-    this.table = {};
+	// Fill table.
+	this.table = {};
 
-    for (var j = 0; j < this.word.length; ++j)
-        this.table[this.word.charCodeAt(j)] = false;
+	for (var j = 0; j < this.word.length; ++j)
+		this.table[this.word.charCodeAt(j)] = false;
 }
 
 /**
@@ -213,21 +186,21 @@
  */
 Hangman.prototype.formatWord = function ()
 {
-    var str = "";
+	var str = "";
 
-    for (var i = 0; i < this.word.length; ++i) {
-        var ch = this.word.charCodeAt(i);
+	for (var i = 0; i < this.word.length; ++i) {
+		var ch = this.word.charCodeAt(i);
 
-        if (!this.table[ch])
-            str += "_";
-        else
-            str += String.fromCharCode(ch);
+		if (!this.table[ch])
+			str += "_";
+		else
+			str += String.fromCharCode(ch);
 
-        if (i + 1 < this.word.length)
-            str += " ";
-    }
+		if (i + 1 < this.word.length)
+			str += " ";
+	}
 
-    return str;
+	return str;
 }
 
 /**
@@ -239,155 +212,154 @@
  */
 Hangman.prototype.propose = function (ch, nickname)
 {
-    var status = "found";
+	var status = "found";
 
-    // Check for collaborative mode.
-    if (Plugin.config["collaborative"] === "true" && !this.query) {
-        if (this.last !== undefined && this.last === nickname)
-            return "wrong-player";
+	// Check for collaborative mode.
+	if (Plugin.config["collaborative"] === "true" && !this.query) {
+		if (this.last !== undefined && this.last === nickname)
+			return "wrong-player";
 
-        this.last = nickname;
-    }
+		this.last = nickname;
+	}
 
-    if (typeof(ch) == "number") {
-        if (this.table[ch] === undefined) {
-            this.tries -= 1;
-            status = "wrong-letter";
-        } else {
-            if (this.table[ch]) {
-                this.tries -= 1;
-                status = "asked";
-            } else
-                this.table[ch] = true;
-        }
-    } else {
-        if (this.word != ch) {
-            this.tries -= 1;
-            status = "wrong-word";
-        } else
-            status = "win";
-    }
+	if (typeof(ch) == "number") {
+		if (this.table[ch] === undefined) {
+			this.tries -= 1;
+			status = "wrong-letter";
+		} else {
+			if (this.table[ch]) {
+				this.tries -= 1;
+				status = "asked";
+			} else
+				this.table[ch] = true;
+		}
+	} else {
+		if (this.word != ch) {
+			this.tries -= 1;
+			status = "wrong-word";
+		} else
+			status = "win";
+	}
 
-    // Check if dead.
-    if (this.tries <= 0)
-        status = "dead";
+	// Check if dead.
+	if (this.tries <= 0)
+		status = "dead";
 
-    // Check if win.
-    var win = true;
+	// Check if win.
+	var win = true;
 
-    for (var i = 0; i < this.word.length; ++i) {
-        if (!this.table[this.word.charCodeAt(i)]) {
-            win = false;
-            break;
-        }
-    }
+	for (var i = 0; i < this.word.length; ++i) {
+		if (!this.table[this.word.charCodeAt(i)]) {
+			win = false;
+			break;
+		}
+	}
 
-    if (win)
-        status = "win";
+	if (win)
+		status = "win";
 
-    return status;
+	return status;
 }
 
 function onLoad()
 {
-    Hangman.loadFormats();
-    Hangman.loadWords();
+	Hangman.loadWords();
 }
 
 onReload = onLoad;
 
 function propose(server, channel, origin, game, proposition)
 {
-    var kw = {
-        channel: channel,
-        command: server.info().commandChar + Plugin.info().name,
-        nickname: Util.splituser(origin),
-        origin: origin,
-        plugin: Plugin.info().name,
-        server: server.toString()
-    };
+	var kw = {
+		channel: channel,
+		command: server.info().commandChar + Plugin.info().name,
+		nickname: Util.splituser(origin),
+		origin: origin,
+		plugin: Plugin.info().name,
+		server: server.toString()
+	};
 
-    var st = game.propose(proposition, kw.nickname);
+	var st = game.propose(proposition, kw.nickname);
 
-    switch (st) {
-    case "found":
-        kw.word = game.formatWord();
-        server.message(channel, Util.format(Plugin.format["found"], kw));
-        break;
-    case "wrong-letter":
-    case "wrong-player":
-    case "wrong-word":
-        kw.word = proposition;
-    case "asked":
-        kw.letter = String.fromCharCode(proposition);
-        server.message(channel, Util.format(Plugin.format[st], kw));
-        break;
-    case "dead":
-    case "win":
-        kw.word = game.word;
-        server.message(channel, Util.format(Plugin.format[st], kw));
+	switch (st) {
+	case "found":
+		kw.word = game.formatWord();
+		server.message(channel, Util.format(Plugin.format["found"], kw));
+		break;
+	case "wrong-letter":
+	case "wrong-player":
+	case "wrong-word":
+		kw.word = proposition;
+	case "asked":
+		kw.letter = String.fromCharCode(proposition);
+		server.message(channel, Util.format(Plugin.format[st], kw));
+		break;
+	case "dead":
+	case "win":
+		kw.word = game.word;
+		server.message(channel, Util.format(Plugin.format[st], kw));
 
-        // Remove the game.
-        Hangman.remove(game);
-        break;
-    default:
-        break;
-    }
+		// Remove the game.
+		Hangman.remove(game);
+		break;
+	default:
+		break;
+	}
 }
 
 function onCommand(server, origin, channel, message)
 {
-    var isquery = server.isSelf(channel);
+	var isquery = server.isSelf(channel);
 
-    if (isquery)
-        channel = origin;
-    else
-        channel = channel.toLowerCase();
+	if (isquery)
+		channel = origin;
+	else
+		channel = channel.toLowerCase();
 
-    var game = Hangman.find(server, channel);
-    var kw = {
-        channel: channel,
-        command: server.info().commandChar + Plugin.info().name,
-        nickname: Util.splituser(origin),
-        origin: origin,
-        plugin: Plugin.info().name,
-        server: server.toString()
-    };
+	var game = Hangman.find(server, channel);
+	var kw = {
+		channel: channel,
+		command: server.info().commandChar + Plugin.info().name,
+		nickname: Util.splituser(origin),
+		origin: origin,
+		plugin: Plugin.info().name,
+		server: server.toString()
+	};
 
-    if (game) {
-        var list = message.split(" \t");
+	if (game) {
+		var list = message.split(" \t");
 
-        if (list.length === 0 || String(list[0]).length === 0) {
-            kw.word = game.formatWord();
-            server.message(channel, Util.format(Plugin.format["running"], kw));
-        } else {
-            var word = String(list[0]);
+		if (list.length === 0 || String(list[0]).length === 0) {
+			kw.word = game.formatWord();
+			server.message(channel, Util.format(Plugin.format["running"], kw));
+		} else {
+			var word = String(list[0]);
 
-            if (Hangman.isWord(word))
-                propose(server, channel, origin, game, word);
-        }
-    } else {
-        game = Hangman.create(server, channel);
-        game.query = isquery;
-        kw.word = game.formatWord();
-        server.message(channel, Util.format(Plugin.format["start"], kw));
-    }
+			if (Hangman.isWord(word))
+				propose(server, channel, origin, game, word);
+		}
+	} else {
+		game = Hangman.create(server, channel);
+		game.query = isquery;
+		kw.word = game.formatWord();
+		server.message(channel, Util.format(Plugin.format["start"], kw));
+	}
 
-    return game;
+	return game;
 }
 
 function onMessage(server, origin, channel, message)
 {
-    if (server.isSelf(channel))
-        channel = origin;
-    else
-        channel = channel.toLowerCase();
+	if (server.isSelf(channel))
+		channel = origin;
+	else
+		channel = channel.toLowerCase();
 
-    var game = Hangman.find(server, channel);
+	var game = Hangman.find(server, channel);
 
-    if (!game)
-        return;
+	if (!game)
+		return;
 
-    if (message.length === 1 && Unicode.isLetter(message.charCodeAt(0)))
-        propose(server, channel, origin, game, message.charCodeAt(0));
+	if (message.length === 1 && Unicode.isLetter(message.charCodeAt(0)))
+		propose(server, channel, origin, game, message.charCodeAt(0));
 }
--- a/plugins/history/history.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/history/history.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,221 +18,190 @@
 
 // Plugin information.
 info = {
-    name: "history",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "track nickname's history",
-    version: "@IRCCD_VERSION@"
+	name: "history",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "track nickname's history",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
-var Directory   = Irccd.Directory;
-var File        = Irccd.File;
-var Logger      = Irccd.Logger;
-var Plugin      = Irccd.Plugin;
-var Server      = Irccd.Server;
-var Util        = Irccd.Util;
+var Directory = Irccd.Directory;
+var File = Irccd.File;
+var Logger = Irccd.Logger;
+var Plugin = Irccd.Plugin;
+var Server = Irccd.Server;
+var Util = Irccd.Util;
 
 Plugin.format = {
-    "error":    "#{nickname}, I'm sorry, something went wrong.",
-    "seen":     "#{nickname}, I've seen #{target} for the last time the %d-%m-%Y %H:%M",
-    "said":     "#{nickname}, #{target} said on %d-%m-%Y %H:%M: #{message}",
-    "unknown":  "#{nickname}, I've never seen #{target}.",
-    "usage":    "#{nickname}, usage: #{plugin} seen | said <target>."
+	"error":        "#{nickname}, I'm sorry, something went wrong.",
+	"seen":         "#{nickname}, I've seen #{target} for the last time the %d-%m-%Y %H:%M",
+	"said":         "#{nickname}, #{target} said on %d-%m-%Y %H:%M: #{message}",
+	"unknown":      "#{nickname}, I've never seen #{target}.",
+	"usage":        "#{nickname}, usage: #{plugin} seen | said <target>."
 };
 
 function isSelf(server, origin)
 {
-    return server.info().nickname === Util.splituser(origin);
+	return server.info().nickname === Util.splituser(origin);
 }
 
 function command(server)
 {
-    return server.info().commandChar + "history";
+	return server.info().commandChar + "history";
 }
 
 function path(server, channel)
 {
-    var p;
+	var p;
 
-    if (Plugin.config["file"] !== undefined) {
-        p = Util.format(Plugin.config["file"], {
-            "server":    server.toString(),
-            "channel":    channel
-        });
-    } else
-        p = Plugin.paths.cache + "/db.json";
+	if (Plugin.config["file"] !== undefined) {
+		p = Util.format(Plugin.config["file"], {
+			"server":       server.toString(),
+			"channel":      channel
+		});
+	} else
+		p = Plugin.paths.cache + "/db.json";
 
-    return p;
+	return p;
 }
 
 function read(server, channel, nickname)
 {
-    var p = path(server, channel);
-    var db = {};
+	var p = path(server, channel);
+	var db = {};
 
-    if (File.exists(p)) {
-        var file = new File(path(server, channel), "r");
-        var str = file.read();
+	if (File.exists(p)) {
+		var file = new File(path(server, channel), "r");
+		var str = file.read();
 
-        db = JSON.parse(str);
-    }
+		db = JSON.parse(str);
+	}
 
-    // Complete if needed.
-    if (!db[server])
-        db[server] = {};
-    if (!db[server][channel])
-        db[server][channel] = {};
-    if (!db[server][channel][nickname])
-        db[server][channel][nickname] = {};
+	// Complete if needed.
+	if (!db[server])
+		db[server] = {};
+	if (!db[server][channel])
+		db[server][channel] = {};
+	if (!db[server][channel][nickname])
+		db[server][channel][nickname] = {};
 
-    return db;
+	return db;
 }
 
 function write(server, channel, nickname, message)
 {
-    var db = read(server, channel, nickname);
-    var entry = db[server][channel][nickname];
-    var p = path(server, channel);
+	var db = read(server, channel, nickname);
+	var entry = db[server][channel][nickname];
+	var p = path(server, channel);
 
-    if (!File.exists(File.dirname(p))) {
-        Logger.debug("creating directory " + File.dirname(p));
-        Directory.mkdir(File.dirname(p));
-    }
+	if (!File.exists(File.dirname(p))) {
+		Logger.debug("creating directory " + File.dirname(p));
+		Directory.mkdir(File.dirname(p));
+	}
 
-    var file = new File(path(server, channel), "wt");
+	var file = new File(path(server, channel), "wt");
 
-    entry.timestamp = Date.now();
-    entry.message = (message) ? message : entry.message;
+	entry.timestamp = Date.now();
+	entry.message = (message) ? message : entry.message;
 
-    file.write(JSON.stringify(db));
+	file.write(JSON.stringify(db));
 }
 
 function find(server, channel, target)
 {
-    var db = read(server, channel, target);
-    var it = db[server][channel][target];
-
-    if (it.timestamp)
-        return it;
-}
+	var db = read(server, channel, target);
+	var it = db[server][channel][target];
 
-function loadFormats()
-{
-    // --- DEPRECATED -------------------------------------------
-    //
-    // This code will be removed.
-    //
-    // Since:    2.1.0
-    // Until:    3.0.0
-    // Reason:    new [format] section replaces it.
-    //
-    // ----------------------------------------------------------
-    for (var key in Plugin.format) {
-        var optname = "format-" + key;
-
-        if (typeof (Plugin.config[optname]) !== "string")
-            continue;
-
-        if (Plugin.config[optname].length === 0)
-            Logger.warning("skipping empty '" + optname + "' format");
-        else
-            Plugin.format[key] = Plugin.config[optname];
-    }
+	if (it.timestamp)
+		return it;
 }
 
 function onCommand(server, origin, channel, message)
 {
-    channel = channel.toLowerCase();
+	channel = channel.toLowerCase();
 
-    var args = message.trim().split(" ");
-    var kw = {
-        channel: channel,
-        command: command(server),
-        nickname: Util.splituser(origin),
-        origin: origin,
-        plugin: Plugin.info().name,
-        server: server.toString()
-    };
+	var args = message.trim().split(" ");
+	var kw = {
+		channel: channel,
+		command: command(server),
+		nickname: Util.splituser(origin),
+		origin: origin,
+		plugin: Plugin.info().name,
+		server: server.toString()
+	};
 
-    if (args.length !== 2 || args[0].length === 0 || args[1].length === 0) {
-        server.message(channel, Util.format(Plugin.format.usage, kw));
-        return;
-    }
+	if (args.length !== 2 || args[0].length === 0 || args[1].length === 0) {
+		server.message(channel, Util.format(Plugin.format.usage, kw));
+		return;
+	}
 
-    if (args[0] !== "seen" && args[0] !== "said") {
-        server.message(channel, Util.format(Plugin.format.usage, kw));
-        return;
-    }
+	if (args[0] !== "seen" && args[0] !== "said") {
+		server.message(channel, Util.format(Plugin.format.usage, kw));
+		return;
+	}
 
-    args[1] = args[1].toLowerCase();
+	args[1] = args[1].toLowerCase();
 
-    if (isSelf(server, args[1]))
-        return;
+	if (isSelf(server, args[1]))
+		return;
 
-    try {
-        var info = find(server, channel, args[1]);
+	try {
+		var info = find(server, channel, args[1]);
 
-        kw.target = args[1];
+		kw.target = args[1];
 
-        if (!info) {
-            server.message(channel, Util.format(Plugin.format.unknown, kw));
-            return;
-        }
+		if (!info) {
+			server.message(channel, Util.format(Plugin.format.unknown, kw));
+			return;
+		}
 
-        kw.date = info.timestamp;
-        kw.message = info.message ? info.message : "";
+		kw.date = info.timestamp;
+		kw.message = info.message ? info.message : "";
 
-        server.message(channel, Util.format(Plugin.format[args[0] == "seen" ? "seen" : "said"], kw));
-    } catch (e) {
-        server.message(channel, Util.format(Plugin.format["error"], kw));
-    }
+		server.message(channel, Util.format(Plugin.format[args[0] == "seen" ? "seen" : "said"], kw));
+	} catch (e) {
+		server.message(channel, Util.format(Plugin.format["error"], kw));
+	}
 }
 
 function onJoin(server, origin, channel)
 {
-    origin = Util.splituser(origin).toLowerCase();
-    channel = channel.toLowerCase();
+	origin = Util.splituser(origin).toLowerCase();
+	channel = channel.toLowerCase();
 
-    write(server, channel, origin);
+	write(server, channel, origin);
 }
 
 function onMessage(server, origin, channel, message)
 {
-    origin = Util.splituser(origin).toLowerCase();
-    channel = channel.toLowerCase();
+	origin = Util.splituser(origin).toLowerCase();
+	channel = channel.toLowerCase();
 
-    write(server, channel, origin, message);
+	write(server, channel, origin, message);
 }
 
 onMe = onMessage;
 
 function onTopic(server, origin, channel)
 {
-    origin = Util.splituser(origin).toLowerCase();
-    channel = channel.toLowerCase();
+	origin = Util.splituser(origin).toLowerCase();
+	channel = channel.toLowerCase();
 
-    write(server, origin, channel)
+	write(server, origin, channel)
 }
 
 function onLoad()
 {
-    var table = Server.list();
-
-    for (var k in table)
-        for (var c in table[k].info().channels)
-            table[k].names(c);
+	var table = Server.list();
 
-    loadFormats();
-}
-
-function onReload()
-{
-    loadFormats();
+	for (var k in table)
+		for (var c in table[k].info().channels)
+			table[k].names(c);
 }
 
 function onNames(server, channel, list)
 {
-    for (var i = 0; i < list.length; ++i)
-        write(server, channel.toLowerCase(), list[i]);
+	for (var i = 0; i < list.length; ++i)
+		write(server, channel.toLowerCase(), list[i]);
 }
--- a/plugins/joke/joke.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/joke/joke.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,18 +18,18 @@
 
 // Plugin information.
 info = {
-    name: "joke",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "display some jokes",
-    version: "@IRCCD_VERSION@"
+	name: "joke",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "display some jokes",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
-var File    = Irccd.File;
-var Logger  = Irccd.Logger;
-var Plugin  = Irccd.Plugin;
-var Util    = Irccd.Util;
+var File = Irccd.File;
+var Logger = Irccd.Logger;
+var Plugin = Irccd.Plugin;
+var Util = Irccd.Util;
 
 Plugin.config["max-list-lines"] = 5;
 Plugin.format["error"] = "#{nickname}: no jokes available";
@@ -84,42 +84,42 @@
  */
 function load(server, channel)
 {
-    var path = Plugin.config.file
-        ? Plugin.config.file
-        : Plugin.paths.data + "/jokes.json";
+	var path = Plugin.config.file
+		? Plugin.config.file
+		: Plugin.paths.data + "/jokes.json";
 
-    // Allow formatting to select different jokes per server/channel.
-    path = Util.format(path, {
-        server: server.toString(),
-        channel: channel
-    });
+	// Allow formatting to select different jokes per server/channel.
+	path = Util.format(path, {
+		server: server.toString(),
+		channel: channel
+	});
 
-    try {
-        var file = new File(path, "r");
-        var data = JSON.parse(file.read());
-    } catch (e) {
-        throw Error(path + ": " + e.message);
-    }
+	try {
+		var file = new File(path, "r");
+		var data = JSON.parse(file.read());
+	} catch (e) {
+		throw Error(path + ": " + e.message);
+	}
 
-    if (!data || !data.length)
-        throw Error(path + ": no jokes found");
+	if (!data || !data.length)
+		throw Error(path + ": no jokes found");
 
-    // Ensure that jokes only contain strings.
-    var jokes = data.filter(function (joke) {
-        if (!joke || joke.length == 0 || joke.length > parseInt(Plugin.config["max-list-lines"]))
-            return false;
+	// Ensure that jokes only contain strings.
+	var jokes = data.filter(function (joke) {
+		if (!joke || joke.length == 0 || joke.length > parseInt(Plugin.config["max-list-lines"]))
+			return false;
 
-        for (var i = 0; i < joke.length; ++i)
-            if (typeof (joke[i]) !== "string")
-                return false;
+		for (var i = 0; i < joke.length; ++i)
+			if (typeof (joke[i]) !== "string")
+				return false;
 
-        return true;
-    });
+		return true;
+	});
 
-    if (!jokes || jokes.length === 0)
-        throw Error(path + ": empty jokes");
+	if (!jokes || jokes.length === 0)
+		throw Error(path + ": empty jokes");
 
-    return jokes;
+	return jokes;
 }
 
 /**
@@ -129,7 +129,7 @@
  */
 function id(server, channel)
 {
-    return channel + "@" + server.toString();
+	return channel + "@" + server.toString();
 }
 
 /**
@@ -142,8 +142,8 @@
  */
 function show(server, channel, joke)
 {
-    for (var l = 0; l < joke.length; ++l)
-        server.message(channel, joke[l]);
+	for (var l = 0; l < joke.length; ++l)
+		server.message(channel, joke[l]);
 }
 
 /**
@@ -154,42 +154,42 @@
  */
 function remove(i, index)
 {
-    table[i].splice(index, 1);
+	table[i].splice(index, 1);
 
-    if (table[i].length == 0)
-        delete table[i];
+	if (table[i].length == 0)
+		delete table[i];
 }
 
 function onCommand(server, origin, channel, message)
 {
-    var i = id(server, channel);
+	var i = id(server, channel);
 
-    if (!table[i]) {
-        Logger.debug("reloading for " + i);
+	if (!table[i]) {
+		Logger.debug("reloading for " + i);
 
-        try {
-            table[i] = load(server, channel);
-        } catch (e) {
-            Logger.warning(e.message);
-            server.message(channel, Util.format(Plugin.format.error, {
-                server: server.toString(),
-                channel: channel,
-                origin: origin,
-                nickname: Util.splituser(origin)
-            }));
+		try {
+			table[i] = load(server, channel);
+		} catch (e) {
+			Logger.warning(e.message);
+			server.message(channel, Util.format(Plugin.format.error, {
+				server: server.toString(),
+				channel: channel,
+				origin: origin,
+				nickname: Util.splituser(origin)
+			}));
 
-            return;
-        }
-    }
+			return;
+		}
+	}
 
-    var index = Math.floor(Math.random() * table[i].length);
+	var index = Math.floor(Math.random() * table[i].length);
 
-    show(server, channel, table[i][index]);
-    remove(i, index);
+	show(server, channel, table[i][index]);
+	remove(i, index);
 }
 
 function onReload()
 {
-    // This will force reload of jokes on next onCommand.
-    table = {};
+	// This will force reload of jokes on next onCommand.
+	table = {};
 }
--- a/plugins/links/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -21,16 +21,16 @@
 add_subdirectory(extern/uriparser)
 
 irccd_define_plugin(
-    NAME links
-    TYPE NATIVE
-    SOURCES
-        ${plugin-links_SOURCE_DIR}/links.cpp
-        ${plugin-links_SOURCE_DIR}/links.hpp
-        ${plugin-links_SOURCE_DIR}/requester.cpp
-        ${plugin-links_SOURCE_DIR}/requester.hpp
-        ${plugin-links_SOURCE_DIR}/scope_exit.cpp
-        ${plugin-links_SOURCE_DIR}/scope_exit.hpp
-        ${plugin-links_SOURCE_DIR}/uri.cpp
-        ${plugin-links_SOURCE_DIR}/uri.hpp
-    LIBRARIES liburiparser
+	NAME links
+	TYPE NATIVE
+	SOURCES
+		${plugin-links_SOURCE_DIR}/links.cpp
+		${plugin-links_SOURCE_DIR}/links.hpp
+		${plugin-links_SOURCE_DIR}/requester.cpp
+		${plugin-links_SOURCE_DIR}/requester.hpp
+		${plugin-links_SOURCE_DIR}/scope_exit.cpp
+		${plugin-links_SOURCE_DIR}/scope_exit.hpp
+		${plugin-links_SOURCE_DIR}/uri.cpp
+		${plugin-links_SOURCE_DIR}/uri.hpp
+	LIBRARIES liburiparser
 )
--- a/plugins/links/links.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/links.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,55 +38,55 @@
 
 auto links_plugin::get_name() const noexcept -> string_view
 {
-    return "links";
+	return "links";
 }
 
 auto links_plugin::get_author() const noexcept -> string_view
 {
-    return "David Demelier <markand@malikania.fr>";
+	return "David Demelier <markand@malikania.fr>";
 }
 
 auto links_plugin::get_license() const noexcept -> string_view
 {
-    return "ISC";
+	return "ISC";
 }
 
 auto links_plugin::get_summary() const noexcept -> string_view
 {
-    return "show webpage title";
+	return "show webpage title";
 }
 
 auto links_plugin::get_version() const noexcept -> string_view
 {
-    return IRCCD_VERSION;
+	return IRCCD_VERSION;
 }
 
 void links_plugin::set_options(const map& conf)
 {
-    if (const auto it = conf.find("timeout"); it != conf.end())
-        if (const auto v = to_uint(it->second); v)
-            conf_timeout = *v;
+	if (const auto it = conf.find("timeout"); it != conf.end())
+		if (const auto v = to_uint(it->second); v)
+			conf_timeout = *v;
 }
 
 void links_plugin::set_formats(const map& formats)
 {
-    if (const auto it = formats.find("info"); it != formats.end())
-        format_info = it->second;
+	if (const auto it = formats.find("info"); it != formats.end())
+		format_info = it->second;
 }
 
 void links_plugin::handle_message(irccd& irccd, const message_event& ev)
 {
-    requester::run(irccd.get_service(), ev.server, ev.origin, ev.channel, ev.message);
+	requester::run(irccd.get_service(), ev.server, ev.origin, ev.channel, ev.message);
 }
 
 auto links_plugin::abi() -> version
 {
-    return version();
+	return version();
 }
 
 auto links_plugin::init(string id) -> unique_ptr<plugin>
 {
-    return make_unique<links_plugin>(move(id));
+	return make_unique<links_plugin>(move(id));
 }
 
 BOOST_DLL_ALIAS(links_plugin::abi, irccd_abi_links)
--- a/plugins/links/links.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/links.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,72 +33,72 @@
  */
 class links_plugin : public plugin {
 public:
-    // options.
-    static inline unsigned conf_timeout{30U};
+	// options.
+	static inline unsigned conf_timeout{30U};
 
-    // formats.
-    static inline std::string format_info{"#{title}"};
+	// formats.
+	static inline std::string format_info{"#{title}"};
 
 public:
-    /**
-     * Inherited constructors.
-     */
-    using plugin::plugin;
+	/**
+	 * Inherited constructors.
+	 */
+	using plugin::plugin;
 
-    /**
-     * \copydoc plugin::get_name
-     */
-    auto get_name() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_name
+	 */
+	auto get_name() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_author
-     */
-    auto get_author() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_author
+	 */
+	auto get_author() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_license
-     */
-    auto get_license() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_license
+	 */
+	auto get_license() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_summary
-     */
-    auto get_summary() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_summary
+	 */
+	auto get_summary() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::get_version
-     */
-    auto get_version() const noexcept -> std::string_view override;
+	/**
+	 * \copydoc plugin::get_version
+	 */
+	auto get_version() const noexcept -> std::string_view override;
 
-    /**
-     * \copydoc plugin::set_options
-     */
-    void set_options(const map&) override;
+	/**
+	 * \copydoc plugin::set_options
+	 */
+	void set_options(const map&) override;
 
-    /**
-     * \copydoc plugin::set_formats
-     */
-    void set_formats(const map&) override;
+	/**
+	 * \copydoc plugin::set_formats
+	 */
+	void set_formats(const map&) override;
 
-    /**
-     * \copydoc plugin::handle_message
-     */
-    void handle_message(irccd&, const message_event&) override;
+	/**
+	 * \copydoc plugin::handle_message
+	 */
+	void handle_message(irccd&, const message_event&) override;
 
-    /**
-     * Export ABI.
-     *
-     * \return the compiled version
-     */
-    static auto abi() -> version;
+	/**
+	 * Export ABI.
+	 *
+	 * \return the compiled version
+	 */
+	static auto abi() -> version;
 
-    /**
-     * Create the plugin
-     *
-     * \param id the plugin id
-     * \return the compiled version
-     */
-    static auto init(std::string) -> std::unique_ptr<plugin>;
+	/**
+	 * Create the plugin
+	 *
+	 * \param id the plugin id
+	 * \return the compiled version
+	 */
+	static auto init(std::string) -> std::unique_ptr<plugin>;
 };
 
 } // !irccd
--- a/plugins/links/requester.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/requester.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -38,15 +38,10 @@
 using std::string;
 using std::variant;
 
-using boost::beast::flat_buffer;
 using boost::beast::http::async_read;
 using boost::beast::http::async_write;
-using boost::beast::http::empty_body;
 using boost::beast::http::field;
-using boost::beast::http::request;
-using boost::beast::http::response;
 using boost::beast::http::status;
-using boost::beast::http::string_body;
 using boost::beast::http::verb;
 
 using boost::asio::async_connect;
@@ -66,221 +61,221 @@
 
 void requester::notify(const string& title)
 {
-    subst subst;
+	subst subst;
 
-    subst.keywords.emplace("channel", channel_);
-    subst.keywords.emplace("nickname", irc::user::parse(origin_).nick);
-    subst.keywords.emplace("origin", origin_);
-    subst.keywords.emplace("server", server_->get_id());
-    subst.keywords.emplace("title", title);
+	subst.keywords.emplace("channel", channel_);
+	subst.keywords.emplace("nickname", irc::user::parse(origin_).nick);
+	subst.keywords.emplace("origin", origin_);
+	subst.keywords.emplace("server", server_->get_id());
+	subst.keywords.emplace("title", title);
 
-    server_->message(channel_, format(links_plugin::format_info, subst));
+	server_->message(channel_, format(links_plugin::format_info, subst));
 }
 
 void requester::parse()
 {
-    /*
-     * Use a regex because Boost's XML parser is strict and many web pages may
-     * have invalid or broken tags.
-     */
-    static const regex regex("<title>([^<]+)<\\/title>");
+	/*
+	 * Use a regex because Boost's XML parser is strict and many web pages may
+	 * have invalid or broken tags.
+	 */
+	static const regex regex("<title>([^<]+)<\\/title>");
 
-    string data(res_.body().data());
-    smatch match;
+	string data(res_.body().data());
+	smatch match;
 
-    if (regex_search(data, match, regex))
-        notify(match[1]);
+	if (regex_search(data, match, regex))
+		notify(match[1]);
 }
 
 void requester::handle_read(const error_code& code)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (code)
-        return;
+	if (code)
+		return;
 
-    // Request again in case of relocation.
-    if (const auto it = res_.find(field::location); it != res_.end() && level_ < 32U) {
-        const string location(it->value().data(), it->value().size());
-        auto& io = timer_.get_io_service();
-        auto uri = uri::parse(location);
+	// Request again in case of relocation.
+	if (const auto it = res_.find(field::location); it != res_.end() && level_ < 32U) {
+		const string location(it->value().data(), it->value().size());
+		auto& io = timer_.get_io_service();
+		auto uri = uri::parse(location);
 
-        if (!uri)
-            return;
+		if (!uri)
+			return;
 
-        shared_ptr<requester>(new requester(io, server_, channel_, origin_, move(*uri), level_ + 1))->start();
-    } else if (res_.result() == status::ok)
-        parse();
+		shared_ptr<requester>(new requester(io, server_, channel_, origin_, move(*uri), level_ + 1))->start();
+	} else if (res_.result() == status::ok)
+		parse();
 }
 
 void requester::read()
 {
-    const auto self = shared_from_this();
-    const auto wrap = [self] (auto code, auto) {
-        self->handle_read(code);
-    };
+	const auto self = shared_from_this();
+	const auto wrap = [self] (auto code, auto) {
+		self->handle_read(code);
+	};
 
-    timer();
+	timer();
 
-    switch (socket_.index()) {
-    case 1:
-        async_read(get<1>(socket_), buffer_, res_, wrap);
-        break;
+	switch (socket_.index()) {
+	case 1:
+		async_read(get<1>(socket_), buffer_, res_, wrap);
+		break;
 #if defined(IRCCD_HAVE_SSL)
-    case 2:
-        async_read(get<2>(socket_), buffer_, res_, wrap);
-        break;
+	case 2:
+		async_read(get<2>(socket_), buffer_, res_, wrap);
+		break;
 #endif
-    default:
-        break;
-    }
+	default:
+		break;
+	}
 }
 
 void requester::handle_write(const error_code& code)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (!code)
-        read();
+	if (!code)
+		read();
 }
 
 void requester::write()
 {
-    req_.version(11);
-    req_.method(verb::get);
-    req_.target(uri_.path);
-    req_.set(field::host, uri_.host);
-    req_.set(field::user_agent, BOOST_BEAST_VERSION_STRING);
+	req_.version(11);
+	req_.method(verb::get);
+	req_.target(uri_.path);
+	req_.set(field::host, uri_.host);
+	req_.set(field::user_agent, BOOST_BEAST_VERSION_STRING);
 
-    const auto self = shared_from_this();
-    const auto wrap = [self] (auto code, auto) {
-        self->handle_write(code);
-    };
+	const auto self = shared_from_this();
+	const auto wrap = [self] (auto code, auto) {
+		self->handle_write(code);
+	};
 
-    timer();
+	timer();
 
-    switch (socket_.index()) {
-    case 1:
-        async_write(get<1>(socket_), req_, wrap);
-        break;
+	switch (socket_.index()) {
+	case 1:
+		async_write(get<1>(socket_), req_, wrap);
+		break;
 #if defined(IRCCD_HAVE_SSL)
-    case 2:
-        async_write(get<2>(socket_), req_, wrap);
-        break;
+	case 2:
+		async_write(get<2>(socket_), req_, wrap);
+		break;
 #endif
-    default:
-        break;
-    }
+	default:
+		break;
+	}
 }
 
 void requester::handle_handshake(const error_code& code)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (!code)
-        write();
+	if (!code)
+		write();
 }
 
 void requester::handshake()
 {
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    timer();
+	timer();
 
-    switch (socket_.index()) {
-    case 1:
-        handle_handshake(error_code());
-        break;
+	switch (socket_.index()) {
+	case 1:
+		handle_handshake(error_code());
+		break;
 #if defined(IRCCD_HAVE_SSL)
-    case 2:
-        get<2>(socket_).async_handshake(stream_base::client, [self] (auto code) {
-            self->handle_handshake(code);
-        });
-        break;
+	case 2:
+		get<2>(socket_).async_handshake(stream_base::client, [self] (auto code) {
+			self->handle_handshake(code);
+		});
+		break;
 #endif
-    default:
-        break;
-    }
+	default:
+		break;
+	}
 }
 
 void requester::handle_connect(const error_code& code)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (!code)
-        handshake();
+	if (!code)
+		handshake();
 }
 
 void requester::connect(const tcp::resolver::results_type& eps)
 {
-    const auto self = shared_from_this();
-    const auto wrap = [self] (auto code, auto) {
-        self->handle_connect(code);
-    };
+	const auto self = shared_from_this();
+	const auto wrap = [self] (auto code, auto) {
+		self->handle_connect(code);
+	};
 
-    timer();
+	timer();
 
-    switch (socket_.index()) {
-    case 1:
-        async_connect(get<1>(socket_), eps, wrap);
-        break;
+	switch (socket_.index()) {
+	case 1:
+		async_connect(get<1>(socket_), eps, wrap);
+		break;
 #if defined(IRCCD_HAVE_SSL)
-    case 2:
-        async_connect(get<2>(socket_).lowest_layer(), eps, wrap);
-        break;
+	case 2:
+		async_connect(get<2>(socket_).lowest_layer(), eps, wrap);
+		break;
 #endif
-    default:
-        break;
-    }
+	default:
+		break;
+	}
 }
 
 void requester::handle_resolve(const error_code& code, const tcp::resolver::results_type& eps)
 {
-    timer_.cancel();
+	timer_.cancel();
 
-    if (!code)
-        connect(eps);
+	if (!code)
+		connect(eps);
 }
 
 void requester::resolve()
 {
-    auto self = shared_from_this();
+	auto self = shared_from_this();
 
-    timer();
-    resolver_.async_resolve(uri_.host, uri_.port, [self] (auto code, auto eps) {
-        self->handle_resolve(code, eps);
-    });
+	timer();
+	resolver_.async_resolve(uri_.host, uri_.port, [self] (auto code, auto eps) {
+		self->handle_resolve(code, eps);
+	});
 }
 
 void requester::handle_timer(const error_code& code)
 {
-    // Force close sockets to cancel all pending operations.
-    if (code && code != std::errc::operation_canceled)
-        socket_.emplace<monostate>();
+	// Force close sockets to cancel all pending operations.
+	if (code && code != std::errc::operation_canceled)
+		socket_.emplace<monostate>();
 }
 
 void requester::timer()
 {
-    const auto self = shared_from_this();
+	const auto self = shared_from_this();
 
-    timer_.expires_from_now(seconds(links_plugin::conf_timeout));
-    timer_.async_wait([self] (auto code) {
-        self->handle_timer(code);
-    });
+	timer_.expires_from_now(seconds(links_plugin::conf_timeout));
+	timer_.async_wait([self] (auto code) {
+		self->handle_timer(code);
+	});
 }
 
 void requester::start()
 {
-    if (uri_.scheme == "http")
-        socket_.emplace<tcp::socket>(resolver_.get_io_service());
+	if (uri_.scheme == "http")
+		socket_.emplace<tcp::socket>(resolver_.get_io_service());
 #if defined(IRCCD_HAVE_SSL)
-    else if (uri_.scheme == "https")
-        socket_.emplace<stream<tcp::socket>>(resolver_.get_io_service(), ctx_);
+	else if (uri_.scheme == "https")
+		socket_.emplace<stream<tcp::socket>>(resolver_.get_io_service(), ctx_);
 #endif
 
-    // Only do the resolve if scheme is correct.
-    if (socket_.index() != 0)
-        resolve();
+	// Only do the resolve if scheme is correct.
+	if (socket_.index() != 0)
+		resolve();
 }
 
 requester::requester(io_context& io,
@@ -289,24 +284,24 @@
                      string origin,
                      uri uri,
                      size_t level)
-    : level_(level)
-    , server_(move(server))
-    , channel_(move(channel))
-    , origin_(move(origin))
-    , uri_(move(uri))
-    , timer_(io)
-    , resolver_(io)
+	: level_(level)
+	, server_(move(server))
+	, channel_(move(channel))
+	, origin_(move(origin))
+	, uri_(move(uri))
+	, timer_(io)
+	, resolver_(io)
 {
 }
 
 void requester::run(io_context& io, shared_ptr<server> server, string origin, string channel, string link)
 {
-    auto uri = uri::parse(link);
+	auto uri = uri::parse(link);
 
-    if (!uri)
-        return;
+	if (!uri)
+		return;
 
-    shared_ptr<requester>(new requester(io, server, channel, origin, move(*uri), 0))->start();
+	shared_ptr<requester>(new requester(io, server, channel, origin, move(*uri), 0))->start();
 }
 
 } // !irccd
--- a/plugins/links/requester.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/requester.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -50,69 +50,69 @@
  */
 class requester : public std::enable_shared_from_this<requester> {
 private:
-    std::variant<
-        std::monostate,
-        boost::asio::ip::tcp::socket
+	std::variant<
+		std::monostate,
+		boost::asio::ip::tcp::socket
 #if defined(IRCCD_HAVE_SSL)
-        , boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
+		, boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
 #endif
-    > socket_;
+	> socket_;
 
-    std::size_t level_{0U};
-    std::shared_ptr<server> server_;
-    std::string channel_;
-    std::string origin_;
+	std::size_t level_{0U};
+	std::shared_ptr<server> server_;
+	std::string channel_;
+	std::string origin_;
 
-    uri uri_;
+	uri uri_;
 
 #if defined(IRCCD_HAVE_SSL)
-    boost::asio::ssl::context ctx_{boost::asio::ssl::context::sslv23};
+	boost::asio::ssl::context ctx_{boost::asio::ssl::context::sslv23};
 #endif
 
-    boost::beast::flat_buffer buffer_;
-    boost::beast::http::request<boost::beast::http::empty_body> req_;
-    boost::beast::http::response<boost::beast::http::string_body> res_;
-    boost::asio::deadline_timer timer_;
-    boost::asio::ip::tcp::resolver resolver_;
+	boost::beast::flat_buffer buffer_;
+	boost::beast::http::request<boost::beast::http::empty_body> req_;
+	boost::beast::http::response<boost::beast::http::string_body> res_;
+	boost::asio::deadline_timer timer_;
+	boost::asio::ip::tcp::resolver resolver_;
 
-    void notify(const std::string&);
-    void parse();
-    void handle_read(const std::error_code&);
-    void read();
-    void handle_write(const std::error_code&);
-    void write();
-    void handle_handshake(const std::error_code&);
-    void handshake();
-    void handle_connect(const std::error_code&);
-    void connect(const boost::asio::ip::tcp::resolver::results_type&);
-    void handle_resolve(const std::error_code&, const boost::asio::ip::tcp::resolver::results_type&);
-    void resolve();
-    void handle_timer(const std::error_code&);
-    void timer();
-    void start();
+	void notify(const std::string&);
+	void parse();
+	void handle_read(const std::error_code&);
+	void read();
+	void handle_write(const std::error_code&);
+	void write();
+	void handle_handshake(const std::error_code&);
+	void handshake();
+	void handle_connect(const std::error_code&);
+	void connect(const boost::asio::ip::tcp::resolver::results_type&);
+	void handle_resolve(const std::error_code&, const boost::asio::ip::tcp::resolver::results_type&);
+	void resolve();
+	void handle_timer(const std::error_code&);
+	void timer();
+	void start();
 
-    requester(boost::asio::io_context&,
-              std::shared_ptr<server>,
-              std::string,
-              std::string,
-              uri,
-              std::size_t);
+	requester(boost::asio::io_context&,
+	          std::shared_ptr<server>,
+	          std::string,
+	          std::string,
+	          uri,
+	          std::size_t);
 
 public:
-    /**
-     * Start seeking for a title in the link
-     *
-     * \param ctx the IO context
-     * \param sv the server
-     * \param origin the originator
-     * \param channel the channel
-     * \param message the message text
-     */
-    static void run(boost::asio::io_context& ctx,
-                    std::shared_ptr<server> sv,
-                    std::string origin,
-                    std::string channel,
-                    std::string message);
+	/**
+	 * Start seeking for a title in the link
+	 *
+	 * \param ctx the IO context
+	 * \param sv the server
+	 * \param origin the originator
+	 * \param channel the channel
+	 * \param message the message text
+	 */
+	static void run(boost::asio::io_context& ctx,
+	                std::shared_ptr<server> sv,
+	                std::string origin,
+	                std::string channel,
+	                std::string message);
 };
 
 } // !irccd
--- a/plugins/links/scope_exit.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/scope_exit.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,14 +27,14 @@
 namespace irccd {
 
 scope_exit::scope_exit(function<void ()> func) noexcept
-    : func_(move(func))
+	: func_(move(func))
 {
-    assert(func_);
+	assert(func_);
 }
 
 scope_exit::~scope_exit() noexcept
 {
-    func_();
+	func_();
 }
 
 } // !irccd
--- a/plugins/links/scope_exit.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/scope_exit.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,21 +33,21 @@
  */
 class scope_exit {
 private:
-    std::function<void ()> func_;
+	std::function<void ()> func_;
 
 public:
-    /**
-     * Constructor.
-     *
-     * \pre func != nullptr
-     * \param func the function to call
-     */
-    scope_exit(std::function<void ()> func) noexcept;
+	/**
+	 * Constructor.
+	 *
+	 * \pre func != nullptr
+	 * \param func the function to call
+	 */
+	scope_exit(std::function<void ()> func) noexcept;
 
-    /**
-     * Execute the handler.
-     */
-    ~scope_exit() noexcept;
+	/**
+	 * Execute the handler.
+	 */
+	~scope_exit() noexcept;
 };
 
 } // !irccd
--- a/plugins/links/uri.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/uri.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,53 +34,53 @@
 
 auto uri::parse(const string& link) noexcept -> optional<uri>
 {
-    /*
-     * The message may contain additional text, example:
-     *
-     * markand: http://example.org check this site
-     */
-    regex regex("^(https?:\\/\\/[^\\s]+).*$");
-    smatch match;
+	/*
+	 * The message may contain additional text, example:
+	 *
+	 * markand: http://example.org check this site
+	 */
+	regex regex("^(https?:\\/\\/[^\\s]+).*$");
+	smatch match;
 
-    if (!regex_match(link, match, regex))
-        return nullopt;
+	if (!regex_match(link, match, regex))
+		return nullopt;
 
-    UriParserStateA state;
-    UriUriA hnd;
-    uri ret;
-    scope_exit exit([&hnd] { uriFreeUriMembersA(&hnd); });
+	UriParserStateA state;
+	UriUriA hnd;
+	uri ret;
+	scope_exit exit([&hnd] { uriFreeUriMembersA(&hnd); });
 
-    state.uri = &hnd;
+	state.uri = &hnd;
 
-    if (uriParseUriA(&state, match[1].str().c_str()) != URI_SUCCESS)
-        return nullopt;
+	if (uriParseUriA(&state, match[1].str().c_str()) != URI_SUCCESS)
+		return nullopt;
 
-    if (hnd.scheme.first)
-        ret.scheme = string(hnd.scheme.first, hnd.scheme.afterLast - hnd.scheme.first);
+	if (hnd.scheme.first)
+		ret.scheme = string(hnd.scheme.first, hnd.scheme.afterLast - hnd.scheme.first);
 
-    // We're only interested in http and https.
-    if (ret.scheme != "http" && ret.scheme != "https")
-        return nullopt;
+	// We're only interested in http and https.
+	if (ret.scheme != "http" && ret.scheme != "https")
+		return nullopt;
 
-    // Correct port if not specified.
-    if (ret.port.empty())
-        ret.port = ret.scheme == "http" ? "80" : "443";
+	// Correct port if not specified.
+	if (ret.port.empty())
+		ret.port = ret.scheme == "http" ? "80" : "443";
 
-    if (hnd.hostText.first)
-        ret.host = string(hnd.hostText.first, hnd.hostText.afterLast - hnd.hostText.first);
-    if (hnd.portText.first)
-        ret.port = string(hnd.portText.first, hnd.portText.afterLast - hnd.portText.first);
+	if (hnd.hostText.first)
+		ret.host = string(hnd.hostText.first, hnd.hostText.afterLast - hnd.hostText.first);
+	if (hnd.portText.first)
+		ret.port = string(hnd.portText.first, hnd.portText.afterLast - hnd.portText.first);
 
-    for (auto p = hnd.pathHead; p != nullptr; p = p->next) {
-        ret.path += "/";
-        ret.path += string(p->text.first, p->text.afterLast - p->text.first);
-    }
+	for (auto p = hnd.pathHead; p != nullptr; p = p->next) {
+		ret.path += "/";
+		ret.path += string(p->text.first, p->text.afterLast - p->text.first);
+	}
 
-    // Correct path if empty.
-    if (ret.path.empty())
-        ret.path = "/";
+	// Correct path if empty.
+	if (ret.path.empty())
+		ret.path = "/";
 
-    return ret;
+	return ret;
 }
 
 } // !irccd
--- a/plugins/links/uri.hpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/links/uri.hpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,18 +33,18 @@
  * \file uri.hpp
  */
 struct uri {
-    std::string scheme;     //!< scheme (e.g. http)
-    std::string host;       //!< host (e.g. example.org)
-    std::string port;       //!< port (e.g. 8080)
-    std::string path;       //!< path (e.g. /foo/bar)
+	std::string scheme;     //!< scheme (e.g. http)
+	std::string host;       //!< host (e.g. example.org)
+	std::string port;       //!< port (e.g. 8080)
+	std::string path;       //!< path (e.g. /foo/bar)
 
-    /**
-     * Try to parse the uri from the link text.
-     *
-     * \param link the link
-     * \return the uri or nullopt if not parseable
-     */
-    static auto parse(const std::string& link) noexcept -> std::optional<uri>;
+	/**
+	 * Try to parse the uri from the link text.
+	 *
+	 * \param link the link
+	 * \return the uri or nullopt if not parseable
+	 */
+	static auto parse(const std::string& link) noexcept -> std::optional<uri>;
 };
 
 } // !irccd
--- a/plugins/logger/logger.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/logger/logger.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,198 +18,164 @@
 
 // Plugin information.
 info = {
-    name: "logger",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "A plugin to log everything",
-    version: "@IRCCD_VERSION@"
+	name: "logger",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "A plugin to log everything",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
-var Directory   = Irccd.Directory;
-var File        = Irccd.File;
-var Logger      = Irccd.Logger;
-var Plugin      = Irccd.Plugin;
-var Util        = Irccd.Util;
+var Directory = Irccd.Directory;
+var File = Irccd.File;
+var Logger = Irccd.Logger;
+var Plugin = Irccd.Plugin;
+var Util = Irccd.Util;
 
 /**
  * All available formats.
  */
 Plugin.format = {
-    "join":     "%H:%M:%S >> #{nickname} joined #{channel}",
-    "kick":     "%H:%M:%S :: #{target} has been kicked by #{nickname} [reason: #{reason}]",
-    "me":       "%H:%M:%S * #{nickname} #{message}",
-    "message":  "%H:%M:%S #{nickname}: #{message}",
-    "mode":     "%H:%M:%S :: #{nickname} set mode #{mode} to #{arg}",
-    "notice":   "%H:%M:%S [notice] #{channel} (#{nickname}) #{message}",
-    "part":     "%H:%M:%S << #{nickname} left #{channel} [#{reason}]",
-    "query":    "%H:%M:%S #{nickname}: #{message}",
-    "topic":    "%H:%M:%S :: #{nickname} changed the topic of #{channel} to: #{topic}"
+	"join":         "%H:%M:%S >> #{nickname} joined #{channel}",
+	"kick":         "%H:%M:%S :: #{target} has been kicked by #{nickname} [reason: #{reason}]",
+	"me":           "%H:%M:%S * #{nickname} #{message}",
+	"message":      "%H:%M:%S #{nickname}: #{message}",
+	"mode":         "%H:%M:%S :: #{nickname} set mode #{mode} to #{arg}",
+	"notice":       "%H:%M:%S [notice] #{channel} (#{nickname}) #{message}",
+	"part":         "%H:%M:%S << #{nickname} left #{channel} [#{reason}]",
+	"query":        "%H:%M:%S #{nickname}: #{message}",
+	"topic":        "%H:%M:%S :: #{nickname} changed the topic of #{channel} to: #{topic}"
 };
 
-/**
- * Load all formats.
- */
-function loadFormats()
-{
-    // --- DEPRECATED -------------------------------------------
-    //
-    // This code will be removed.
-    //
-    // Since:    2.1.0
-    // Until:    3.0.0
-    // Reason:    new [format] section replaces it.
-    //
-    // ----------------------------------------------------------
-    for (var key in Plugin.format) {
-        var optname = "format-" + key;
-
-        if (typeof (Plugin.config[optname]) !== "string")
-            continue;
-
-        if (Plugin.config[optname].length === 0)
-            Logger.warning("skipping empty '" + optname + "' format");
-        else
-            Plugin.format[key] = Plugin.config[optname];
-    }
-}
-
 function keywords(server, channel, origin, extra)
 {
-    var kw = {
-        "server": server.toString(),
-        "channel": channel,
-        "origin": origin,
-        "nickname": Util.splituser(origin)
-    };
+	var kw = {
+		"server": server.toString(),
+		"channel": channel,
+		"origin": origin,
+		"nickname": Util.splituser(origin)
+	};
 
-    for (var key in extra)
-        kw[key] = extra[key];
+	for (var key in extra)
+		kw[key] = extra[key];
 
-    return kw;
+	return kw;
 }
 
 function write(fmt, args)
 {
-    var path = Util.format(Plugin.config["path"], args);
-    var directory = File.dirname(path);
+	var path = Util.format(Plugin.config["path"], args);
+	var directory = File.dirname(path);
 
-    // Try to create the directory.
-    if (!File.exists(directory)) {
-        Logger.debug("creating directory: " + directory);
-        Directory.mkdir(directory);
-    }
+	// Try to create the directory.
+	if (!File.exists(directory)) {
+		Logger.debug("creating directory: " + directory);
+		Directory.mkdir(directory);
+	}
 
-    Logger.debug("opening: " + path);
+	Logger.debug("opening: " + path);
 
-    var str = Util.format(Plugin.format[fmt], args);
-    var file = new File(path, "a");
+	var str = Util.format(Plugin.format[fmt], args);
+	var file = new File(path, "a");
 
-    file.write(str + "\n");
+	file.write(str + "\n");
 }
 
 function onLoad()
 {
-    if (Plugin.config["path"] === undefined)
-        throw new Error("Missing 'path' option");
-
-    loadFormats();
-}
-
-function onReload()
-{
-    loadFormats();
+	if (Plugin.config["path"] === undefined)
+		throw new Error("Missing 'path' option");
 }
 
 function onInvite(server, origin, channel)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("invite", keywords(server, channel, origin));
+	write("invite", keywords(server, channel, origin));
 }
 
 function onJoin(server, origin, channel)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("join", keywords(server, channel, origin));
+	write("join", keywords(server, channel, origin));
 }
 
 function onKick(server, origin, channel, target, reason)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("kick", keywords(server, channel, origin, {
-        "target":   target,
-        "reason":   reason
-    }));
+	write("kick", keywords(server, channel, origin, {
+		"target":   target,
+		"reason":   reason
+	}));
 }
 
 function onMe(server, origin, channel, message)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("me", keywords(server, channel, origin, {
-        "message":  message,
-    }));
+	write("me", keywords(server, channel, origin, {
+		"message":  message,
+	}));
 }
 
 function onMessage(server, origin, channel, message)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("message", keywords(server, channel, origin, {
-        "message":  message,
-    }));
+	write("message", keywords(server, channel, origin, {
+		"message":  message,
+	}));
 }
 
 function onMode(server, origin, channel, mode, limit, user, mask)
 {
-    origin = origin.toLowerCase();
+	origin = origin.toLowerCase();
 
-    write("mode", keywords(server, channel, origin, {
-        "mode":     mode,
-        "limit":    limit,
-        "user":     user,
-        "mask":     mask
-    }));
+	write("mode", keywords(server, channel, origin, {
+		"mode":	 mode,
+		"limit":	limit,
+		"user":	 user,
+		"mask":	 mask
+	}));
 }
 
 function onNick(server, origin, nickname)
 {
-    // TODO: write for all servers/channels a log entry
+	// TODO: write for all servers/channels a log entry
 }
 
 function onNotice(server, origin, channel, notice)
 {
-    origin = origin.toLowerCase();
+	origin = origin.toLowerCase();
 
-    write("notice", keywords(server, channel, origin, {
-        "message":  notice,
-    }));
+	write("notice", keywords(server, channel, origin, {
+		"message":  notice,
+	}));
 }
 
 function onPart(server, origin, channel, reason)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("part", keywords(server, channel, origin, {
-        "reason":   reason,
-    }));
+	write("part", keywords(server, channel, origin, {
+		"reason":   reason,
+	}));
 }
 
 function onTopic(server, origin, channel, topic)
 {
-    origin = origin.toLowerCase();
-    channel = channel.toLowerCase();
+	origin = origin.toLowerCase();
+	channel = channel.toLowerCase();
 
-    write("topic", keywords(server, channel, origin, {
-        "topic":    topic
-    }));
+	write("topic", keywords(server, channel, origin, {
+		"topic":	topic
+	}));
 }
--- a/plugins/plugin/plugin.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/plugin/plugin.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "plugin",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "A plugin to inspect plugins",
-    version: "@IRCCD_VERSION@"
+	name: "plugin",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "A plugin to inspect plugins",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -30,158 +30,124 @@
 var Plugin = Irccd.Plugin;
 
 Plugin.format = {
-    "usage":        "#{nickname}, usage: #{command} list | info plugin",
-    "info":         "#{nickname}, #{name}: #{summary}, version #{version} by #{author} (#{license} license).",
-    "not-found":    "#{nickname}, plugin #{name} does not exist.",
-    "too-long":     "#{nickname}, plugin list too long, ask in query for more details."
+	"usage":        "#{nickname}, usage: #{command} list | info plugin",
+	"info":         "#{nickname}, #{name}: #{summary}, version #{version} by #{author} (#{license} license).",
+	"not-found":    "#{nickname}, plugin #{name} does not exist.",
+	"too-long":     "#{nickname}, plugin list too long, ask in query for more details."
 }
 
 Plugin.config = {
-    "max-list-lines":   3,
-    "max-list-columns": 80
+	"max-list-lines":   3,
+	"max-list-columns": 80
 }
 
 var commands = {
-    loadFormats: function ()
-    {
-        // --- DEPRECATED -----------------------------------
-        //
-        // This code will be removed.
-        //
-        // Since:    2.1.0
-        // Until:    3.0.0
-        // Reason:    new [format] section replaces it.
-        //
-        // --------------------------------------------------
-        for (var key in Plugin.format) {
-            var optname = "format-" + key;
+	keywords: function (server, channel, origin)
+	{
+		return {
+			channel: channel,
+			command: server.info().commandChar + Plugin.info().name,
+			nickname: Util.splituser(origin),
+			origin: origin,
+			plugin: Plugin.info().name,
+			server: server.toString()
+		}
+	},
 
-            if (typeof (Plugin.config[optname]) !== "string")
-                continue;
-
-            if (Plugin.config[optname].length === 0)
-                Logger.warning("skipping empty '" + optname + "' format");
-            else
-                Plugin.format[key] = Plugin.config[optname];
-        }
-    },
+	list: function (server, origin, target, query)
+	{
+		var kw = commands.keywords(server, target, origin);
+		var plugins = Plugin.list();
+		var lines = [ "" ];
+		var maxl = parseInt(Plugin.config["max-list-lines"]);
+		var maxc = parseInt(Plugin.config["max-list-columns"]);
 
-    keywords: function (server, channel, origin)
-    {
-        return {
-            channel: channel,
-            command: server.info().commandChar + Plugin.info().name,
-            nickname: Util.splituser(origin),
-            origin: origin,
-            plugin: Plugin.info().name,
-            server: server.toString()
-        }
-    },
+		if (isNaN(maxc)) {
+			maxc = 80;
+		}
+		if (isNaN(maxl)) {
+			maxl = 3;
+		}
+
+		for (var p = 0; p < plugins.length; ++p) {
+			var l = lines.length - 1;
 
-    list: function (server, origin, target, query)
-    {
-        var kw = commands.keywords(server, target, origin);
-        var plugins = Plugin.list();
-        var lines = [ "" ];
-        var maxl = parseInt(Plugin.config["max-list-lines"]);
-        var maxc = parseInt(Plugin.config["max-list-columns"]);
+			if (plugins[p].length + 1 + lines[l].length > maxc) {
+				lines.push("");
+				l++;
+			}
+
+			lines[l] += plugins[p] + " ";
+		}
 
-        if (isNaN(maxc)) {
-            maxc = 80;
-        }
-        if (isNaN(maxl)) {
-            maxl = 3;
-        }
-
-        for (var p = 0; p < plugins.length; ++p) {
-            var l = lines.length - 1;
-
-            if (plugins[p].length + 1 + lines[l].length > maxc) {
-                lines.push("");
-                l++;
-            }
+		if (!query && maxl > 0 && lines.length > maxl) {
+			server.message(target, Util.format(Plugin.format["too-long"], kw));
+		} else {
+			for (var i = 0; i < lines.length; ++i) {
+				server.message(target, lines[i]);
+			}
+		}
+	},
 
-            lines[l] += plugins[p] + " ";
-        }
+	info: function (server, origin, target, name)
+	{
+		var kw = commands.keywords(server, target, origin);
+		var info = Plugin.info(name);
+		var str;
 
-        if (!query && maxl > 0 && lines.length > maxl) {
-            server.message(target, Util.format(Plugin.format["too-long"], kw));
-        } else {
-            for (var i = 0; i < lines.length; ++i) {
-                server.message(target, lines[i]);
-            }
-        }
-    },
+		kw.name = name;
 
-    info: function (server, origin, target, name)
-    {
-        var kw = commands.keywords(server, target, origin);
-        var info = Plugin.info(name);
-        var str;
-
-        kw.name = name;
+		if (info) {
+			kw.author = info.author;
+			kw.license = info.license;
+			kw.summary = info.summary;
+			kw.version = info.version;
 
-        if (info) {
-            kw.author = info.author;
-            kw.license = info.license;
-            kw.summary = info.summary;
-            kw.version = info.version;
+			str = Util.format(Plugin.format["info"], kw);
+		} else
+			str = Util.format(Plugin.format["not-found"], kw);
 
-            str = Util.format(Plugin.format["info"], kw);
-        } else
-            str = Util.format(Plugin.format["not-found"], kw);
+		server.message(target, str);
+	},
+
+	usage: function (server, origin, target)
+	{
+		server.message(target, Util.format(Plugin.format["usage"], commands.keywords(server, target, origin)));
+	},
 
-        server.message(target, str);
-    },
-
-    usage: function (server, origin, target)
-    {
-        server.message(target, Util.format(Plugin.format["usage"], commands.keywords(server, target, origin)));
-    },
+	execute: function (server, origin, target, message, query)
+	{
+		if (message.length === 0) {
+			commands.usage(server, origin, target);
+			return;
+		}
 
-    execute: function (server, origin, target, message, query)
-    {
-        if (message.length === 0) {
-            commands.usage(server, origin, target);
-            return;
-        }
-
-        var list = message.split(" ");
+		var list = message.split(" ");
 
-        switch (list[0]) {
-        case "info":
-            if (list.length === 2)
-                commands.info(server, origin, target, list[1]);
-            else
-                commands.usage(server, origin, target);
+		switch (list[0]) {
+		case "info":
+			if (list.length === 2)
+				commands.info(server, origin, target, list[1]);
+			else
+				commands.usage(server, origin, target);
 
-            break;
-        case "list":
-            commands.list(server, origin, target, query);
-            break;
-        default:
-            commands.usage(server, origin, target);
-            break;
-        }
-    }
+			break;
+		case "list":
+			commands.list(server, origin, target, query);
+			break;
+		default:
+			commands.usage(server, origin, target);
+			break;
+		}
+	}
 };
 
 function onCommand(server, origin, channel, message)
 {
-    commands.execute(server, origin, channel, message, false)
-}
-
-function onLoad()
-{
-    commands.loadFormats();
+	commands.execute(server, origin, channel, message, false)
 }
 
 function onQueryCommand(server, origin, message)
 {
-    commands.execute(server, origin, origin, message, true)
+	commands.execute(server, origin, origin, message, true)
 }
-
-function onReload()
-{
-    commands.loadFormats();
-}
--- a/plugins/roulette/roulette.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/roulette/roulette.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "roulette",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "A russian roulette for IRC",
-    version: "@IRCCD_VERSION@"
+	name: "roulette",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "A russian roulette for IRC",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -35,16 +35,16 @@
  * Formats for writing.
  */
 Plugin.format = {
-    "lucky":    "#{nickname}, you're lucky this time",
-    "shot":     "HEADSHOT"
+	"lucky":        "#{nickname}, you're lucky this time",
+	"shot":         "HEADSHOT"
 };
 
 function Gun(server, channel)
 {
-    this.server = server;
-    this.channel = channel;
-    this.index = 0;
-    this.bullet = Math.floor(Math.random() * 6);
+	this.server = server;
+	this.channel = channel;
+	this.index = 0;
+	this.bullet = Math.floor(Math.random() * 6);
 }
 
 /**
@@ -61,7 +61,7 @@
  */
 Gun.find = function (server, channel)
 {
-    return Gun.map[server.toString() + '@' + channel];
+	return Gun.map[server.toString() + '@' + channel];
 }
 
 /**
@@ -73,7 +73,7 @@
  */
 Gun.create = function (server, channel)
 {
-    return Gun.map[server.toString() + "@" + channel] = new Gun(server, channel);
+	return Gun.map[server.toString() + "@" + channel] = new Gun(server, channel);
 }
 
 /**
@@ -83,71 +83,37 @@
  */
 Gun.remove = function (game)
 {
-    delete Gun.map[game.server + "@" + game.channel];
-}
-
-/**
- * Load all formats.
- */
-Gun.loadFormats = function ()
-{
-    // --- DEPRECATED ------------------------------------------
-    //
-    // This code will be removed.
-    //
-    // Since:    2.1.0
-    // Until:    3.0.0
-    // Reason:    new [format] section replaces it.
-    //
-    // ----------------------------------------------------------
-    for (var key in Plugin.format) {
-        var optname = "format-" + key;
-
-        if (typeof (Plugin.config[optname]) !== "string")
-            continue;
-
-        if (Plugin.config[optname].length === 0)
-            Logger.warning("skipping empty '" + optname + "' format");
-        else
-            Plugin.format[key] = Plugin.config[optname];
-    }
+	delete Gun.map[game.server + "@" + game.channel];
 }
 
 Gun.prototype.shot = function ()
 {
-    return this.index++ === this.bullet;
+	return this.index++ === this.bullet;
 }
 
-function onLoad()
-{
-    Gun.loadFormats();
-}
-
-onReload = onLoad;
-
 function onCommand(server, origin, channel)
 {
-    channel = channel.toLowerCase();
+	channel = channel.toLowerCase();
 
-    var kw = {
-        channel: channel,
-        command: server.info().commandChar + Plugin.info().name,
-        nickname: Util.splituser(origin),
-        origin: origin,
-        server: server.toString(),
-        plugin: Plugin.info().name
-    };
+	var kw = {
+		channel: channel,
+		command: server.info().commandChar + Plugin.info().name,
+		nickname: Util.splituser(origin),
+		origin: origin,
+		server: server.toString(),
+		plugin: Plugin.info().name
+	};
 
-    var game = Gun.find(server, channel);
+	var game = Gun.find(server, channel);
 
-    if (!game)
-        game = Gun.create(server, channel);
+	if (!game)
+		game = Gun.create(server, channel);
 
-    if (game.shot()) {
-        server.kick(Util.splituser(origin), channel, Util.format(Plugin.format["shot"], kw));
-        Gun.remove(game);
-    } else {
-        kw.count = (6 - game.index).toString();
-        server.message(channel, Util.format(Plugin.format["lucky"], kw));
-    }
+	if (game.shot()) {
+		server.kick(Util.splituser(origin), channel, Util.format(Plugin.format["shot"], kw));
+		Gun.remove(game);
+	} else {
+		kw.count = (6 - game.index).toString();
+		server.message(channel, Util.format(Plugin.format["lucky"], kw));
+	}
 }
--- a/plugins/tictactoe/tictactoe.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/plugins/tictactoe/tictactoe.js	Fri Oct 26 13:01:00 2018 +0200
@@ -18,11 +18,11 @@
 
 // Plugin information.
 info = {
-    name: "tictactoe",
-    author: "David Demelier <markand@malikania.fr>",
-    license: "ISC",
-    summary: "A tictactoe game for IRC",
-    version: "@IRCCD_VERSION@"
+	name: "tictactoe",
+	author: "David Demelier <markand@malikania.fr>",
+	license: "ISC",
+	summary: "A tictactoe game for IRC",
+	version: "@IRCCD_VERSION@"
 };
 
 // Modules.
@@ -31,12 +31,12 @@
 
 // Formats.
 Plugin.format = {
-    "draw":     "nobody won",
-    "invalid":  "#{nickname}, please select a valid opponent",
-    "running":  "#{nickname}, the game is already running",
-    "turn":     "#{nickname}, it's your turn",
-    "used":     "#{nickname}, this square is already used",
-    "win":      "#{nickname}, congratulations, you won!"
+	"draw":         "nobody won",
+	"invalid":      "#{nickname}, please select a valid opponent",
+	"running":      "#{nickname}, the game is already running",
+	"turn":         "#{nickname}, it's your turn",
+	"used":         "#{nickname}, this square is already used",
+	"win":          "#{nickname}, congratulations, you won!"
 };
 
 /**
@@ -51,17 +51,17 @@
  */
 function Game(server, channel, origin, target)
 {
-    this.server = server;
-    this.origin = origin;
-    this.target = target;
-    this.channel = channel;
-    this.players = [ Util.splituser(origin), target ];
-    this.player = Math.floor(Math.random() * 2);
-    this.grid = [
-        [ '.', '.', '.' ],
-        [ '.', '.', '.' ],
-        [ '.', '.', '.' ]
-    ];
+	this.server = server;
+	this.origin = origin;
+	this.target = target;
+	this.channel = channel;
+	this.players = [ Util.splituser(origin), target ];
+	this.player = Math.floor(Math.random() * 2);
+	this.grid = [
+		[ '.', '.', '.' ],
+		[ '.', '.', '.' ],
+		[ '.', '.', '.' ]
+	];
 }
 
 // Pending games requests checking for names listing.
@@ -79,7 +79,7 @@
  */
 Game.id = function (server, channel)
 {
-    return channel + "@" + server.toString();
+	return channel + "@" + server.toString();
 }
 
 /**
@@ -91,7 +91,7 @@
  */
 Game.find = function (server, channel)
 {
-    return Game.map[Game.id(server, channel)];
+	return Game.map[Game.id(server, channel)];
 }
 
 /**
@@ -104,12 +104,12 @@
  */
 Game.postpone = function (server, channel, origin, target)
 {
-    /*
-     * Get list of users on the channel to avoid playing against a non existing
-     * target.
-     */
-    Game.requests[Game.id(server, channel)] = new Game(server, channel, origin, target);
-    server.names(channel);
+	/*
+	 * Get list of users on the channel to avoid playing against a non existing
+	 * target.
+	 */
+	Game.requests[Game.id(server, channel)] = new Game(server, channel, origin, target);
+	server.names(channel);
 }
 
 /**
@@ -122,19 +122,19 @@
  */
 Game.keywords = function (server, channel, origin)
 {
-    var kw = {
-        channel: channel,
-        command: server.info().commandChar + Plugin.info().name,
-        plugin: Plugin.info().name,
-        server: server.info().name
-    };
+	var kw = {
+		channel: channel,
+		command: server.info().commandChar + Plugin.info().name,
+		plugin: Plugin.info().name,
+		server: server.info().name
+	};
 
-    if (origin) {
-        kw.origin = origin;
-        kw.nickname = Util.splituser(origin);
-    }
+	if (origin) {
+		kw.origin = origin;
+		kw.nickname = Util.splituser(origin);
+	}
 
-    return kw;
+	return kw;
 }
 
 /**
@@ -146,9 +146,9 @@
  */
 Game.exists = function (server, channel)
 {
-    var id = Game.id(server, channel);
+	var id = Game.id(server, channel);
 
-    return Game.requests[id] || Game.map[id];
+	return Game.requests[id] || Game.map[id];
 }
 
 /**
@@ -159,7 +159,7 @@
  */
 Game.remove = function (server, channel)
 {
-    delete Game.map[Game.id(server, channel)];
+	delete Game.map[Game.id(server, channel)];
 }
 
 /**
@@ -171,11 +171,11 @@
  */
 Game.clear = function (server, user, channel)
 {
-    var nickname = Util.splituser(user);
-    var game = Game.find(server, channel);
+	var nickname = Util.splituser(user);
+	var game = Game.find(server, channel);
 
-    if (game && (game.players[0] === nickname || game.players[1] === nickname))
-        Game.remove(server, channel);
+	if (game && (game.players[0] === nickname || game.players[1] === nickname))
+		Game.remove(server, channel);
 }
 
 /**
@@ -183,22 +183,22 @@
  */
 Game.prototype.show = function ()
 {
-    var kw = Game.keywords(this.server, this.channel);
+	var kw = Game.keywords(this.server, this.channel);
 
-    // nickname is the current player.
-    kw.nickname = this.players[this.player];
+	// nickname is the current player.
+	kw.nickname = this.players[this.player];
 
-    this.server.message(this.channel, "  a b c");
-    this.server.message(this.channel, "1 " + this.grid[0].join(" "));
-    this.server.message(this.channel, "2 " + this.grid[1].join(" "));
-    this.server.message(this.channel, "3 " + this.grid[2].join(" "));
+	this.server.message(this.channel, "  a b c");
+	this.server.message(this.channel, "1 " + this.grid[0].join(" "));
+	this.server.message(this.channel, "2 " + this.grid[1].join(" "));
+	this.server.message(this.channel, "3 " + this.grid[2].join(" "));
 
-    if (this.hasWinner())
-        this.server.message(this.channel, Util.format(Plugin.format.win, kw));
-    else if (this.hasDraw())
-        this.server.message(this.channel, Util.format(Plugin.format.draw, kw));
-    else
-        this.server.message(this.channel, Util.format(Plugin.format.turn, kw));
+	if (this.hasWinner())
+		this.server.message(this.channel, Util.format(Plugin.format.win, kw));
+	else if (this.hasDraw())
+		this.server.message(this.channel, Util.format(Plugin.format.draw, kw));
+	else
+		this.server.message(this.channel, Util.format(Plugin.format.turn, kw));
 }
 
 /**
@@ -209,7 +209,7 @@
  */
 Game.prototype.isTurn = function (nickname)
 {
-    return this.players[this.player] == nickname;
+	return this.players[this.player] == nickname;
 }
 
 /**
@@ -220,26 +220,26 @@
  */
 Game.prototype.place = function (column, row, origin)
 {
-    var columns = { a: 0, b: 1, c: 2 };
-    var rows = { 1: 0, 2: 1, 3: 2 };
+	var columns = { a: 0, b: 1, c: 2 };
+	var rows = { 1: 0, 2: 1, 3: 2 };
 
-    column = columns[column];
-    row = rows[row];
+	column = columns[column];
+	row = rows[row];
 
-    var kw = Game.keywords(this.server, this.channel, origin);
+	var kw = Game.keywords(this.server, this.channel, origin);
 
-    if (this.grid[row][column] !== '.') {
-        this.server.message(this.channel, Util.format(Plugin.format.used, kw));
-        return false;
-    }
+	if (this.grid[row][column] !== '.') {
+		this.server.message(this.channel, Util.format(Plugin.format.used, kw));
+		return false;
+	}
 
-    this.grid[row][column] = this.player === 0 ? 'x' : 'o';
+	this.grid[row][column] = this.player === 0 ? 'x' : 'o';
 
-    // Do not change if game is finished.
-    if (!this.hasWinner() && !this.hasDraw())
-        this.player = this.player === 0 ? 1 : 0;
+	// Do not change if game is finished.
+	if (!this.hasWinner() && !this.hasDraw())
+		this.player = this.player === 0 ? 1 : 0;
 
-    return true;
+	return true;
 }
 
 /**
@@ -249,29 +249,29 @@
  */
 Game.prototype.hasWinner = function ()
 {
-    var lines = [
-        [ [ 0, 0 ], [ 0, 1 ], [ 0, 2 ] ],
-        [ [ 1, 0 ], [ 1, 1 ], [ 1, 2 ] ],
-        [ [ 2, 0 ], [ 2, 1 ], [ 2, 2 ] ],
-        [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ],
-        [ [ 0, 1 ], [ 1, 1 ], [ 2, 1 ] ],
-        [ [ 0, 2 ], [ 1, 2 ], [ 2, 2 ] ],
-        [ [ 0, 0 ], [ 1, 1 ], [ 2, 2 ] ],
-        [ [ 0, 2 ], [ 1, 1 ], [ 2, 0 ] ]
-    ];
+	var lines = [
+		[ [ 0, 0 ], [ 0, 1 ], [ 0, 2 ] ],
+		[ [ 1, 0 ], [ 1, 1 ], [ 1, 2 ] ],
+		[ [ 2, 0 ], [ 2, 1 ], [ 2, 2 ] ],
+		[ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ] ],
+		[ [ 0, 1 ], [ 1, 1 ], [ 2, 1 ] ],
+		[ [ 0, 2 ], [ 1, 2 ], [ 2, 2 ] ],
+		[ [ 0, 0 ], [ 1, 1 ], [ 2, 2 ] ],
+		[ [ 0, 2 ], [ 1, 1 ], [ 2, 0 ] ]
+	];
 
-    for (var i = 0; i < lines.length; ++i) {
-        var p1 = lines[i][0];
-        var p2 = lines[i][1];
-        var p3 = lines[i][2];
+	for (var i = 0; i < lines.length; ++i) {
+		var p1 = lines[i][0];
+		var p2 = lines[i][1];
+		var p3 = lines[i][2];
 
-        var result = this.grid[p1[0]][p1[1]] === this.grid[p2[0]][p2[1]] &&
-                     this.grid[p2[0]][p2[1]] === this.grid[p3[0]][p3[1]] &&
-                     this.grid[p3[0]][p3[1]] !== '.';
+		var result = this.grid[p1[0]][p1[1]] === this.grid[p2[0]][p2[1]] &&
+		             this.grid[p2[0]][p2[1]] === this.grid[p3[0]][p3[1]] &&
+		             this.grid[p3[0]][p3[1]] !== '.';
 
-        if (result)
-            return true;
-    }
+		if (result)
+			return true;
+	}
 }
 
 /**
@@ -281,80 +281,80 @@
  */
 Game.prototype.hasDraw = function ()
 {
-    for (var r = 0; r < 3; ++r)
-        for (var c = 0; c < 3; ++c)
-            if (this.grid[r][c] === '.')
-                return false;
+	for (var r = 0; r < 3; ++r)
+		for (var c = 0; c < 3; ++c)
+			if (this.grid[r][c] === '.')
+				return false;
 
-    return true;
+	return true;
 }
 
 function onNames(server, channel, list)
 {
-    var id = Game.id(server, channel);
-    var game = Game.requests[id];
+	var id = Game.id(server, channel);
+	var game = Game.requests[id];
 
-    // Names can come from any other plugin/event.
-    if (!game)
-        return;
+	// Names can come from any other plugin/event.
+	if (!game)
+		return;
 
-    // Not a valid target? destroy the game.
-    if (list.indexOf(game.target) < 0)
-        server.message(channel, Util.format(Plugin.format.invalid,
-            Game.keywords(server, channel, game.origin)));
-    else {
-        Game.map[id] = game;
-        game.show();
-    }
+	// Not a valid target? destroy the game.
+	if (list.indexOf(game.target) < 0)
+		server.message(channel, Util.format(Plugin.format.invalid,
+			Game.keywords(server, channel, game.origin)));
+	else {
+		Game.map[id] = game;
+		game.show();
+	}
 
-    delete Game.requests[id];
+	delete Game.requests[id];
 }
 
 function onCommand(server, origin, channel, message)
 {
-    var target = message.trim();
-    var nickname = Util.splituser(origin);
+	var target = message.trim();
+	var nickname = Util.splituser(origin);
 
-    if (Game.exists(server, channel))
-        server.message(channel, Util.format(Plugin.format.running, Game.keywords(server, channel, origin)));
-    else if (target === "" || target === nickname || target === server.info().nickname)
-        server.message(channel, Util.format(Plugin.format.invalid, Game.keywords(server, channel, origin)));
-    else
-        Game.postpone(server, channel, origin, message);
+	if (Game.exists(server, channel))
+		server.message(channel, Util.format(Plugin.format.running, Game.keywords(server, channel, origin)));
+	else if (target === "" || target === nickname || target === server.info().nickname)
+		server.message(channel, Util.format(Plugin.format.invalid, Game.keywords(server, channel, origin)));
+	else
+		Game.postpone(server, channel, origin, message);
 }
 
 function onMessage(server, origin, channel, message)
 {
-    var nickname = Util.splituser(origin);
-    var game = Game.find(server, channel);
+	var nickname = Util.splituser(origin);
+	var game = Game.find(server, channel);
 
-    if (!game || !game.isTurn(nickname))
-        return;
+	if (!game || !game.isTurn(nickname))
+		return;
 
-    var match = /^([abc]) ?([123])$/.exec(message.trim());
+	var match = /^([abc]) ?([123])$/.exec(message.trim());
 
-    if (!match)
-        return;
+	if (!match)
+		return;
 
-    if (game.place(match[1], match[2], origin))
-        game.show();
-    if (game.hasWinner() || game.hasDraw())
-        Game.remove(server, channel);
+	if (game.place(match[1], match[2], origin))
+		game.show();
+	if (game.hasWinner() || game.hasDraw())
+		Game.remove(server, channel);
 }
 
 function onDisconnect(server)
 {
-    for (var key in Game.map)
-        if (key.endsWith(server.toString()))
-            delete Game.map[key];
+	for (var key in Game.map)
+		if (key.endsWith(server.toString()))
+			delete Game.map[key];
 }
 
 function onKick(server, origin, channel, target)
 {
-    Game.clear(server, target, channel);
+	Game.clear(server, target, channel);
 }
 
 function onPart(server, origin, channel)
 {
-    Game.clear(server, origin, channel);
+	Game.clear(server, origin, channel);
 }
--- a/systemd/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/systemd/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -19,15 +19,15 @@
 project(contrib)
 
 if (IRCCD_WITH_SYSTEMD)
-    set(PATH "${CMAKE_INSTALL_FULL_BINDIR}/irccd")
+	set(PATH "${CMAKE_INSTALL_FULL_BINDIR}/irccd")
 
-    configure_file(
-        ${CMAKE_CURRENT_SOURCE_DIR}/irccd.service
-        ${CMAKE_CURRENT_BINARY_DIR}/irccd.service
-    )
+	configure_file(
+		${CMAKE_CURRENT_SOURCE_DIR}/irccd.service
+		${CMAKE_CURRENT_BINARY_DIR}/irccd.service
+	)
 
-    install(
-        FILES ${CMAKE_CURRENT_BINARY_DIR}/irccd.service
-        DESTINATION "/usr/lib/systemd/system"
-    )
+	install(
+		FILES ${CMAKE_CURRENT_BINARY_DIR}/irccd.service
+		DESTINATION "/usr/lib/systemd/system"
+	)
 endif()
--- a/tests/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -20,8 +20,8 @@
 
 # for test-cli-* tests.
 configure_file(
-    ${tests_SOURCE_DIR}/data/irccdctl.conf
-    ${CMAKE_BINARY_DIR}/tmp/irccdctl.conf
+	${tests_SOURCE_DIR}/data/irccdctl.conf
+	${CMAKE_BINARY_DIR}/tmp/irccdctl.conf
 )
 
 add_subdirectory(src/libcommon)
@@ -29,6 +29,6 @@
 add_subdirectory(src/irccdctl)
 
 if (IRCCD_HAVE_JS)
-    add_subdirectory(src/plugins)
-    add_subdirectory(src/libirccd-js)
+	add_subdirectory(src/plugins)
+	add_subdirectory(src/libirccd-js)
 endif ()
--- a/tests/src/irccdctl/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,12 +17,12 @@
 #
 
 if (IRCCD_HAVE_JS)
-    add_subdirectory(cli-plugin-config)
-    add_subdirectory(cli-plugin-info)
-    add_subdirectory(cli-plugin-list)
-    add_subdirectory(cli-plugin-load)
-    add_subdirectory(cli-plugin-reload)
-    add_subdirectory(cli-plugin-unload)
+	add_subdirectory(cli-plugin-config)
+	add_subdirectory(cli-plugin-info)
+	add_subdirectory(cli-plugin-list)
+	add_subdirectory(cli-plugin-load)
+	add_subdirectory(cli-plugin-reload)
+	add_subdirectory(cli-plugin-unload)
 endif ()
 
 add_subdirectory(cli-rule-add)
--- a/tests/src/irccdctl/cli-plugin-config/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-config/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-config
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-config
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-config/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-config/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,85 +30,85 @@
 
 class configurable_plugin_cli_fixture : public cli_fixture {
 public:
-    configurable_plugin_cli_fixture()
-    {
-        auto conf1 = std::make_unique<mock_plugin>("conf1");
-        auto conf2 = std::make_unique<mock_plugin>("conf2");
+	configurable_plugin_cli_fixture()
+	{
+		auto conf1 = std::make_unique<mock_plugin>("conf1");
+		auto conf2 = std::make_unique<mock_plugin>("conf2");
 
-        conf1->set_options({
-            { "v1", "123" },
-            { "v2", "456" }
-        });
+		conf1->set_options({
+			{ "v1", "123" },
+			{ "v2", "456" }
+		});
 
-        irccd_.plugins().add(std::move(conf1));
-        irccd_.plugins().add(std::move(conf2));
-    }
+		irccd_.plugins().add(std::move(conf1));
+		irccd_.plugins().add(std::move(conf2));
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_config_suite, configurable_plugin_cli_fixture)
 
 BOOST_AUTO_TEST_CASE(set_and_get)
 {
-    start();
+	start();
 
-    // First, configure. No output yet
-    {
-        const auto [code, out, err] = exec({ "plugin-config", "conf2", "verbose", "false" });
+	// First, configure. No output yet
+	{
+		const auto [code, out, err] = exec({ "plugin-config", "conf2", "verbose", "false" });
 
-        // no output yet.
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		// no output yet.
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    // Get the newly created value.
-    {
-        const auto [code, out, err] = exec({ "plugin-config", "conf2", "verbose" });
+	// Get the newly created value.
+	{
+		const auto [code, out, err] = exec({ "plugin-config", "conf2", "verbose" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 1U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0] == "false");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 1U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0] == "false");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(getall)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-config", "conf1" });
+	const auto [code, out, err] = exec({ "plugin-config", "conf1" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 2U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0] == "v1               : 123");
-    BOOST_TEST(out[1] == "v2               : 456");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 2U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "v1               : 123");
+	BOOST_TEST(out[1] == "v2               : 456");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-config", "+++" });
+	const auto [code, out, err] = exec({ "plugin-config", "+++" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid plugin identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid plugin identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-config", "unknown" });
+	const auto [code, out, err] = exec({ "plugin-config", "unknown" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: plugin not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: plugin not found");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-plugin-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-info
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-info
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,44 +32,44 @@
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    irccd_.plugins().add(std::make_unique<mock_plugin>("test"));
-    start();
+	irccd_.plugins().add(std::make_unique<mock_plugin>("test"));
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-info", "test" });
+	const auto [code, out, err] = exec({ "plugin-info", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 4U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0] == "Author         : David Demelier <markand@malikania.fr>");
-    BOOST_TEST(out[1] == "License        : ISC");
-    BOOST_TEST(out[2] == "Summary        : mock plugin");
-    BOOST_TEST(out[3] == "Version        : 1.0");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 4U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "Author         : David Demelier <markand@malikania.fr>");
+	BOOST_TEST(out[1] == "License        : ISC");
+	BOOST_TEST(out[2] == "Summary        : mock plugin");
+	BOOST_TEST(out[3] == "Version        : 1.0");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-info", "+++" });
+	const auto [code, out, err] = exec({ "plugin-info", "+++" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid plugin identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid plugin identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-info", "unknown" });
+	const auto [code, out, err] = exec({ "plugin-info", "unknown" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: plugin not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: plugin not found");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-plugin-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-list
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-list
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,17 +32,17 @@
 
 BOOST_AUTO_TEST_CASE(output)
 {
-    irccd_.plugins().add(std::make_unique<mock_plugin>("p1"));
-    irccd_.plugins().add(std::make_unique<mock_plugin>("p2"));
-    start();
+	irccd_.plugins().add(std::make_unique<mock_plugin>("p1"));
+	irccd_.plugins().add(std::make_unique<mock_plugin>("p2"));
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-list" });
+	const auto [code, out, err] = exec({ "plugin-list" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 2U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0] == "p1");
-    BOOST_TEST(out[1] == "p2");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 2U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "p1");
+	BOOST_TEST(out[1] == "p2");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-plugin-load/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-load/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-load
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-load
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-load/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-load/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,20 +30,20 @@
 
 class custom_plugin_loader : public plugin_loader {
 public:
-    custom_plugin_loader()
-        : plugin_loader({}, { "none" })
-    {
-    }
+	custom_plugin_loader()
+		: plugin_loader({}, { "none" })
+	{
+	}
 
-    auto find(std::string_view id) -> std::shared_ptr<plugin> override
-    {
-        return std::make_unique<mock_plugin>(std::string(id));
-    }
+	auto find(std::string_view id) -> std::shared_ptr<plugin> override
+	{
+		return std::make_unique<mock_plugin>(std::string(id));
+	}
 
-    auto open(std::string_view id, std::string_view) -> std::shared_ptr<plugin> override
-    {
-        return std::make_unique<mock_plugin>(std::string(id));
-    }
+	auto open(std::string_view id, std::string_view) -> std::shared_ptr<plugin> override
+	{
+		return std::make_unique<mock_plugin>(std::string(id));
+	}
 };
 
 } // !namespace
@@ -52,31 +52,31 @@
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    irccd_.plugins().add(std::make_unique<mock_plugin>("p1"));
-    irccd_.plugins().add(std::make_unique<mock_plugin>("p2"));
-    irccd_.plugins().add_loader(std::make_unique<custom_plugin_loader>());
-    start();
+	irccd_.plugins().add(std::make_unique<mock_plugin>("p1"));
+	irccd_.plugins().add(std::make_unique<mock_plugin>("p2"));
+	irccd_.plugins().add_loader(std::make_unique<custom_plugin_loader>());
+	start();
 
-    // Load a plugin first.
-    {
-        const auto [code, out, err] = exec({ "plugin-load", "test" });
+	// Load a plugin first.
+	{
+		const auto [code, out, err] = exec({ "plugin-load", "test" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    // Get the new list of plugins.
-    {
-        const auto [code, out, err] = exec({ "plugin-list" });
+	// Get the new list of plugins.
+	{
+		const auto [code, out, err] = exec({ "plugin-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 3U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0] == "p1");
-        BOOST_TEST(out[1] == "p2");
-        BOOST_TEST(out[2] == "test");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 3U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0] == "p1");
+		BOOST_TEST(out[1] == "p2");
+		BOOST_TEST(out[2] == "test");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-reload/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-reload
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-reload
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-reload/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-reload/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,37 +30,37 @@
 
 class reloadable_plugin : public mock, public plugin {
 public:
-    reloadable_plugin()
-        : plugin("test")
-    {
-    }
+	reloadable_plugin()
+		: plugin("test")
+	{
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "reload";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "reload";
+	}
 
-    void handle_reload(irccd&) override
-    {
-        push("handle_reload");
-    }
+	void handle_reload(irccd&) override
+	{
+		push("handle_reload");
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_reload_suite, cli_fixture)
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    const auto plugin = std::make_shared<reloadable_plugin>();
+	const auto plugin = std::make_shared<reloadable_plugin>();
 
-    irccd_.plugins().add(plugin);
-    start();
+	irccd_.plugins().add(plugin);
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-reload", "test" });
+	const auto [code, out, err] = exec({ "plugin-reload", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(plugin->find("handle_reload").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(plugin->find("handle_reload").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-unload/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-plugin-unload
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-plugin-unload
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-plugin-unload/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-plugin-unload/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,38 +30,38 @@
 
 class unloadable_plugin : public mock, public plugin {
 public:
-    unloadable_plugin()
-        : plugin("test")
-    {
-    }
+	unloadable_plugin()
+		: plugin("test")
+	{
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "unload";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "unload";
+	}
 
-    void handle_unload(irccd&) override
-    {
-        push("handle_unload");
-    }
+	void handle_unload(irccd&) override
+	{
+		push("handle_unload");
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_unload_suite, cli_fixture)
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    const auto plugin = std::make_shared<unloadable_plugin>();
+	const auto plugin = std::make_shared<unloadable_plugin>();
 
-    irccd_.plugins().add(plugin);
-    start();
+	irccd_.plugins().add(plugin);
+	start();
 
-    const auto [code, out, err] = exec({ "plugin-unload", "test" });
+	const auto [code, out, err] = exec({ "plugin-unload", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(plugin->find("handle_unload").size() == 1U);
-    BOOST_TEST(!irccd_.plugins().has("p"));
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(plugin->find("handle_unload").size() == 1U);
+	BOOST_TEST(!irccd_.plugins().has("p"));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-add/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-add/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-add
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-add
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-add/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-add/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,157 +31,157 @@
 
 BOOST_AUTO_TEST_CASE(all)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-add",
-            "-c c1",        "--add-channel c2",
-            "-e onMessage", "--add-event onCommand",
-            "-p p1",        "--add-plugin p2",
-            "-s s1",        "--add-server s2",
-            "drop"
-        });
+	{
+		const auto [code, out, err] = exec({ "rule-add",
+			"-c c1",        "--add-channel c2",
+			"-e onMessage", "--add-event onCommand",
+			"-p p1",        "--add-plugin p2",
+			"-s s1",        "--add-server s2",
+			"drop"
+		});
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(server)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-add", "-s s1", "--add-server s2", "drop" });
+	{
+		const auto [code, out, err] = exec({ "rule-add", "-s s1", "--add-server s2", "drop" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    ");
-        BOOST_TEST(out[3]  == "plugins:     ");
-        BOOST_TEST(out[4]  == "events:      ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    ");
+		BOOST_TEST(out[3]  == "plugins:     ");
+		BOOST_TEST(out[4]  == "events:      ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(channel)
-{
-    start();
+	{
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-add", "-c c1", "--add-channel c2", "drop" });
+	{
+		const auto [code, out, err] = exec({ "rule-add", "-c c1", "--add-channel c2", "drop" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     ");
-        BOOST_TEST(out[4]  == "events:      ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     ");
+		BOOST_TEST(out[4]  == "events:      ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(plugin)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-add", "-p p1", "--add-plugin p2", "drop" });
+	{
+		const auto [code, out, err] = exec({ "rule-add", "-p p1", "--add-plugin p2", "drop" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     ");
-        BOOST_TEST(out[2]  == "channels:    ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     ");
+		BOOST_TEST(out[2]  == "channels:    ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(event)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-add", "-e onMessage", "--add-event onCommand", "drop" });
+	{
+		const auto [code, out, err] = exec({ "rule-add", "-e onMessage", "--add-event onCommand", "drop" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     ");
-        BOOST_TEST(out[2]  == "channels:    ");
-        BOOST_TEST(out[3]  == "plugins:     ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     ");
+		BOOST_TEST(out[2]  == "channels:    ");
+		BOOST_TEST(out[3]  == "plugins:     ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_action)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-add", "-p p1", "--add-plugin p2", "break" });
+	const auto [code, out, err] = exec({ "rule-add", "-p p1", "--add-plugin p2", "break" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule action");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule action");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-edit/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-edit/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-edit
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-edit
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-edit/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-edit/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,234 +29,234 @@
 
 class custom_cli_fixture : public cli_fixture {
 public:
-    custom_cli_fixture()
-    {
-        irccd_.rules().add({
-            { "s1", "s2" },
-            { "c1", "c2" },
-            { "o1", "o2" },
-            { "p1", "p2" },
-            { "onCommand", "onMessage" },
-            rule::action::drop
-        });
-    }
+	custom_cli_fixture()
+	{
+		irccd_.rules().add({
+			{ "s1", "s2" },
+			{ "c1", "c2" },
+			{ "o1", "o2" },
+			{ "p1", "p2" },
+			{ "onCommand", "onMessage" },
+			rule::action_type::drop
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_edit_suite, custom_cli_fixture)
 
 BOOST_AUTO_TEST_CASE(server)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit",
-            "-s ts1",   "--add-server ts2",
-            "-S s1",    "--remove-server s2",
-            "0"
-        });
+	{
+		const auto [code, out, err] = exec({ "rule-edit",
+			"-s ts1",   "--add-server ts2",
+			"-S s1",    "--remove-server s2",
+			"0"
+		});
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     ts1 ts2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     ts1 ts2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(channel)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit",
-            "-c tc1",   "--add-channel tc2",
-            "-C c1",    "--remove-channel c2",
-            "0"
-        });
+	{
+		const auto [code, out, err] = exec({ "rule-edit",
+			"-c tc1",   "--add-channel tc2",
+			"-C c1",    "--remove-channel c2",
+			"0"
+		});
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    tc1 tc2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    tc1 tc2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(plugin)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit",
-            "-p tp1",   "--add-plugin tp2",
-            "-P p1",    "--remove-plugin p2",
-            "0"
-        });
+	{
+		const auto [code, out, err] = exec({ "rule-edit",
+			"-p tp1",   "--add-plugin tp2",
+			"-P p1",    "--remove-plugin p2",
+			"0"
+		});
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     tp1 tp2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     tp1 tp2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(event)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit",
-            "-e onKick",    "--add-event onNickname",
-            "-E onMessage", "--remove-event onCommand",
-            "0"
-        });
+	{
+		const auto [code, out, err] = exec({ "rule-edit",
+			"-e onKick",    "--add-event onNickname",
+			"-E onMessage", "--remove-event onCommand",
+			"0"
+		});
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onKick onNickname ");
-        BOOST_TEST(out[5]  == "action:      drop");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onKick onNickname ");
+		BOOST_TEST(out[5]  == "action:      drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(action_1)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit", "-a accept", "0" });
+	{
+		const auto [code, out, err] = exec({ "rule-edit", "-a accept", "0" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      accept");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      accept");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(action_2)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-edit", "--action accept", "0" });
+	{
+		const auto [code, out, err] = exec({ "rule-edit", "--action accept", "0" });
 
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 7U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-        BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-        BOOST_TEST(out[5]  == "action:      accept");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 7U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+		BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+		BOOST_TEST(out[5]  == "action:      accept");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-edit", "-p p1", "100" });
+	const auto [code, out, err] = exec({ "rule-edit", "-p p1", "100" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-edit", "-p p1", "notaint" });
+	const auto [code, out, err] = exec({ "rule-edit", "-p p1", "notaint" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_action)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-edit", "--action break", "0" });
+	const auto [code, out, err] = exec({ "rule-edit", "--action break", "0" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule action");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule action");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-info
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-info
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,53 +31,53 @@
 
 BOOST_AUTO_TEST_CASE(info)
 {
-    irccd_.rules().add({
-        { "s1", "s2" },
-        { "c1", "c2" },
-        { "o1", "o2" },
-        { "p1", "p2" },
-        { "onCommand", "onMessage" },
-        rule::action::drop
-    });
-    start();
+	irccd_.rules().add({
+		{ "s1", "s2" },
+		{ "c1", "c2" },
+		{ "o1", "o2" },
+		{ "p1", "p2" },
+		{ "onCommand", "onMessage" },
+		rule::action_type::drop
+	});
+	start();
 
-    const auto [code, out, err] = exec({ "rule-info", "0" });
+	const auto [code, out, err] = exec({ "rule-info", "0" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 7U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0]  == "rule:        0");
-    BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-    BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-    BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-    BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-    BOOST_TEST(out[5]  == "action:      drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 7U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0]  == "rule:        0");
+	BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+	BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+	BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+	BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+	BOOST_TEST(out[5]  == "action:      drop");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-info", "100" });
+	const auto [code, out, err] = exec({ "rule-info", "100" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-info", "notaint" });
+	const auto [code, out, err] = exec({ "rule-info", "notaint" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-list
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-list
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,27 +31,27 @@
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    irccd_.rules().add({
-        { "s1", "s2" },
-        { "c1", "c2" },
-        { "o1", "o2" },
-        { "p1", "p2" },
-        { "onCommand", "onMessage" },
-        rule::action::drop
-    });
-    start();
+	irccd_.rules().add({
+		{ "s1", "s2" },
+		{ "c1", "c2" },
+		{ "o1", "o2" },
+		{ "p1", "p2" },
+		{ "onCommand", "onMessage" },
+		rule::action_type::drop
+	});
+	start();
 
-    const auto [code, out, err] = exec({ "rule-list" });
+	const auto [code, out, err] = exec({ "rule-list" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 7U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0]  == "rule:        0");
-    BOOST_TEST(out[1]  == "servers:     s1 s2 ");
-    BOOST_TEST(out[2]  == "channels:    c1 c2 ");
-    BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
-    BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
-    BOOST_TEST(out[5]  == "action:      drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 7U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0]  == "rule:        0");
+	BOOST_TEST(out[1]  == "servers:     s1 s2 ");
+	BOOST_TEST(out[2]  == "channels:    c1 c2 ");
+	BOOST_TEST(out[3]  == "plugins:     p1 p2 ");
+	BOOST_TEST(out[4]  == "events:      onCommand onMessage ");
+	BOOST_TEST(out[5]  == "action:      drop");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-move/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-move/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-move
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-move
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-move/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-move/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,199 +29,199 @@
 
 class custom_cli_fixture : public cli_fixture {
 public:
-    custom_cli_fixture()
-    {
-        irccd_.rules().add({
-            { "s1" },
-            { "c1" },
-            { "o1" },
-            { "p1" },
-            { "onTopic" },
-            rule::action::accept
-        });
-        irccd_.rules().add({
-            { "s2" },
-            { "c2" },
-            { "o2" },
-            { "p2" },
-            { "onCommand" },
-            rule::action::drop
-        });
-        irccd_.rules().add({
-            { "s3" },
-            { "c3" },
-            { "o3" },
-            { "p3" },
-            { "onMessage" },
-            rule::action::accept
-        });
-    }
+	custom_cli_fixture()
+	{
+		irccd_.rules().add({
+			{ "s1" },
+			{ "c1" },
+			{ "o1" },
+			{ "p1" },
+			{ "onTopic" },
+			rule::action_type::accept
+		});
+		irccd_.rules().add({
+			{ "s2" },
+			{ "c2" },
+			{ "o2" },
+			{ "p2" },
+			{ "onCommand" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add({
+			{ "s3" },
+			{ "c3" },
+			{ "o3" },
+			{ "p3" },
+			{ "onMessage" },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_move_suite, custom_cli_fixture)
 
 BOOST_AUTO_TEST_CASE(from_0_to_1)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-move", "0", "1" });
+	{
+		const auto [code, out, err] = exec({ "rule-move", "0", "1" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 21U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s2 ");
-        BOOST_TEST(out[2]  == "channels:    c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand ");
-        BOOST_TEST(out[5]  == "action:      drop");
-        BOOST_TEST(out[6]  == "");
-        BOOST_TEST(out[7]  == "rule:        1");
-        BOOST_TEST(out[8]  == "servers:     s1 ");
-        BOOST_TEST(out[9]  == "channels:    c1 ");
-        BOOST_TEST(out[10] == "plugins:     p1 ");
-        BOOST_TEST(out[11] == "events:      onTopic ");
-        BOOST_TEST(out[12] == "action:      accept");
-        BOOST_TEST(out[13] == "");
-        BOOST_TEST(out[14] == "rule:        2");
-        BOOST_TEST(out[15] == "servers:     s3 ");
-        BOOST_TEST(out[16] == "channels:    c3 ");
-        BOOST_TEST(out[17] == "plugins:     p3 ");
-        BOOST_TEST(out[18] == "events:      onMessage ");
-        BOOST_TEST(out[19] == "action:      accept");
-        BOOST_TEST(out[20] == "");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 21U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s2 ");
+		BOOST_TEST(out[2]  == "channels:    c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand ");
+		BOOST_TEST(out[5]  == "action:      drop");
+		BOOST_TEST(out[6]  == "");
+		BOOST_TEST(out[7]  == "rule:        1");
+		BOOST_TEST(out[8]  == "servers:     s1 ");
+		BOOST_TEST(out[9]  == "channels:    c1 ");
+		BOOST_TEST(out[10] == "plugins:     p1 ");
+		BOOST_TEST(out[11] == "events:      onTopic ");
+		BOOST_TEST(out[12] == "action:      accept");
+		BOOST_TEST(out[13] == "");
+		BOOST_TEST(out[14] == "rule:        2");
+		BOOST_TEST(out[15] == "servers:     s3 ");
+		BOOST_TEST(out[16] == "channels:    c3 ");
+		BOOST_TEST(out[17] == "plugins:     p3 ");
+		BOOST_TEST(out[18] == "events:      onMessage ");
+		BOOST_TEST(out[19] == "action:      accept");
+		BOOST_TEST(out[20] == "");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(from_2_to_0)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-move", "2", "0" });
+	{
+		const auto [code, out, err] = exec({ "rule-move", "2", "0" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 21U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s3 ");
-        BOOST_TEST(out[2]  == "channels:    c3 ");
-        BOOST_TEST(out[3]  == "plugins:     p3 ");
-        BOOST_TEST(out[4]  == "events:      onMessage ");
-        BOOST_TEST(out[5]  == "action:      accept");
-        BOOST_TEST(out[6]  == "");
-        BOOST_TEST(out[7]  == "rule:        1");
-        BOOST_TEST(out[8]  == "servers:     s1 ");
-        BOOST_TEST(out[9]  == "channels:    c1 ");
-        BOOST_TEST(out[10] == "plugins:     p1 ");
-        BOOST_TEST(out[11] == "events:      onTopic ");
-        BOOST_TEST(out[12] == "action:      accept");
-        BOOST_TEST(out[13] == "");
-        BOOST_TEST(out[14] == "rule:        2");
-        BOOST_TEST(out[15] == "servers:     s2 ");
-        BOOST_TEST(out[16] == "channels:    c2 ");
-        BOOST_TEST(out[17] == "plugins:     p2 ");
-        BOOST_TEST(out[18] == "events:      onCommand ");
-        BOOST_TEST(out[19] == "action:      drop");
-        BOOST_TEST(out[20] == "");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 21U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s3 ");
+		BOOST_TEST(out[2]  == "channels:    c3 ");
+		BOOST_TEST(out[3]  == "plugins:     p3 ");
+		BOOST_TEST(out[4]  == "events:      onMessage ");
+		BOOST_TEST(out[5]  == "action:      accept");
+		BOOST_TEST(out[6]  == "");
+		BOOST_TEST(out[7]  == "rule:        1");
+		BOOST_TEST(out[8]  == "servers:     s1 ");
+		BOOST_TEST(out[9]  == "channels:    c1 ");
+		BOOST_TEST(out[10] == "plugins:     p1 ");
+		BOOST_TEST(out[11] == "events:      onTopic ");
+		BOOST_TEST(out[12] == "action:      accept");
+		BOOST_TEST(out[13] == "");
+		BOOST_TEST(out[14] == "rule:        2");
+		BOOST_TEST(out[15] == "servers:     s2 ");
+		BOOST_TEST(out[16] == "channels:    c2 ");
+		BOOST_TEST(out[17] == "plugins:     p2 ");
+		BOOST_TEST(out[18] == "events:      onCommand ");
+		BOOST_TEST(out[19] == "action:      drop");
+		BOOST_TEST(out[20] == "");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(same)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-move", "2", "2" });
+	{
+		const auto [code, out, err] = exec({ "rule-move", "2", "2" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 21U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s1 ");
-        BOOST_TEST(out[2]  == "channels:    c1 ");
-        BOOST_TEST(out[3]  == "plugins:     p1 ");
-        BOOST_TEST(out[4]  == "events:      onTopic ");
-        BOOST_TEST(out[5]  == "action:      accept");
-        BOOST_TEST(out[6]  == "");
-        BOOST_TEST(out[7]  == "rule:        1");
-        BOOST_TEST(out[8]  == "servers:     s2 ");
-        BOOST_TEST(out[9]  == "channels:    c2 ");
-        BOOST_TEST(out[10] == "plugins:     p2 ");
-        BOOST_TEST(out[11] == "events:      onCommand ");
-        BOOST_TEST(out[12] == "action:      drop");
-        BOOST_TEST(out[13] == "");
-        BOOST_TEST(out[14] == "rule:        2");
-        BOOST_TEST(out[15] == "servers:     s3 ");
-        BOOST_TEST(out[16] == "channels:    c3 ");
-        BOOST_TEST(out[17] == "plugins:     p3 ");
-        BOOST_TEST(out[18] == "events:      onMessage ");
-        BOOST_TEST(out[19] == "action:      accept");
-        BOOST_TEST(out[20] == "");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 21U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s1 ");
+		BOOST_TEST(out[2]  == "channels:    c1 ");
+		BOOST_TEST(out[3]  == "plugins:     p1 ");
+		BOOST_TEST(out[4]  == "events:      onTopic ");
+		BOOST_TEST(out[5]  == "action:      accept");
+		BOOST_TEST(out[6]  == "");
+		BOOST_TEST(out[7]  == "rule:        1");
+		BOOST_TEST(out[8]  == "servers:     s2 ");
+		BOOST_TEST(out[9]  == "channels:    c2 ");
+		BOOST_TEST(out[10] == "plugins:     p2 ");
+		BOOST_TEST(out[11] == "events:      onCommand ");
+		BOOST_TEST(out[12] == "action:      drop");
+		BOOST_TEST(out[13] == "");
+		BOOST_TEST(out[14] == "rule:        2");
+		BOOST_TEST(out[15] == "servers:     s3 ");
+		BOOST_TEST(out[16] == "channels:    c3 ");
+		BOOST_TEST(out[17] == "plugins:     p3 ");
+		BOOST_TEST(out[18] == "events:      onMessage ");
+		BOOST_TEST(out[19] == "action:      accept");
+		BOOST_TEST(out[20] == "");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1_from)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-move", "100", "0" });
+	const auto [code, out, err] = exec({ "rule-move", "100", "0" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2_from)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-move", "notaint", "0" });
+	const auto [code, out, err] = exec({ "rule-move", "notaint", "0" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_to)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-move", "0", "notaint" });
+	const auto [code, out, err] = exec({ "rule-move", "0", "notaint" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-rule-remove/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-remove/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-rule-remove
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-rule-remove
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-rule-remove/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-rule-remove/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,96 +29,96 @@
 
 class custom_cli_fixture : public cli_fixture {
 public:
-    custom_cli_fixture()
-    {
-        irccd_.rules().add({
-            { "s1" },
-            { "c1" },
-            { "o1" },
-            { "p1" },
-            { "onTopic" },
-            rule::action::accept
-        });
-        irccd_.rules().add({
-            { "s2" },
-            { "c2" },
-            { "o2" },
-            { "p2" },
-            { "onCommand" },
-            rule::action::drop
-        });
-        irccd_.rules().add({
-            { "s3" },
-            { "c3" },
-            { "o3" },
-            { "p3" },
-            { "onMessage" },
-            rule::action::accept
-        });
-    }
+	custom_cli_fixture()
+	{
+		irccd_.rules().add({
+			{ "s1" },
+			{ "c1" },
+			{ "o1" },
+			{ "p1" },
+			{ "onTopic" },
+			rule::action_type::accept
+		});
+		irccd_.rules().add({
+			{ "s2" },
+			{ "c2" },
+			{ "o2" },
+			{ "p2" },
+			{ "onCommand" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add({
+			{ "s3" },
+			{ "c3" },
+			{ "o3" },
+			{ "p3" },
+			{ "onMessage" },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_move_suite, custom_cli_fixture)
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    start();
+	start();
 
-    {
-        const auto [code, out, err] = exec({ "rule-remove", "0" });
+	{
+		const auto [code, out, err] = exec({ "rule-remove", "0" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 0U);
-        BOOST_TEST(err.size() == 0U);
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 0U);
+		BOOST_TEST(err.size() == 0U);
+	}
 
-    {
-        const auto [code, out, err] = exec({ "rule-list" });
+	{
+		const auto [code, out, err] = exec({ "rule-list" });
 
-        BOOST_TEST(!code);
-        BOOST_TEST(out.size() == 14U);
-        BOOST_TEST(err.size() == 0U);
-        BOOST_TEST(out[0]  == "rule:        0");
-        BOOST_TEST(out[1]  == "servers:     s2 ");
-        BOOST_TEST(out[2]  == "channels:    c2 ");
-        BOOST_TEST(out[3]  == "plugins:     p2 ");
-        BOOST_TEST(out[4]  == "events:      onCommand ");
-        BOOST_TEST(out[5]  == "action:      drop");
-        BOOST_TEST(out[6]  == "");
-        BOOST_TEST(out[7]  == "rule:        1");
-        BOOST_TEST(out[8]  == "servers:     s3 ");
-        BOOST_TEST(out[9]  == "channels:    c3 ");
-        BOOST_TEST(out[10] == "plugins:     p3 ");
-        BOOST_TEST(out[11] == "events:      onMessage ");
-        BOOST_TEST(out[12] == "action:      accept");
-        BOOST_TEST(out[13] == "");
-    }
+		BOOST_TEST(!code);
+		BOOST_TEST(out.size() == 14U);
+		BOOST_TEST(err.size() == 0U);
+		BOOST_TEST(out[0]  == "rule:        0");
+		BOOST_TEST(out[1]  == "servers:     s2 ");
+		BOOST_TEST(out[2]  == "channels:    c2 ");
+		BOOST_TEST(out[3]  == "plugins:     p2 ");
+		BOOST_TEST(out[4]  == "events:      onCommand ");
+		BOOST_TEST(out[5]  == "action:      drop");
+		BOOST_TEST(out[6]  == "");
+		BOOST_TEST(out[7]  == "rule:        1");
+		BOOST_TEST(out[8]  == "servers:     s3 ");
+		BOOST_TEST(out[9]  == "channels:    c3 ");
+		BOOST_TEST(out[10] == "plugins:     p3 ");
+		BOOST_TEST(out[11] == "events:      onMessage ");
+		BOOST_TEST(out[12] == "action:      accept");
+		BOOST_TEST(out[13] == "");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-remove", "100" });
+	const auto [code, out, err] = exec({ "rule-remove", "100" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "rule-remove", "notaint" });
+	const auto [code, out, err] = exec({ "rule-remove", "notaint" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid rule index");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid rule index");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-disconnect/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-disconnect/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-disconnect
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-disconnect
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-disconnect/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-disconnect/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,70 +31,70 @@
 
 BOOST_AUTO_TEST_CASE(one)
 {
-    const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
-    const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
+	const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
+	const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
 
-    irccd_.servers().add(s1);
-    irccd_.servers().add(s2);
-    s1->clear();
-    s2->clear();
-    start();
+	irccd_.servers().add(s1);
+	irccd_.servers().add(s2);
+	s1->clear();
+	s2->clear();
+	start();
 
-    const auto [code, out, err] = exec({ "server-disconnect", "test" });
+	const auto [code, out, err] = exec({ "server-disconnect", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(server_->find("disconnect").size() == 1U);
-    BOOST_TEST(s1->find("disconnect").size() == 0U);
-    BOOST_TEST(s2->find("disconnect").size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(server_->find("disconnect").size() == 1U);
+	BOOST_TEST(s1->find("disconnect").size() == 0U);
+	BOOST_TEST(s2->find("disconnect").size() == 0U);
 }
 
 BOOST_AUTO_TEST_CASE(all)
 {
-    const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
-    const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
+	const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
+	const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
 
-    irccd_.servers().add(s1);
-    irccd_.servers().add(s2);
-    s1->clear();
-    s2->clear();
-    start();
+	irccd_.servers().add(s1);
+	irccd_.servers().add(s2);
+	s1->clear();
+	s2->clear();
+	start();
 
-    const auto [code, out, err] = exec({ "server-disconnect" });
+	const auto [code, out, err] = exec({ "server-disconnect" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(server_->find("disconnect").size() == 1U);
-    BOOST_TEST(s1->find("disconnect").size() == 1U);
-    BOOST_TEST(s2->find("disconnect").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(server_->find("disconnect").size() == 1U);
+	BOOST_TEST(s1->find("disconnect").size() == 1U);
+	BOOST_TEST(s2->find("disconnect").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-disconnect", "+++" });
+	const auto [code, out, err] = exec({ "server-disconnect", "+++" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-disconnect", "unknown" });
+	const auto [code, out, err] = exec({ "server-disconnect", "unknown" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-info
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-info
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,51 +31,51 @@
 
 BOOST_AUTO_TEST_CASE(output)
 {
-    server_->set_username("francis");
-    server_->set_nickname("francis");
-    start();
+	server_->set_username("francis");
+	server_->set_nickname("francis");
+	start();
 
-    const auto [code, out, err] = exec({ "server-info", "test" });
+	const auto [code, out, err] = exec({ "server-info", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 10U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0] == "Name           : test");
-    BOOST_TEST(out[1] == "Host           : localhost");
-    BOOST_TEST(out[2] == "Port           : 6667");
-    BOOST_TEST(out[3] == "Ipv6           : null");
-    BOOST_TEST(out[4] == "SSL            : null");
-    BOOST_TEST(out[5] == "SSL verified   : null");
-    BOOST_TEST(out[6] == "Channels       : ");
-    BOOST_TEST(out[7] == "Nickname       : francis");
-    BOOST_TEST(out[8] == "User name      : francis");
-    BOOST_TEST(out[9] == "Real name      : IRC Client Daemon");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 10U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "Name           : test");
+	BOOST_TEST(out[1] == "Host           : localhost");
+	BOOST_TEST(out[2] == "Port           : 6667");
+	BOOST_TEST(out[3] == "Ipv6           : null");
+	BOOST_TEST(out[4] == "SSL            : null");
+	BOOST_TEST(out[5] == "SSL verified   : null");
+	BOOST_TEST(out[6] == "Channels       : ");
+	BOOST_TEST(out[7] == "Nickname       : francis");
+	BOOST_TEST(out[8] == "User name      : francis");
+	BOOST_TEST(out[9] == "Real name      : IRC Client Daemon");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-info", "+++" });
+	const auto [code, out, err] = exec({ "server-info", "+++" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-info", "unknown" });
+	const auto [code, out, err] = exec({ "server-info", "unknown" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-invite/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-invite/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-invite
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-invite
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-invite/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-invite/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,69 +31,69 @@
 
 BOOST_AUTO_TEST_CASE(output)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-invite", "test", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-invite", "test", "francis", "#staff" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("invite");
+	const auto cmd = server_->find("invite");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-invite", "+++", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-invite", "+++", "francis", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-invite", "unknown", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-invite", "unknown", "francis", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-invite", "test", "\"\"", "#staff" });
+	const auto [code, out, err] = exec({ "server-invite", "test", "\"\"", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid nickname");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid nickname");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-invite", "test", "francis", "\"\"" });
+	const auto [code, out, err] = exec({ "server-invite", "test", "francis", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-join/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-join/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-join
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-join
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-join/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-join/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,74 +31,74 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-join", "test", "#staff" });
+	const auto [code, out, err] = exec({ "server-join", "test", "#staff" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("join");
+	const auto cmd = server_->find("join");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "");
 }
 
 BOOST_AUTO_TEST_CASE(with_password)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-join", "test", "#staff", "secret" });
+	const auto [code, out, err] = exec({ "server-join", "test", "#staff", "secret" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("join");
+	const auto cmd = server_->find("join");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "secret");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "secret");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-join", "+++", "#staff" });
+	const auto [code, out, err] = exec({ "server-join", "+++", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-join", "unknown", "#staff" });
+	const auto [code, out, err] = exec({ "server-join", "unknown", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-join", "test", "\"\"" });
+	const auto [code, out, err] = exec({ "server-join", "test", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-kick/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-kick/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-kick
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-kick
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-kick/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-kick/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,88 +31,88 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "test", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-kick", "test", "francis", "#staff" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("kick");
+	const auto cmd = server_->find("kick");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "");
 }
 
 BOOST_AUTO_TEST_CASE(with_reason)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "test", "francis", "#staff", "shhh" });
+	const auto [code, out, err] = exec({ "server-kick", "test", "francis", "#staff", "shhh" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("kick");
+	const auto cmd = server_->find("kick");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "shhh");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "shhh");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "+++", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-kick", "+++", "francis", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "unknown", "francis", "#staff" });
+	const auto [code, out, err] = exec({ "server-kick", "unknown", "francis", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "test", "\"\"", "#staff" });
+	const auto [code, out, err] = exec({ "server-kick", "test", "\"\"", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid nickname");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid nickname");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-kick", "test", "francis", "\"\"" });
+	const auto [code, out, err] = exec({ "server-kick", "test", "francis", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-list
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-list
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,18 +31,18 @@
 
 BOOST_AUTO_TEST_CASE(output)
 {
-    irccd_.servers().add(std::make_unique<mock_server>(irccd_.get_service(), "s1", "localhost"));
-    irccd_.servers().add(std::make_unique<mock_server>(irccd_.get_service(), "s2", "localhost"));
-    start();
+	irccd_.servers().add(std::make_unique<mock_server>(irccd_.get_service(), "s1", "localhost"));
+	irccd_.servers().add(std::make_unique<mock_server>(irccd_.get_service(), "s2", "localhost"));
+	start();
 
-    const auto [code, out, err] = exec({ "server-list" });
+	const auto [code, out, err] = exec({ "server-list" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 3U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(out[0] == "test");
-    BOOST_TEST(out[1] == "s1");
-    BOOST_TEST(out[2] == "s2");
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 3U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(out[0] == "test");
+	BOOST_TEST(out[1] == "s1");
+	BOOST_TEST(out[2] == "s2");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-me/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-me/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-me
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-me
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-me/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-me/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,57 +31,57 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-me", "test", "#staff", "hi" });
+	const auto [code, out, err] = exec({ "server-me", "test", "#staff", "hi" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("me");
+	const auto cmd = server_->find("me");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-me", "+++", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-me", "+++", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-me", "unknown", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-me", "unknown", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-me", "test", "\"\"", "hello" });
+	const auto [code, out, err] = exec({ "server-me", "test", "\"\"", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-message/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-message/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-message
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-message
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-message/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-message/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,57 +31,57 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-message", "test", "#staff", "hi" });
+	const auto [code, out, err] = exec({ "server-message", "test", "#staff", "hi" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("message");
+	const auto cmd = server_->find("message");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-message", "+++", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-message", "+++", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-message", "unknown", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-message", "unknown", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-message", "test", "\"\"", "hello" });
+	const auto [code, out, err] = exec({ "server-message", "test", "\"\"", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-mode/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-mode/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-mode
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-mode
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-mode/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-mode/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,92 +31,92 @@
 
 BOOST_AUTO_TEST_CASE(user)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "test", "irccd", "+i" });
+	const auto [code, out, err] = exec({ "server-mode", "test", "irccd", "+i" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("mode");
+	const auto cmd = server_->find("mode");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "irccd");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "+i");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][3]) == "");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][4]) == "");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "irccd");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "+i");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][3]) == "");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][4]) == "");
 }
 
 BOOST_AUTO_TEST_CASE(channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "test", "#staff", "+b", "francis" });
+	const auto [code, out, err] = exec({ "server-mode", "test", "#staff", "+b", "francis" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("mode");
+	const auto cmd = server_->find("mode");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "+b");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][3]) == "");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][4]) == "");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "+b");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][2]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][3]) == "");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][4]) == "");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "+++", "#staff", "+t" });
+	const auto [code, out, err] = exec({ "server-mode", "+++", "#staff", "+t" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "unknown", "#staff", "+t" });
+	const auto [code, out, err] = exec({ "server-mode", "unknown", "#staff", "+t" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "test", "\"\"", "+t" });
+	const auto [code, out, err] = exec({ "server-mode", "test", "\"\"", "+t" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_mode)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-mode", "test", "#staff", "\"\"" });
+	const auto [code, out, err] = exec({ "server-mode", "test", "#staff", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty mode");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty mode");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-nick/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-nick/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-nick
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-nick
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-nick/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-nick/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,75 +31,74 @@
 
 BOOST_AUTO_TEST_CASE(not_connected)
 {
-    start();
-    server_->disconnect();
+	start();
+	server_->disconnect();
 
-    const auto [code, out, err] = exec({ "server-nick", "test", "new" });
+	const auto [code, out, err] = exec({ "server-nick", "test", "new" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("raw");
+	const auto cmd = server_->find("raw");
 
-    BOOST_TEST(cmd.size() == 0U);
-    BOOST_TEST(server_->get_nickname() == "new");
+	BOOST_TEST(cmd.size() == 0U);
+	BOOST_TEST(server_->get_nickname() == "new");
 }
 
 BOOST_AUTO_TEST_CASE(connected)
 {
-    start();
-    server_->connect([] (auto) {});
+	start();
+	server_->connect([] (auto) {});
 
-    const auto [code, out, err] = exec({ "server-nick", "test", "new" });
+	const auto [code, out, err] = exec({ "server-nick", "test", "new" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("send");
+	const auto cmd = server_->find("send");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "NICK new");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "NICK new");
 }
 
-
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-nick", "+++", "francis" });
+	const auto [code, out, err] = exec({ "server-nick", "+++", "francis" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-nick", "unknown", "francis" });
+	const auto [code, out, err] = exec({ "server-nick", "unknown", "francis" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-nick", "test", "\"\"" });
+	const auto [code, out, err] = exec({ "server-nick", "test", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid nickname");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid nickname");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-notice/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-notice/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-notice
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-notice
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-notice/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-notice/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,57 +31,57 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-notice", "test", "francis", "hi" });
+	const auto [code, out, err] = exec({ "server-notice", "test", "francis", "hi" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("notice");
+	const auto cmd = server_->find("notice");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "hi");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-notice", "+++", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-notice", "+++", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-notice", "unknown", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-notice", "unknown", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-notice", "test", "\"\"", "hello" });
+	const auto [code, out, err] = exec({ "server-notice", "test", "\"\"", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-part/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-part/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-part
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-part
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-part/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-part/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,74 +31,74 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-part", "test", "#staff" });
+	const auto [code, out, err] = exec({ "server-part", "test", "#staff" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("part");
+	const auto cmd = server_->find("part");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "");
 }
 
 BOOST_AUTO_TEST_CASE(with_reason)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-part", "test", "#staff", "sick" });
+	const auto [code, out, err] = exec({ "server-part", "test", "#staff", "sick" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("part");
+	const auto cmd = server_->find("part");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "sick");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "sick");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-part", "+++", "#staff" });
+	const auto [code, out, err] = exec({ "server-part", "+++", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-part", "unknown", "#staff" });
+	const auto [code, out, err] = exec({ "server-part", "unknown", "#staff" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-part", "test", "\"\"" });
+	const auto [code, out, err] = exec({ "server-part", "test", "\"\"" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-reconnect/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-reconnect/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-reconnect
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-reconnect
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-reconnect/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-reconnect/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,76 +31,76 @@
 
 BOOST_AUTO_TEST_CASE(one)
 {
-    const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
-    const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
+	const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
+	const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
 
-    irccd_.servers().add(s1);
-    irccd_.servers().add(s2);
-    s1->clear();
-    s2->clear();
-    start();
+	irccd_.servers().add(s1);
+	irccd_.servers().add(s2);
+	s1->clear();
+	s2->clear();
+	start();
 
-    const auto [code, out, err] = exec({ "server-reconnect", "test" });
+	const auto [code, out, err] = exec({ "server-reconnect", "test" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(server_->find("disconnect").size() == 1U);
-    BOOST_TEST(server_->find("connect").size() == 1U);
-    BOOST_TEST(s1->find("disconnect").size() == 0U);
-    BOOST_TEST(s2->find("disconnect").size() == 0U);
-    BOOST_TEST(s1->find("connect").size() == 0U);
-    BOOST_TEST(s2->find("connect").size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(server_->find("disconnect").size() == 1U);
+	BOOST_TEST(server_->find("connect").size() == 1U);
+	BOOST_TEST(s1->find("disconnect").size() == 0U);
+	BOOST_TEST(s2->find("disconnect").size() == 0U);
+	BOOST_TEST(s1->find("connect").size() == 0U);
+	BOOST_TEST(s2->find("connect").size() == 0U);
 }
 
 BOOST_AUTO_TEST_CASE(all)
 {
-    const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
-    const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
+	const auto s1 = std::make_shared<mock_server>(irccd_.get_service(), "s1", "localhost");
+	const auto s2 = std::make_shared<mock_server>(irccd_.get_service(), "s2", "localhost");
 
-    irccd_.servers().add(s1);
-    irccd_.servers().add(s2);
-    s1->clear();
-    s2->clear();
-    start();
+	irccd_.servers().add(s1);
+	irccd_.servers().add(s2);
+	s1->clear();
+	s2->clear();
+	start();
 
-    const auto [code, out, err] = exec({ "server-reconnect" });
+	const auto [code, out, err] = exec({ "server-reconnect" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
-    BOOST_TEST(server_->find("disconnect").size() == 1U);
-    BOOST_TEST(server_->find("connect").size() == 1U);
-    BOOST_TEST(s1->find("disconnect").size() == 1U);
-    BOOST_TEST(s2->find("disconnect").size() == 1U);
-    BOOST_TEST(s1->find("connect").size() == 1U);
-    BOOST_TEST(s2->find("connect").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(server_->find("disconnect").size() == 1U);
+	BOOST_TEST(server_->find("connect").size() == 1U);
+	BOOST_TEST(s1->find("disconnect").size() == 1U);
+	BOOST_TEST(s2->find("disconnect").size() == 1U);
+	BOOST_TEST(s1->find("connect").size() == 1U);
+	BOOST_TEST(s2->find("connect").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-reconnect", "+++" });
+	const auto [code, out, err] = exec({ "server-reconnect", "+++" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-reconnect", "unknown" });
+	const auto [code, out, err] = exec({ "server-reconnect", "unknown" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/irccdctl/cli-server-topic/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-topic/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME cli-server-topic
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
-    DEPENDS irccd irccdctl
+	NAME cli-server-topic
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
+	DEPENDS irccd irccdctl
 )
--- a/tests/src/irccdctl/cli-server-topic/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/irccdctl/cli-server-topic/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,57 +31,57 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-topic", "test", "#staff", "welcome" });
+	const auto [code, out, err] = exec({ "server-topic", "test", "#staff", "welcome" });
 
-    BOOST_TEST(!code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 0U);
 
-    const auto cmd = server_->find("topic");
+	const auto cmd = server_->find("topic");
 
-    BOOST_TEST(cmd.size() == 1U);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "welcome");
+	BOOST_TEST(cmd.size() == 1U);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0][1]) == "welcome");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-topic", "+++", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-topic", "+++", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid server identifier");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid server identifier");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-topic", "unknown", "#staff", "hello" });
+	const auto [code, out, err] = exec({ "server-topic", "unknown", "#staff", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: server not found");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: server not found");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel)
 {
-    start();
+	start();
 
-    const auto [code, out, err] = exec({ "server-topic", "test", "\"\"", "hello" });
+	const auto [code, out, err] = exec({ "server-topic", "test", "\"\"", "hello" });
 
-    BOOST_TEST(code);
-    BOOST_TEST(out.size() == 0U);
-    BOOST_TEST(err.size() == 1U);
-    BOOST_TEST(err[0] == "abort: invalid or empty channel");
+	BOOST_TEST(code);
+	BOOST_TEST(out.size() == 0U);
+	BOOST_TEST(err.size() == 1U);
+	BOOST_TEST(err[0] == "abort: invalid or empty channel");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libcommon/fs-util/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/fs-util/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME fs-util
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
+	NAME fs-util
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
 )
--- a/tests/src/libcommon/fs-util/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/fs-util/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,20 +35,20 @@
 
 BOOST_AUTO_TEST_CASE(not_recursive)
 {
-    auto file1 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-1.txt", false);
-    auto file2 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-2.txt", false);
+	auto file1 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-1.txt", false);
+	auto file2 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-2.txt", false);
 
-    BOOST_TEST(file1.find("file-1.txt") != std::string::npos);
-    BOOST_TEST(file2.empty());
+	BOOST_TEST(file1.find("file-1.txt") != std::string::npos);
+	BOOST_TEST(file2.empty());
 }
 
 BOOST_AUTO_TEST_CASE(recursive)
 {
-    auto file1 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-1.txt", true);
-    auto file2 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-2.txt", true);
+	auto file1 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-1.txt", true);
+	auto file2 = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", "file-2.txt", true);
 
-    BOOST_TEST(file1.find("file-1.txt") != std::string::npos);
-    BOOST_TEST(file2.find("file-2.txt") != std::string::npos);
+	BOOST_TEST(file1.find("file-1.txt") != std::string::npos);
+	BOOST_TEST(file2.find("file-2.txt") != std::string::npos);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -62,18 +62,18 @@
 
 BOOST_AUTO_TEST_CASE(not_recursive)
 {
-    const std::regex regex("file-[12]\\.txt");
-    const auto file = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", regex, false);
+	const std::regex regex("file-[12]\\.txt");
+	const auto file = fs_util::find(CMAKE_SOURCE_DIR "/tests/root", regex, false);
 
-    BOOST_TEST(file.find("file-1.txt") != std::string::npos);
+	BOOST_TEST(file.find("file-1.txt") != std::string::npos);
 }
 
 BOOST_AUTO_TEST_CASE(recursive)
 {
-    const std::regex regex("file-[12]\\.txt");
-    const auto file = fs_util::find(CMAKE_SOURCE_DIR "/tests/root/level-1", regex, true);
+	const std::regex regex("file-[12]\\.txt");
+	const auto file = fs_util::find(CMAKE_SOURCE_DIR "/tests/root/level-1", regex, true);
 
-    BOOST_TEST(file.find("file-2.txt") != std::string::npos);
+	BOOST_TEST(file.find("file-2.txt") != std::string::npos);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libcommon/io/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/io/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME io
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
+	NAME io
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
 )
--- a/tests/src/libcommon/io/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/io/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -28,9 +28,9 @@
 #include <irccd/socket_stream.hpp>
 
 #if defined(IRCCD_HAVE_SSL)
-#   include <irccd/tls_acceptor.hpp>
-#   include <irccd/tls_connector.hpp>
-#   include <irccd/tls_stream.hpp>
+#	include <irccd/tls_acceptor.hpp>
+#	include <irccd/tls_connector.hpp>
+#	include <irccd/tls_stream.hpp>
 #endif // !IRCCD_HAVE_SSL
 
 using boost::asio::io_service;
@@ -50,100 +50,100 @@
 
 class io_fixture {
 public:
-    io_service service_;
+	io_service service_;
 
-    std::unique_ptr<io::acceptor> acceptor_;
-    std::unique_ptr<io::connector> connector_;
+	std::unique_ptr<acceptor> acceptor_;
+	std::unique_ptr<connector> connector_;
 
-    std::shared_ptr<io::stream> stream1_;
-    std::shared_ptr<io::stream> stream2_;
+	std::shared_ptr<stream> stream1_;
+	std::shared_ptr<stream> stream2_;
 
-    virtual auto create_acceptor() -> std::unique_ptr<io::acceptor> = 0;
+	virtual auto create_acceptor() -> std::unique_ptr<acceptor> = 0;
 
-    virtual auto create_connector() -> std::unique_ptr<io::connector> = 0;
+	virtual auto create_connector() -> std::unique_ptr<connector> = 0;
 
-    void init()
-    {
-        acceptor_ = create_acceptor();
-        connector_ = create_connector();
+	void init()
+	{
+		acceptor_ = create_acceptor();
+		connector_ = create_connector();
 
-        acceptor_->accept([this] (auto code, auto stream) {
-            if (code)
-                throw std::system_error(code);
+		acceptor_->accept([this] (auto code, auto stream) {
+			if (code)
+				throw std::system_error(code);
 
-            stream1_ = std::move(stream);
-        });
-        connector_->connect([this] (auto code, auto stream) {
-            if (code)
-                throw std::system_error(code);
+			stream1_ = std::move(stream);
+		});
+		connector_->connect([this] (auto code, auto stream) {
+			if (code)
+				throw std::system_error(code);
 
-            stream2_ = std::move(stream);
-        });
+			stream2_ = std::move(stream);
+		});
 
-        service_.run();
-        service_.reset();
-    }
+		service_.run();
+		service_.reset();
+	}
 };
 
 class ip_io_fixture : public io_fixture {
 private:
-    tcp::endpoint endpoint_;
+	tcp::endpoint endpoint_;
 
 protected:
-    /**
-     * \copydoc io_fixture::create_acceptor
-     */
-    auto create_acceptor() -> std::unique_ptr<io::acceptor> override
-    {
-        tcp::endpoint endpoint(tcp::v4(), 0U);
-        tcp::acceptor acceptor(service_, std::move(endpoint));
+	/**
+	 * \copydoc io_fixture::create_acceptor
+	 */
+	auto create_acceptor() -> std::unique_ptr<acceptor> override
+	{
+		tcp::endpoint endpoint(tcp::v4(), 0U);
+		tcp::acceptor acceptor(service_, std::move(endpoint));
 
-        endpoint_ = acceptor.local_endpoint();
+		endpoint_ = acceptor.local_endpoint();
 
-        return std::make_unique<io::ip_acceptor>(std::move(acceptor));
-    }
+		return std::make_unique<ip_acceptor>(std::move(acceptor));
+	}
 
-    /**
-     * \copydoc io_fixture::create_connector
-     */
-    auto create_connector() -> std::unique_ptr<io::connector> override
-    {
-        return std::make_unique<io::ip_connector>(service_, endpoint_);
-    }
+	/**
+	 * \copydoc io_fixture::create_connector
+	 */
+	auto create_connector() -> std::unique_ptr<connector> override
+	{
+		return std::make_unique<ip_connector>(service_, endpoint_);
+	}
 };
 
 #if defined(IRCCD_HAVE_SSL)
 
 class ssl_io_fixture : public io_fixture {
 private:
-    tcp::endpoint endpoint_;
+	tcp::endpoint endpoint_;
 
 protected:
-    /**
-     * \copydoc io_fixture::create_acceptor
-     */
-    auto create_acceptor() -> std::unique_ptr<io::acceptor> override
-    {
-        context context(context::sslv23);
+	/**
+	 * \copydoc io_fixture::create_acceptor
+	 */
+	auto create_acceptor() -> std::unique_ptr<acceptor> override
+	{
+		context context(context::sslv23);
 
-        context.use_certificate_file(TESTS_SOURCE_DIR "/data/test.crt", context::pem);
-        context.use_private_key_file(TESTS_SOURCE_DIR "/data/test.key", context::pem);
+		context.use_certificate_file(TESTS_SOURCE_DIR "/data/test.crt", context::pem);
+		context.use_private_key_file(TESTS_SOURCE_DIR "/data/test.key", context::pem);
 
-        tcp::endpoint endpoint(tcp::v4(), 0U);
-        tcp::acceptor acceptor(service_, std::move(endpoint));
+		tcp::endpoint endpoint(tcp::v4(), 0U);
+		tcp::acceptor acceptor(service_, std::move(endpoint));
 
-        endpoint_ = acceptor.local_endpoint();
+		endpoint_ = acceptor.local_endpoint();
 
-        return std::make_unique<io::tls_acceptor<>>(std::move(context), std::move(acceptor));
-    }
+		return std::make_unique<tls_acceptor<>>(std::move(context), std::move(acceptor));
+	}
 
-    /**
-     * \copydoc io_fixture::create_connector
-     */
-    auto create_connector() -> std::unique_ptr<io::connector> override
-    {
-        return std::make_unique<io::tls_connector<>>(context(context::sslv23), service_, endpoint_);
-    }
+	/**
+	 * \copydoc io_fixture::create_connector
+	 */
+	auto create_connector() -> std::unique_ptr<connector> override
+	{
+		return std::make_unique<tls_connector<>>(context(context::sslv23), service_, endpoint_);
+	}
 };
 
 #endif // !IRCCD_HAVE_SSL
@@ -152,25 +152,25 @@
 
 class local_io_fixture : public io_fixture {
 public:
-    /**
-     * \copydoc io_fixture::create_acceptor
-     */
-    auto create_acceptor() -> std::unique_ptr<io::acceptor> override
-    {
-        std::remove(CMAKE_BINARY_DIR "/tmp/io-test.sock");
+	/**
+	 * \copydoc io_fixture::create_acceptor
+	 */
+	auto create_acceptor() -> std::unique_ptr<acceptor> override
+	{
+		std::remove(CMAKE_BINARY_DIR "/tmp/io-test.sock");
 
-        stream_protocol::acceptor acceptor(service_, CMAKE_BINARY_DIR "/tmp/io-test.sock");
+		stream_protocol::acceptor acceptor(service_, CMAKE_BINARY_DIR "/tmp/io-test.sock");
 
-        return std::make_unique<io::local_acceptor>(std::move(acceptor));
-    }
+		return std::make_unique<local_acceptor>(std::move(acceptor));
+	}
 
-    /**
-     * \copydoc io_fixture::create_connector
-     */
-    auto create_connector() -> std::unique_ptr<io::connector> override
-    {
-        return std::make_unique<io::local_connector>(service_, CMAKE_BINARY_DIR "/tmp/io-test.sock");
-    }
+	/**
+	 * \copydoc io_fixture::create_connector
+	 */
+	auto create_connector() -> std::unique_ptr<connector> override
+	{
+		return std::make_unique<local_connector>(service_, CMAKE_BINARY_DIR "/tmp/io-test.sock");
+	}
 };
 
 #endif // !BOOST_OS_WINDOWS
@@ -179,48 +179,48 @@
  * List of fixtures to tests.
  */
 using list = boost::mpl::list<
-    ip_io_fixture
+	ip_io_fixture
 #if defined(IRCCD_HAVE_SSL)
-    , ssl_io_fixture
+	, ssl_io_fixture
 #endif
 #if !BOOST_OS_WINDOWS
-    , local_io_fixture
+	, local_io_fixture
 #endif
 >;
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(invalid_argument, Test, list)
 {
-    Test fixture;
+	Test fixture;
 
-    const nlohmann::json message{
-        { "abc", 123 },
-        { "def", 456 }
-    };
+	const nlohmann::json message{
+		{ "abc", 123 },
+		{ "def", 456 }
+	};
 
-    fixture.init();
-    fixture.stream1_->read([] (auto code, auto message) {
-        BOOST_TEST(!code);
-        BOOST_TEST(message.is_object());
-        BOOST_TEST(message["abc"].template get<int>() == 123);
-        BOOST_TEST(message["def"].template get<int>() == 456);
-    });
-    fixture.stream2_->write(message, [] (auto code) {
-        BOOST_TEST(!code);
-    });
-    fixture.service_.run();
+	fixture.init();
+	fixture.stream1_->read([] (auto code, auto message) {
+		BOOST_TEST(!code);
+		BOOST_TEST(message.is_object());
+		BOOST_TEST(message["abc"].template get<int>() == 123);
+		BOOST_TEST(message["def"].template get<int>() == 456);
+	});
+	fixture.stream2_->write(message, [] (auto code) {
+		BOOST_TEST(!code);
+	});
+	fixture.service_.run();
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(network_down, Test, list)
 {
-    Test fixture;
+	Test fixture;
 
-    fixture.init();
-    fixture.stream1_->read([] (auto code, auto message) {
-        BOOST_TEST(code.value() == static_cast<int>(std::errc::not_connected));
-        BOOST_TEST(message.is_null());
-    });
-    fixture.stream2_ = nullptr;
-    fixture.service_.run();
+	fixture.init();
+	fixture.stream1_->read([] (auto code, auto message) {
+		BOOST_TEST(code.value() == static_cast<int>(std::errc::not_connected));
+		BOOST_TEST(message.is_null());
+	});
+	fixture.stream2_ = nullptr;
+	fixture.service_.run();
 }
 
 } // !namespace
--- a/tests/src/libcommon/string-util/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/string-util/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME string-util
-    SOURCES main.cpp
-    LIBRARIES libirccd-core
+	NAME string-util
+	SOURCES main.cpp
+	LIBRARIES libirccd-core
 )
--- a/tests/src/libcommon/string-util/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libcommon/string-util/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,122 +34,122 @@
 
 BOOST_AUTO_TEST_CASE(nothing)
 {
-    std::string expected = "hello world!";
-    std::string result = string_util::format("hello world!");
+	std::string expected = "hello world!";
+	std::string result = string_util::format("hello world!");
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(escape)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.keywords.emplace("target", "hello");
+	params.keywords.emplace("target", "hello");
 
-    BOOST_TEST(string_util::format("$@#") == "$@#");
-    BOOST_TEST(string_util::format(" $ @ # ") == " $ @ # ");
-    BOOST_TEST(string_util::format("#") == "#");
-    BOOST_TEST(string_util::format(" # ") == " # ");
-    BOOST_TEST(string_util::format("#@") == "#@");
-    BOOST_TEST(string_util::format("##") == "##");
-    BOOST_TEST(string_util::format("#!") == "#!");
-    BOOST_TEST(string_util::format("##{target}") == "#{target}");
-    BOOST_TEST(string_util::format("@#{target}", params) == "@hello");
-    BOOST_TEST(string_util::format("#{target}#", params) == "hello#");
-    BOOST_REQUIRE_THROW(string_util::format("#{failure"), std::exception);
+	BOOST_TEST(string_util::format("$@#") == "$@#");
+	BOOST_TEST(string_util::format(" $ @ # ") == " $ @ # ");
+	BOOST_TEST(string_util::format("#") == "#");
+	BOOST_TEST(string_util::format(" # ") == " # ");
+	BOOST_TEST(string_util::format("#@") == "#@");
+	BOOST_TEST(string_util::format("##") == "##");
+	BOOST_TEST(string_util::format("#!") == "#!");
+	BOOST_TEST(string_util::format("##{target}") == "#{target}");
+	BOOST_TEST(string_util::format("@#{target}", params) == "@hello");
+	BOOST_TEST(string_util::format("#{target}#", params) == "hello#");
+	BOOST_REQUIRE_THROW(string_util::format("#{failure"), std::exception);
 }
 
 BOOST_AUTO_TEST_CASE(disable_date)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.flags &= ~(string_util::subst_flags::date);
+	params.flags &= ~(string_util::subst_flags::date);
 
-    BOOST_TEST(string_util::format("%H:%M", params) == "%H:%M");
+	BOOST_TEST(string_util::format("%H:%M", params) == "%H:%M");
 }
 
 BOOST_AUTO_TEST_CASE(disable_keywords)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.keywords.emplace("target", "hello");
-    params.flags &= ~(string_util::subst_flags::keywords);
+	params.keywords.emplace("target", "hello");
+	params.flags &= ~(string_util::subst_flags::keywords);
 
-    BOOST_TEST(string_util::format("#{target}", params) == "#{target}");
+	BOOST_TEST(string_util::format("#{target}", params) == "#{target}");
 }
 
 BOOST_AUTO_TEST_CASE(disable_env)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.flags &= ~(string_util::subst_flags::env);
+	params.flags &= ~(string_util::subst_flags::env);
 
-    BOOST_TEST(string_util::format("${HOME}", params) == "${HOME}");
+	BOOST_TEST(string_util::format("${HOME}", params) == "${HOME}");
 }
 
 BOOST_AUTO_TEST_CASE(keyword_simple)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.keywords.insert({"target", "irccd"});
+	params.keywords.insert({"target", "irccd"});
 
-    std::string expected = "hello irccd!";
-    std::string result = string_util::format("hello #{target}!", params);
+	std::string expected = "hello irccd!";
+	std::string result = string_util::format("hello #{target}!", params);
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(keyword_multiple)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.keywords.insert({"target", "irccd"});
-    params.keywords.insert({"source", "nightmare"});
+	params.keywords.insert({"target", "irccd"});
+	params.keywords.insert({"source", "nightmare"});
 
-    std::string expected = "hello irccd from nightmare!";
-    std::string result = string_util::format("hello #{target} from #{source}!", params);
+	std::string expected = "hello irccd from nightmare!";
+	std::string result = string_util::format("hello #{target} from #{source}!", params);
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(keyword_adj_twice)
 {
-    string_util::subst params;
+	string_util::subst params;
 
-    params.keywords.insert({"target", "irccd"});
+	params.keywords.insert({"target", "irccd"});
 
-    std::string expected = "hello irccdirccd!";
-    std::string result = string_util::format("hello #{target}#{target}!", params);
+	std::string expected = "hello irccdirccd!";
+	std::string result = string_util::format("hello #{target}#{target}!", params);
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(keyword_missing)
 {
-    std::string expected = "hello !";
-    std::string result = string_util::format("hello #{target}!");
+	std::string expected = "hello !";
+	std::string result = string_util::format("hello #{target}!");
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(env_simple)
 {
-    std::string home = sys::env("HOME");
+	std::string home = sys::env("HOME");
 
-    if (!home.empty()) {
-        std::string expected = "my home is " + home;
-        std::string result = string_util::format("my home is ${HOME}");
+	if (!home.empty()) {
+		std::string expected = "my home is " + home;
+		std::string result = string_util::format("my home is ${HOME}");
 
-        BOOST_TEST(expected == result);
-    }
+		BOOST_TEST(expected == result);
+	}
 }
 
 BOOST_AUTO_TEST_CASE(env_missing)
 {
-    std::string expected = "value is ";
-    std::string result = string_util::format("value is ${HOPE_THIS_VAR_NOT_EXIST}");
+	std::string expected = "value is ";
+	std::string result = string_util::format("value is ${HOPE_THIS_VAR_NOT_EXIST}");
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -165,18 +165,18 @@
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    list expected { "a", "b" };
-    list result = string_util::split("a;b", ";");
+	list expected { "a", "b" };
+	list result = string_util::split("a;b", ";");
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(cut)
 {
-    list expected { "msg", "#staff", "foo bar baz" };
-    list result = string_util::split("msg;#staff;foo bar baz", ";", 3);
+	list expected { "msg", "#staff", "foo bar baz" };
+	list result = string_util::split("msg;#staff;foo bar baz", ";", 3);
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -190,74 +190,74 @@
 
 BOOST_AUTO_TEST_CASE(left)
 {
-    std::string value = "   123";
-    std::string result = string_util::strip(value);
+	std::string value = "   123";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "123");
+	BOOST_TEST(result == "123");
 }
 
 BOOST_AUTO_TEST_CASE(right)
 {
-    std::string value = "123   ";
-    std::string result = string_util::strip(value);
+	std::string value = "123   ";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "123");
+	BOOST_TEST(result == "123");
 }
 
 BOOST_AUTO_TEST_CASE(both)
 {
-    std::string value = "   123   ";
-    std::string result = string_util::strip(value);
+	std::string value = "   123   ";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "123");
+	BOOST_TEST(result == "123");
 }
 
 BOOST_AUTO_TEST_CASE(none)
 {
-    std::string value = "without";
-    std::string result = string_util::strip(value);
+	std::string value = "without";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "without");
+	BOOST_TEST(result == "without");
 }
 
 BOOST_AUTO_TEST_CASE(between_empty)
 {
-    std::string value = "one list";
-    std::string result = string_util::strip(value);
+	std::string value = "one list";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "one list");
+	BOOST_TEST(result == "one list");
 }
 
 BOOST_AUTO_TEST_CASE(between_left)
 {
-    std::string value = "  space at left";
-    std::string result = string_util::strip(value);
+	std::string value = "  space at left";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "space at left");
+	BOOST_TEST(result == "space at left");
 }
 
 BOOST_AUTO_TEST_CASE(between_right)
 {
-    std::string value = "space at right  ";
-    std::string result = string_util::strip(value);
+	std::string value = "space at right  ";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "space at right");
+	BOOST_TEST(result == "space at right");
 }
 
 BOOST_AUTO_TEST_CASE(between_both)
 {
-    std::string value = "  space at both  ";
-    std::string result = string_util::strip(value);
+	std::string value = "  space at both  ";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "space at both");
+	BOOST_TEST(result == "space at both");
 }
 
 BOOST_AUTO_TEST_CASE(empty)
 {
-    std::string value = "    ";
-    std::string result = string_util::strip(value);
+	std::string value = "    ";
+	std::string result = string_util::strip(value);
 
-    BOOST_TEST(result == "");
+	BOOST_TEST(result == "");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -271,42 +271,42 @@
 
 BOOST_AUTO_TEST_CASE(empty)
 {
-    std::string expected = "";
-    std::string result = string_util::join<int>({});
+	std::string expected = "";
+	std::string result = string_util::join<int>({});
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(one)
 {
-    std::string expected = "1";
-    std::string result = string_util::join({1});
+	std::string expected = "1";
+	std::string result = string_util::join({1});
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(two)
 {
-    std::string expected = "1:2";
-    std::string result = string_util::join({1, 2});
+	std::string expected = "1:2";
+	std::string result = string_util::join({1, 2});
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(delimiter_string)
 {
-    std::string expected = "1;;2;;3";
-    std::string result = string_util::join({1, 2, 3}, ";;");
+	std::string expected = "1;;2;;3";
+	std::string result = string_util::join({1, 2, 3}, ";;");
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_CASE(delimiter_char)
 {
-    std::string expected = "1@2@3@4";
-    std::string result = string_util::join({1, 2, 3, 4}, '@');
+	std::string expected = "1@2@3@4";
+	std::string result = string_util::join({1, 2, 3, 4}, '@');
 
-    BOOST_TEST(expected == result);
+	BOOST_TEST(expected == result);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -320,20 +320,20 @@
 
 BOOST_AUTO_TEST_CASE(correct)
 {
-    BOOST_TEST(string_util::is_identifier("localhost"));
-    BOOST_TEST(string_util::is_identifier("localhost2"));
-    BOOST_TEST(string_util::is_identifier("localhost2-4_"));
+	BOOST_TEST(string_util::is_identifier("localhost"));
+	BOOST_TEST(string_util::is_identifier("localhost2"));
+	BOOST_TEST(string_util::is_identifier("localhost2-4_"));
 }
 
 BOOST_AUTO_TEST_CASE(incorrect)
 {
-    BOOST_TEST(!string_util::is_identifier(""));
-    BOOST_TEST(!string_util::is_identifier("localhost with spaces"));
-    BOOST_TEST(!string_util::is_identifier("localhost*"));
-    BOOST_TEST(!string_util::is_identifier("&&"));
-    BOOST_TEST(!string_util::is_identifier("@'"));
-    BOOST_TEST(!string_util::is_identifier("##"));
-    BOOST_TEST(!string_util::is_identifier("===++"));
+	BOOST_TEST(!string_util::is_identifier(""));
+	BOOST_TEST(!string_util::is_identifier("localhost with spaces"));
+	BOOST_TEST(!string_util::is_identifier("localhost*"));
+	BOOST_TEST(!string_util::is_identifier("&&"));
+	BOOST_TEST(!string_util::is_identifier("@'"));
+	BOOST_TEST(!string_util::is_identifier("##"));
+	BOOST_TEST(!string_util::is_identifier("===++"));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -347,34 +347,34 @@
 
 BOOST_AUTO_TEST_CASE(correct)
 {
-    // true
-    BOOST_TEST(string_util::is_boolean("true"));
-    BOOST_TEST(string_util::is_boolean("True"));
-    BOOST_TEST(string_util::is_boolean("TRUE"));
-    BOOST_TEST(string_util::is_boolean("TruE"));
+	// true
+	BOOST_TEST(string_util::is_boolean("true"));
+	BOOST_TEST(string_util::is_boolean("True"));
+	BOOST_TEST(string_util::is_boolean("TRUE"));
+	BOOST_TEST(string_util::is_boolean("TruE"));
 
-    // yes
-    BOOST_TEST(string_util::is_boolean("yes"));
-    BOOST_TEST(string_util::is_boolean("Yes"));
-    BOOST_TEST(string_util::is_boolean("YES"));
-    BOOST_TEST(string_util::is_boolean("YeS"));
+	// yes
+	BOOST_TEST(string_util::is_boolean("yes"));
+	BOOST_TEST(string_util::is_boolean("Yes"));
+	BOOST_TEST(string_util::is_boolean("YES"));
+	BOOST_TEST(string_util::is_boolean("YeS"));
 
-    // on
-    BOOST_TEST(string_util::is_boolean("on"));
-    BOOST_TEST(string_util::is_boolean("On"));
-    BOOST_TEST(string_util::is_boolean("oN"));
-    BOOST_TEST(string_util::is_boolean("ON"));
+	// on
+	BOOST_TEST(string_util::is_boolean("on"));
+	BOOST_TEST(string_util::is_boolean("On"));
+	BOOST_TEST(string_util::is_boolean("oN"));
+	BOOST_TEST(string_util::is_boolean("ON"));
 
-    // 1
-    BOOST_TEST(string_util::is_boolean("1"));
+	// 1
+	BOOST_TEST(string_util::is_boolean("1"));
 }
 
 BOOST_AUTO_TEST_CASE(incorrect)
 {
-    BOOST_TEST(!string_util::is_boolean("false"));
-    BOOST_TEST(!string_util::is_boolean("lol"));
-    BOOST_TEST(!string_util::is_boolean(""));
-    BOOST_TEST(!string_util::is_boolean("0"));
+	BOOST_TEST(!string_util::is_boolean("false"));
+	BOOST_TEST(!string_util::is_boolean("lol"));
+	BOOST_TEST(!string_util::is_boolean(""));
+	BOOST_TEST(!string_util::is_boolean("0"));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-directory/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-directory/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-directory
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-directory
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-directory/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-directory/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,28 +30,28 @@
 
 class directory_js_fixture : public js_fixture {
 public:
-    directory_js_fixture()
-    {
-        duk::push(plugin_->get_context(), CMAKE_SOURCE_DIR);
-        duk_put_global_string(plugin_->get_context(), "CMAKE_SOURCE_DIR");
-    }
+	directory_js_fixture()
+	{
+		duk::push(plugin_->get_context(), CMAKE_SOURCE_DIR);
+		duk_put_global_string(plugin_->get_context(), "CMAKE_SOURCE_DIR");
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(directory_js_api_suite, directory_js_fixture)
 
 BOOST_AUTO_TEST_CASE(constructor)
 {
-    const std::string script(
-        "d = new Irccd.Directory(CMAKE_SOURCE_DIR + \"/tests/root\");"
-        "p = d.path;"
-        "l = d.entries.length;"
-    );
+	const std::string script(
+		"d = new Irccd.Directory(CMAKE_SOURCE_DIR + \"/tests/root\");"
+		"p = d.path;"
+		"l = d.entries.length;"
+	);
 
-    if (duk_peval_string(plugin_->get_context(), script.c_str()) != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), script.c_str()) != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    duk_get_global_string(plugin_->get_context(), "l");
-    BOOST_TEST(duk_get_int(plugin_->get_context(), -1) == 3);
+	duk_get_global_string(plugin_->get_context(), "l");
+	BOOST_TEST(duk_get_int(plugin_->get_context(), -1) == 3);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-elapsedtimer/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-elapsedtimer/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-elapsedtimer
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-elapsedtimer
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-elapsedtimer/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-elapsedtimer/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -36,17 +36,17 @@
 
 BOOST_AUTO_TEST_CASE(standard)
 {
-    if (duk_peval_string(plugin_->get_context(), "timer = new Irccd.ElapsedTimer();") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "timer = new Irccd.ElapsedTimer();") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    std::this_thread::sleep_for(300ms);
+	std::this_thread::sleep_for(300ms);
 
-    if (duk_peval_string(plugin_->get_context(), "result = timer.elapsed();") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = timer.elapsed();") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_REQUIRE(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_REQUIRE_GE(duk_get_int(plugin_->get_context(), -1), 250);
-    BOOST_REQUIRE_LE(duk_get_int(plugin_->get_context(), -1), 350);
+	BOOST_REQUIRE(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_REQUIRE_GE(duk_get_int(plugin_->get_context(), -1), 250);
+	BOOST_REQUIRE_LE(duk_get_int(plugin_->get_context(), -1), 350);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-file/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-file/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-file
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-file
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-file/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-file/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,286 +32,286 @@
 
 class file_js_fixture : public js_fixture {
 public:
-    file_js_fixture()
-    {
-        duk::push(plugin_->get_context(), CMAKE_SOURCE_DIR);
-        duk_put_global_string(plugin_->get_context(), "CMAKE_SOURCE_DIR");
-    }
+	file_js_fixture()
+	{
+		duk::push(plugin_->get_context(), CMAKE_SOURCE_DIR);
+		duk_put_global_string(plugin_->get_context(), "CMAKE_SOURCE_DIR");
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(file_js_api_suite, file_js_fixture)
 
 BOOST_AUTO_TEST_CASE(function_basename)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.basename('/usr/local/etc/irccd.conf');"))
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.basename('/usr/local/etc/irccd.conf');"))
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("irccd.conf" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("irccd.conf" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(function_dirname)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.dirname('/usr/local/etc/irccd.conf');"))
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.dirname('/usr/local/etc/irccd.conf');"))
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("/usr/local/etc" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("/usr/local/etc" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(function_exists)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.exists(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt')"))
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.exists(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt')"))
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(function_exists2)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.exists('file_which_does_not_exist.txt')"))
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.File.exists('file_which_does_not_exist.txt')"))
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(function_remove)
 {
-    // First create a dummy file
-    std::ofstream("test-js-fs.remove");
+	// First create a dummy file
+	std::ofstream("test-js-fs.remove");
 
-    if (duk_peval_string(plugin_->get_context(), "Irccd.File.remove('test-js-fs.remove');") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "Irccd.File.remove('test-js-fs.remove');") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    std::ifstream in("test-js-fs.remove");
+	std::ifstream in("test-js-fs.remove");
 
-    BOOST_TEST(!in.is_open());
+	BOOST_TEST(!in.is_open());
 }
 
 BOOST_AUTO_TEST_CASE(method_basename)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "result = f.basename();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"result = f.basename();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("file-1.txt" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("file-1.txt" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_basename_closed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.close();"
-        "result = f.basename();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.close();"
+		"result = f.basename();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("file-1.txt" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("file-1.txt" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_dirname)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "result = f.dirname();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"result = f.dirname();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(CMAKE_SOURCE_DIR "/tests/root" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(CMAKE_SOURCE_DIR "/tests/root" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_dirname_closed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.close();"
-        "result = f.dirname();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.close();"
+		"result = f.dirname();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(CMAKE_SOURCE_DIR "/tests/root" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(CMAKE_SOURCE_DIR "/tests/root" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_lines)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "result = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r').lines();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"result = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r').lines();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    std::vector<std::string> expected{"a", "b", "c"};
+	std::vector<std::string> expected{"a", "b", "c"};
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek1)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.seek(Irccd.File.SeekSet, 6);"
-        "result = f.read(1);"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.seek(Irccd.File.SeekSet, 6);"
+		"result = f.read(1);"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(".", duk::get<std::string>(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(".", duk::get<std::string>(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek1_closed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.close();"
-        "f.seek(Irccd.File.SeekSet, 4);"
-        "result = f.read(1);"
-        "result = typeof (result) === \"undefined\";"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.close();"
+		"f.seek(Irccd.File.SeekSet, 4);"
+		"result = f.read(1);"
+		"result = typeof (result) === \"undefined\";"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek2)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.seek(Irccd.File.SeekSet, 2);"
-        "f.seek(Irccd.File.SeekCur, 4);"
-        "result = f.read(1);"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.seek(Irccd.File.SeekSet, 2);"
+		"f.seek(Irccd.File.SeekCur, 4);"
+		"result = f.read(1);"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("." == duk::get<std::string>(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("." == duk::get<std::string>(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek2c_losed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.close();"
-        "f.seek(Irccd.File.SeekSet, 2);"
-        "f.seek(Irccd.File.SeekCur, 2);"
-        "result = f.read(1);"
-        "result = typeof (result) === \"undefined\";"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.close();"
+		"f.seek(Irccd.File.SeekSet, 2);"
+		"f.seek(Irccd.File.SeekCur, 2);"
+		"result = f.read(1);"
+		"result = typeof (result) === \"undefined\";"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek3)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.seek(Irccd.File.SeekEnd, -2);"
-        "result = f.read(1);"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.seek(Irccd.File.SeekEnd, -2);"
+		"result = f.read(1);"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("t" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("t" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_seek3_closed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "f.close();"
-        "f.seek(Irccd.File.SeekEnd, -2);"
-        "result = f.read(1);"
-        "result = typeof (result) === \"undefined\";"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"f.close();"
+		"f.seek(Irccd.File.SeekEnd, -2);"
+		"result = f.read(1);"
+		"result = typeof (result) === \"undefined\";"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_read1)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
-        "result = f.read();"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/file-1.txt', 'r');"
+		"result = f.read();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST("file-1.txt\n" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST("file-1.txt\n" == duk_get_string(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_readline)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "result = [];"
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r');"
-        "for (var s; s = f.readline(); ) {"
-        "  result.push(s);"
-        "}"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"result = [];"
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r');"
+		"for (var s; s = f.readline(); ) {"
+		"  result.push(s);"
+		"}"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    std::vector<std::string> expected{"a", "b", "c"};
+	std::vector<std::string> expected{"a", "b", "c"};
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(method_readline_closed)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "result = [];"
-        "f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r');"
-        "f.close();"
-        "for (var s; s = f.readline(); ) {"
-        "  result.push(s);"
-        "}"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"result = [];"
+		"f = new Irccd.File(CMAKE_SOURCE_DIR + '/tests/root/lines.txt', 'r');"
+		"f.close();"
+		"for (var s; s = f.readline(); ) {"
+		"  result.push(s);"
+		"}"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    std::vector<std::string> expected;
+	std::vector<std::string> expected;
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(expected == duk::get<std::vector<std::string>>(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-irccd/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-irccd/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-irccd
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-irccd
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-irccd/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-irccd/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,84 +32,84 @@
 
 BOOST_AUTO_TEST_CASE(version)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "major = Irccd.version.major;"
-        "minor = Irccd.version.minor;"
-        "patch = Irccd.version.patch;"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"major = Irccd.version.major;"
+		"minor = Irccd.version.minor;"
+		"patch = Irccd.version.patch;"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "major"));
-    BOOST_TEST(IRCCD_VERSION_MAJOR == duk_get_int(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "minor"));
-    BOOST_TEST(IRCCD_VERSION_MINOR == duk_get_int(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "patch"));
-    BOOST_TEST(IRCCD_VERSION_PATCH == duk_get_int(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "major"));
+	BOOST_TEST(IRCCD_VERSION_MAJOR == duk_get_int(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "minor"));
+	BOOST_TEST(IRCCD_VERSION_MINOR == duk_get_int(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "patch"));
+	BOOST_TEST(IRCCD_VERSION_PATCH == duk_get_int(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(from_javascript)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {"
-        "  throw new Irccd.SystemError(1, 'test');"
-        "} catch (e) {"
-        "  errno = e.errno;"
-        "  name = e.name;"
-        "  message = e.message;"
-        "  v1 = (e instanceof Error);"
-        "  v2 = (e instanceof Irccd.SystemError);"
-        "}"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {"
+		"  throw new Irccd.SystemError(1, 'test');"
+		"} catch (e) {"
+		"  errno = e.errno;"
+		"  name = e.name;"
+		"  message = e.message;"
+		"  v1 = (e instanceof Error);"
+		"  v2 = (e instanceof Irccd.SystemError);"
+		"}"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "errno"));
-    BOOST_TEST(1 == duk_get_int(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST("SystemError" == duk_get_string(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
-    BOOST_TEST("test" == duk_get_string(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v1"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v2"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "errno"));
+	BOOST_TEST(1 == duk_get_int(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST("SystemError" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
+	BOOST_TEST("test" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v1"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v2"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(from_native)
 {
-    duk_push_c_function(plugin_->get_context(), [] (duk_context *ctx) -> duk_ret_t {
-        duk::raise(ctx, std::system_error(make_error_code(std::errc::invalid_argument)));
+	duk_push_c_function(plugin_->get_context(), [] (duk_context *ctx) -> duk_ret_t {
+		duk::raise(ctx, std::system_error(make_error_code(std::errc::invalid_argument)));
 
-        return 0;
-    }, 0);
+		return 0;
+	}, 0);
 
-    duk_put_global_string(plugin_->get_context(), "f");
+	duk_put_global_string(plugin_->get_context(), "f");
 
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {"
-        "  f();"
-        "} catch (e) {"
-        "  errno = e.errno;"
-        "  name = e.name;"
-        "  v1 = (e instanceof Error);"
-        "  v2 = (e instanceof Irccd.SystemError);"
-        "}"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {"
+		"  f();"
+		"} catch (e) {"
+		"  errno = e.errno;"
+		"  name = e.name;"
+		"  v1 = (e instanceof Error);"
+		"  v2 = (e instanceof Irccd.SystemError);"
+		"}"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "errno"));
-    BOOST_TEST(EINVAL == duk_get_int(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST("SystemError" == duk_get_string(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v1"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v2"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "errno"));
+	BOOST_TEST(EINVAL == duk_get_int(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST("SystemError" == duk_get_string(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v1"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "v2"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-logger/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-logger/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-logger
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-logger
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-logger/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-logger/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,69 +32,69 @@
 
 class logger_fixture : public js_fixture {
 protected:
-    std::string line_info;
-    std::string line_warning;
-    std::string line_debug;
+	std::string line_info;
+	std::string line_warning;
+	std::string line_debug;
 
-    class sample_sink : public logger::sink {
-    private:
-        logger_fixture& test_;
+	class sample_sink : public logger::sink {
+	private:
+		logger_fixture& test_;
 
-    public:
-        sample_sink(logger_fixture& test) noexcept
-            : test_(test)
-        {
-        }
+	public:
+		sample_sink(logger_fixture& test) noexcept
+			: test_(test)
+		{
+		}
 
-        void write_info(const std::string& line) override
-        {
-            test_.line_info = line;
-        }
+		void write_info(const std::string& line) override
+		{
+			test_.line_info = line;
+		}
 
-        void write_warning(const std::string& line) override
-        {
-            test_.line_warning = line;
-        }
+		void write_warning(const std::string& line) override
+		{
+			test_.line_warning = line;
+		}
 
-        void write_debug(const std::string& line) override
-        {
-            test_.line_debug = line;
-        }
-    };
+		void write_debug(const std::string& line) override
+		{
+			test_.line_debug = line;
+		}
+	};
 
-    logger_fixture()
-    {
-        irccd_.set_log(std::make_unique<sample_sink>(*this));
-        irccd_.get_log().set_verbose(true);
-    }
+	logger_fixture()
+	{
+		irccd_.set_log(std::make_unique<sample_sink>(*this));
+		irccd_.get_log().set_verbose(true);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(logger_js_api_suite, logger_fixture)
 
 BOOST_AUTO_TEST_CASE(info)
 {
-    if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.info(\"hello!\");") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.info(\"hello!\");") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST("plugin test: hello!" == line_info);
+	BOOST_TEST("plugin test: hello!" == line_info);
 }
 
 BOOST_AUTO_TEST_CASE(warning)
 {
-    if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.warning(\"FAIL!\");") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.warning(\"FAIL!\");") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST("plugin test: FAIL!" == line_warning);
+	BOOST_TEST("plugin test: FAIL!" == line_warning);
 }
 
 #if !defined(NDEBUG)
 
 BOOST_AUTO_TEST_CASE(debug)
 {
-    if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.debug(\"starting\");") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "Irccd.Logger.debug(\"starting\");") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST("plugin test: starting" == line_debug);
+	BOOST_TEST("plugin test: starting" == line_debug);
 }
 
 #endif
--- a/tests/src/libirccd-js/js-api-system/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-system/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME js-api-system
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
-    FLAGS IRCCD_EXECUTABLE=\"$<TARGET_FILE:irccd>\"
+	NAME js-api-system
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
+	FLAGS IRCCD_EXECUTABLE=\"$<TARGET_FILE:irccd>\"
 )
--- a/tests/src/libirccd-js/js-api-system/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-system/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,26 +34,26 @@
 
 BOOST_AUTO_TEST_CASE(home)
 {
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.System.home();");
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.System.home();");
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(),"result"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == sys::home());
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(),"result"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == sys::home());
 }
 
 #if defined(IRCCD_HAVE_POPEN)
 
 BOOST_AUTO_TEST_CASE(popen)
 {
-    auto ret = duk_peval_string(plugin_->get_context(),
-        "f = Irccd.System.popen(\"" IRCCD_EXECUTABLE " --version\", \"r\");"
-        "r = f.readline();"
-    );
+	auto ret = duk_peval_string(plugin_->get_context(),
+		"f = Irccd.System.popen(\"" IRCCD_EXECUTABLE " --version\", \"r\");"
+		"r = f.readline();"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "r"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == IRCCD_VERSION);
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "r"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == IRCCD_VERSION);
 }
 
 #endif
--- a/tests/src/libirccd-js/js-api-timer/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-timer/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-timer
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-timer
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-timer/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-timer/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,54 +30,54 @@
 
 class js_timer_fixture : public js_fixture {
 public:
-    js_timer_fixture()
-        : js_fixture(CMAKE_CURRENT_SOURCE_DIR "/timer.js")
-    {
-    }
+	js_timer_fixture()
+		: js_fixture(CMAKE_CURRENT_SOURCE_DIR "/timer.js")
+	{
+	}
 
-    void set_type(const std::string& name)
-    {
-        duk_get_global_string(plugin_->get_context(), "Irccd");
-        duk_get_prop_string(plugin_->get_context(), -1, "Timer");
-        duk_get_prop_string(plugin_->get_context(), -1, name.c_str());
-        duk_put_global_string(plugin_->get_context(), "type");
-        duk_pop_n(plugin_->get_context(), 2);
+	void set_type(const std::string& name)
+	{
+		duk_get_global_string(plugin_->get_context(), "Irccd");
+		duk_get_prop_string(plugin_->get_context(), -1, "Timer");
+		duk_get_prop_string(plugin_->get_context(), -1, name.c_str());
+		duk_put_global_string(plugin_->get_context(), "type");
+		duk_pop_n(plugin_->get_context(), 2);
 
-        plugin_->open();
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->open();
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(js_timer_api_suite, js_timer_fixture)
 
 BOOST_AUTO_TEST_CASE(single)
 {
-    boost::timer::cpu_timer timer;
+	boost::timer::cpu_timer timer;
 
-    set_type("Single");
+	set_type("Single");
 
-    while (timer.elapsed().wall / 1000000LL < 3000) {
-        ctx_.reset();
-        ctx_.poll();
-    }
+	while (timer.elapsed().wall / 1000000LL < 3000) {
+		ctx_.reset();
+		ctx_.poll();
+	}
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "count"));
-    BOOST_TEST(duk_get_int(plugin_->get_context(), -1) == 1);
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "count"));
+	BOOST_TEST(duk_get_int(plugin_->get_context(), -1) == 1);
 }
 
 BOOST_AUTO_TEST_CASE(repeat)
 {
-    boost::timer::cpu_timer timer;
+	boost::timer::cpu_timer timer;
 
-    set_type("Repeat");
+	set_type("Repeat");
 
-    while (timer.elapsed().wall / 1000000LL < 3000) {
-        ctx_.reset();
-        ctx_.poll();
-    }
+	while (timer.elapsed().wall / 1000000LL < 3000) {
+		ctx_.reset();
+		ctx_.poll();
+	}
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "count"));
-    BOOST_TEST(duk_get_int(plugin_->get_context(), -1) >= 5);
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "count"));
+	BOOST_TEST(duk_get_int(plugin_->get_context(), -1) >= 5);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-timer/timer.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-timer/timer.js	Fri Oct 26 13:01:00 2018 +0200
@@ -2,12 +2,12 @@
 
 function onLoad()
 {
-    if (typeof (type) === "undefined")
-        throw Error("global timer type not defined");
+	if (typeof (type) === "undefined")
+		throw Error("global timer type not defined");
 
-    t = new Irccd.Timer(type, 50, function () {
-        count += 1;
-    });
+	t = new Irccd.Timer(type, 50, function () {
+		count += 1;
+	});
 
-    t.start();
+	t.start();
 }
--- a/tests/src/libirccd-js/js-api-unicode/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-unicode/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-unicode
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-unicode
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-unicode/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-unicode/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -35,35 +35,35 @@
 
 BOOST_AUTO_TEST_CASE(is_letter)
 {
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLetter(String('é').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLetter(String('é').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLetter(String('€').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLetter(String('€').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(is_lower)
 {
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLower(String('é').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLower(String('é').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLower(String('É').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isLower(String('É').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(is_upper)
 {
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isUpper(String('É').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isUpper(String('É').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_boolean(plugin_->get_context(), -1));
 
-    duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isUpper(String('é').charCodeAt(0));");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
+	duk_peval_string_noresult(plugin_->get_context(), "result = Irccd.Unicode.isUpper(String('é').charCodeAt(0));");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(!duk_get_boolean(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-api-util/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-util/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-api-util
-    SOURCES main.cpp
-    LIBRARIES libirccd-js
+	NAME js-api-util
+	SOURCES main.cpp
+	LIBRARIES libirccd-js
 )
--- a/tests/src/libirccd-js/js-api-util/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-api-util/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -37,33 +37,33 @@
 
 BOOST_AUTO_TEST_CASE(format_simple)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "result = Irccd.Util.format(\"#{target}\", { target: \"markand\" })"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"result = Irccd.Util.format(\"#{target}\", { target: \"markand\" })"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "markand");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "markand");
 }
 
 BOOST_AUTO_TEST_CASE(splituser)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.Util.splituser(\"user!~user@hyper/super/host\");") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.Util.splituser(\"user!~user@hyper/super/host\");") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "user");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "user");
 }
 
 BOOST_AUTO_TEST_CASE(splithost)
 {
-    if (duk_peval_string(plugin_->get_context(), "result = Irccd.Util.splithost(\"user!~user@hyper/super/host\");") != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (duk_peval_string(plugin_->get_context(), "result = Irccd.Util.splithost(\"user!~user@hyper/super/host\");") != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "~user@hyper/super/host");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "result"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "~user@hyper/super/host");
 }
 
 /*
@@ -73,189 +73,189 @@
 
 BOOST_AUTO_TEST_CASE(cut_string_simple)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut('hello world');\n"
-        "line0 = lines[0];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut('hello world');\n"
+		"line0 = lines[0];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_double)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut('hello world', 5);\n"
-        "line0 = lines[0];\n"
-        "line1 = lines[1];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut('hello world', 5);\n"
+		"line0 = lines[0];\n"
+		"line1 = lines[1];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_dirty)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut('     hello    world     ', 5);\n"
-        "line0 = lines[0];\n"
-        "line1 = lines[1];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut('	 hello	world	 ', 5);\n"
+		"line0 = lines[0];\n"
+		"line1 = lines[1];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_too_much_lines)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut('abc def ghi jkl', 3, 3);\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut('abc def ghi jkl', 3, 3);\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "lines"));
-    BOOST_TEST(duk_is_undefined(plugin_->get_context(), -1));
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "lines"));
+	BOOST_TEST(duk_is_undefined(plugin_->get_context(), -1));
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_token_too_big)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {\n"
-        "  lines = Irccd.Util.cut('hello world', 3);\n"
-        "} catch (e) {\n"
-        "  name = e.name;\n"
-        "  message = e.message;\n"
-        "}\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {\n"
+		"  lines = Irccd.Util.cut('hello world', 3);\n"
+		"} catch (e) {\n"
+		"  name = e.name;\n"
+		"  message = e.message;\n"
+		"}\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "word 'hello' could not fit in maxc limit (3)");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "word 'hello' could not fit in maxc limit (3)");
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_negative_maxc)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {\n"
-        "  lines = Irccd.Util.cut('hello world', -3);\n"
-        "} catch (e) {\n"
-        "  name = e.name;\n"
-        "  message = e.message;\n"
-        "}\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {\n"
+		"  lines = Irccd.Util.cut('hello world', -3);\n"
+		"} catch (e) {\n"
+		"  name = e.name;\n"
+		"  message = e.message;\n"
+		"}\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "argument 1 (maxc) must be positive");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "argument 1 (maxc) must be positive");
 }
 
 BOOST_AUTO_TEST_CASE(cut_string_negative_maxl)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {\n"
-        "  lines = Irccd.Util.cut('hello world', undefined, -1);\n"
-        "} catch (e) {\n"
-        "  name = e.name;\n"
-        "  message = e.message;\n"
-        "}\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {\n"
+		"  lines = Irccd.Util.cut('hello world', undefined, -1);\n"
+		"} catch (e) {\n"
+		"  name = e.name;\n"
+		"  message = e.message;\n"
+		"}\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "argument 2 (maxl) must be positive");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "RangeError");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "message"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "argument 2 (maxl) must be positive");
 }
 
 BOOST_AUTO_TEST_CASE(cut_array_simple)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut([ 'hello', 'world' ]);\n"
-        "line0 = lines[0];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut([ 'hello', 'world' ]);\n"
+		"line0 = lines[0];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_array_double)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut([ 'hello', 'world' ], 5);\n"
-        "line0 = lines[0];\n"
-        "line1 = lines[1];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut([ 'hello', 'world' ], 5);\n"
+		"line0 = lines[0];\n"
+		"line1 = lines[1];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_array_dirty)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "lines = Irccd.Util.cut([ '   ', ' hello  ', '  world ', '    '], 5);\n"
-        "line0 = lines[0];\n"
-        "line1 = lines[1];\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"lines = Irccd.Util.cut([ '   ', ' hello  ', '  world ', '	'], 5);\n"
+		"line0 = lines[0];\n"
+		"line1 = lines[1];\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line0"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "hello");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "line1"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "world");
 }
 
 BOOST_AUTO_TEST_CASE(cut_invalid_data)
 {
-    const auto ret = duk_peval_string(plugin_->get_context(),
-        "try {\n"
-        "  lines = Irccd.Util.cut(123);\n"
-        "} catch (e) {\n"
-        "  name = e.name;\n"
-        "  message = e.message;\n"
-        "}\n"
-    );
+	const auto ret = duk_peval_string(plugin_->get_context(),
+		"try {\n"
+		"  lines = Irccd.Util.cut(123);\n"
+		"} catch (e) {\n"
+		"  name = e.name;\n"
+		"  message = e.message;\n"
+		"}\n"
+	);
 
-    if (ret != 0)
-        throw duk::get_stack(plugin_->get_context(), -1);
+	if (ret != 0)
+		throw duk::get_stack(plugin_->get_context(), -1);
 
-    BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
-    BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "TypeError");
+	BOOST_TEST(duk_get_global_string(plugin_->get_context(), "name"));
+	BOOST_TEST(duk_get_string(plugin_->get_context(), -1) == "TypeError");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd-js/js-plugin/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-plugin/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME js-plugin
-    SOURCES main.cpp
-    LIBRARIES libirccd
+	NAME js-plugin
+	SOURCES main.cpp
+	LIBRARIES libirccd
 )
--- a/tests/src/libirccd-js/js-plugin/config-assign.js	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-plugin/config-assign.js	Fri Oct 26 13:01:00 2018 +0200
@@ -1,3 +1,3 @@
 Irccd.Plugin.config = {
-    "hard": "true"
+	"hard": "true"
 };
--- a/tests/src/libirccd-js/js-plugin/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd-js/js-plugin/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,118 +34,118 @@
 
 class js_plugin_fixture : public irccd_fixture {
 protected:
-    std::shared_ptr<js::js_plugin> plugin_;
+	std::shared_ptr<js::js_plugin> plugin_;
 
-    void load(const std::string& path)
-    {
-        plugin_ = std::make_unique<js::js_plugin>("test", path);
+	void load(const std::string& path)
+	{
+		plugin_ = std::make_unique<js::js_plugin>("test", path);
 
-        for (const auto& f : js::js_api::registry)
-            f()->load(irccd_, plugin_);
+		for (const auto& f : js::js_api::registry)
+			f()->load(irccd_, plugin_);
 
-        plugin_->open();
-    }
+		plugin_->open();
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(js_plugin_suite, js_plugin_fixture)
 
 BOOST_AUTO_TEST_CASE(assign)
 {
-    load(CMAKE_CURRENT_SOURCE_DIR "/config-assign.js");
+	load(CMAKE_CURRENT_SOURCE_DIR "/config-assign.js");
 
-    plugin_->set_options({
-        { "path",       "none"  },
-        { "verbose",    "false" }
-    });
-    plugin_->handle_load(irccd_);
+	plugin_->set_options({
+		{ "path",	   "none"  },
+		{ "verbose",	"false" }
+	});
+	plugin_->handle_load(irccd_);
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_CASE(fill)
 {
-    load(CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
+	load(CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
 
-    plugin_->set_options({
-        { "path",       "none"  },
-        { "verbose",    "false" }
-    });
-    plugin_->handle_load(irccd_);
+	plugin_->set_options({
+		{ "path",	   "none"  },
+		{ "verbose",	"false" }
+	});
+	plugin_->handle_load(irccd_);
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_CASE(merge_after)
 {
-    load(CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
+	load(CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
 
-    plugin_->handle_load(irccd_);
-    plugin_->set_options({
-        { "path",       "none"  },
-        { "verbose",    "false" }
-    });
+	plugin_->handle_load(irccd_);
+	plugin_->set_options({
+		{ "path",	   "none"  },
+		{ "verbose",	"false" }
+	});
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
 
 class js_plugin_loader_fixture : public irccd_fixture {
 protected:
-    std::shared_ptr<plugin> plugin_;
+	std::shared_ptr<plugin> plugin_;
 
-    js_plugin_loader_fixture()
-    {
-        irccd_.set_config(config(CMAKE_CURRENT_SOURCE_DIR "/irccd.conf"));
+	js_plugin_loader_fixture()
+	{
+		irccd_.set_config(config(CMAKE_CURRENT_SOURCE_DIR "/irccd.conf"));
 
-        auto loader = std::make_unique<js::js_plugin_loader>(irccd_);
+		auto loader = std::make_unique<js::js_plugin_loader>(irccd_);
 
-        for (const auto& f : js::js_api::registry)
-            loader->get_modules().push_back(f());
+		for (const auto& f : js::js_api::registry)
+			loader->get_modules().push_back(f());
 
-        irccd_.plugins().add_loader(std::move(loader));
-    }
+		irccd_.plugins().add_loader(std::move(loader));
+	}
 
-    void load(std::string name, std::string path)
-    {
-        irccd_.plugins().load(name, path);
-        plugin_ = irccd_.plugins().require(name);
-    }
+	void load(std::string name, std::string path)
+	{
+		irccd_.plugins().load(name, path);
+		plugin_ = irccd_.plugins().require(name);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(js_plugin_loader_test_suite, js_plugin_loader_fixture)
 
 BOOST_AUTO_TEST_CASE(assign)
 {
-    load("test", CMAKE_CURRENT_SOURCE_DIR "/config-assign.js");
+	load("test", CMAKE_CURRENT_SOURCE_DIR "/config-assign.js");
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_CASE(fill)
 {
-    load("test", CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
+	load("test", CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_CASE(merge_after)
 {
-    load("test", CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
+	load("test", CMAKE_CURRENT_SOURCE_DIR "/config-fill.js");
 
-    BOOST_TEST(plugin_->get_options().at("path") == "none");
-    BOOST_TEST(plugin_->get_options().at("verbose") == "false");
-    BOOST_TEST(plugin_->get_options().at("hard") == "true");
+	BOOST_TEST(plugin_->get_options().at("path") == "none");
+	BOOST_TEST(plugin_->get_options().at("verbose") == "false");
+	BOOST_TEST(plugin_->get_options().at("hard") == "true");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-config/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-config/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-plugin-config
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-plugin-config
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-plugin-config/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-config/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,86 +31,86 @@
 
 BOOST_AUTO_TEST_CASE(set)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-config" },
-        { "plugin",     "test"          },
-        { "variable",   "verbosy"       },
-        { "value",      "falsy"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-config" },
+		{ "plugin",     "test"          },
+		{ "variable",   "verbosy"       },
+		{ "value",      "falsy"         }
+	});
 
-    const auto config = irccd_.plugins().require("test")->get_options();
+	const auto config = irccd_.plugins().require("test")->get_options();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(!config.empty());
-    BOOST_TEST(config.at("verbosy") == "falsy");
+	BOOST_TEST(!code);
+	BOOST_TEST(!config.empty());
+	BOOST_TEST(config.at("verbosy") == "falsy");
 }
 
 BOOST_AUTO_TEST_CASE(get)
 {
-    auto plugin = std::make_unique<mock_plugin>("test");
+	auto plugin = std::make_unique<mock_plugin>("test");
 
-    plugin->set_options({
-        { "x1", "10" },
-        { "x2", "20" }
-    });
-    irccd_.plugins().clear();
-    irccd_.plugins().add(std::move(plugin));
+	plugin->set_options({
+		{ "x1", "10" },
+		{ "x2", "20" }
+	});
+	irccd_.plugins().clear();
+	irccd_.plugins().add(std::move(plugin));
 
-    const auto [json, code] = request({
-        { "command",    "plugin-config" },
-        { "plugin",     "test"          },
-        { "variable",   "x1"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-config" },
+		{ "plugin",     "test"          },
+		{ "variable",   "x1"            }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["variables"]["x1"].get<std::string>() == "10");
-    BOOST_TEST(json["variables"].count("x2") == 0U);
+	BOOST_TEST(!code);
+	BOOST_TEST(json["variables"]["x1"].get<std::string>() == "10");
+	BOOST_TEST(json["variables"].count("x2") == 0U);
 }
 
 BOOST_AUTO_TEST_CASE(getall)
 {
-    auto plugin = std::make_unique<mock_plugin>("test");
+	auto plugin = std::make_unique<mock_plugin>("test");
 
-    plugin->set_options({
-        { "x1", "10" },
-        { "x2", "20" }
-    });
-    irccd_.plugins().clear();
-    irccd_.plugins().add(std::move(plugin));
+	plugin->set_options({
+		{ "x1", "10" },
+		{ "x2", "20" }
+	});
+	irccd_.plugins().clear();
+	irccd_.plugins().add(std::move(plugin));
 
-    const auto [json, code] = request({
-        { "command",    "plugin-config" },
-        { "plugin",     "test"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-config" },
+		{ "plugin",     "test"          }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["variables"]["x1"].get<std::string>() == "10");
-    BOOST_TEST(json["variables"]["x2"].get<std::string>() == "20");
+	BOOST_TEST(!code);
+	BOOST_TEST(json["variables"]["x1"].get<std::string>() == "10");
+	BOOST_TEST(json["variables"]["x2"].get<std::string>() == "20");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-config" }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-config" }
+	});
 
-    BOOST_TEST(code == plugin_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-config" },
-        { "plugin",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-config" },
+		{ "plugin",     "unknown"       }
+	});
 
-    BOOST_TEST(code == plugin_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-plugin-info
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-plugin-info
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-plugin-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,41 +31,41 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-info"       },
-        { "plugin",     "test"              },
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-info"   },
+		{ "plugin",     "test"          },
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["author"].get<std::string>() == "David Demelier <markand@malikania.fr>");
-    BOOST_TEST(json["license"].get<std::string>() == "ISC");
-    BOOST_TEST(json["summary"].get<std::string>() == "mock plugin");
-    BOOST_TEST(json["version"].get<std::string>() == "1.0");
+	BOOST_TEST(!code);
+	BOOST_TEST(json["author"].get<std::string>() == "David Demelier <markand@malikania.fr>");
+	BOOST_TEST(json["license"].get<std::string>() == "ISC");
+	BOOST_TEST(json["summary"].get<std::string>() == "mock plugin");
+	BOOST_TEST(json["version"].get<std::string>() == "1.0");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-info"   }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-info" }
+	});
 
-    BOOST_TEST(code == plugin_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-info"   },
-        { "plugin",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-info"   },
+		{ "plugin",     "unknown"       }
+	});
 
-    BOOST_TEST(code == plugin_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-plugin-list
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-plugin-list
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-plugin-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,26 +29,26 @@
 
 class plugin_list_fixture : public command_fixture {
 public:
-    plugin_list_fixture()
-    {
-        irccd_.plugins().clear();
-        irccd_.plugins().add(std::make_unique<mock_plugin>("t1"));
-        irccd_.plugins().add(std::make_unique<mock_plugin>("t2"));
-    }
+	plugin_list_fixture()
+	{
+		irccd_.plugins().clear();
+		irccd_.plugins().add(std::make_unique<mock_plugin>("t1"));
+		irccd_.plugins().add(std::make_unique<mock_plugin>("t2"));
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_list_fixture_suite, plugin_list_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command", "plugin-list" }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-list" }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["list"][0].get<std::string>() == "t1");
-    BOOST_TEST(json["list"][1].get<std::string>() == "t2");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["list"][0].get<std::string>() == "t1");
+	BOOST_TEST(json["list"][1].get<std::string>() == "t2");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-load/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-load/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-plugin-load
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-plugin-load
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-plugin-load/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-load/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,73 +29,73 @@
 
 class broken : public plugin {
 public:
-    broken()
-        : plugin("broken")
-    {
-    }
+	broken()
+		: plugin("broken")
+	{
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "broken";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "broken";
+	}
 
-    void handle_load(irccd&) override
-    {
-        throw std::runtime_error("broken");
-    }
+	void handle_load(irccd&) override
+	{
+		throw std::runtime_error("broken");
+	}
 };
 
 class broken_loader : public plugin_loader {
 public:
-    broken_loader()
-        : plugin_loader({}, { ".none" })
-    {
-    }
+	broken_loader()
+		: plugin_loader({}, { ".none" })
+	{
+	}
 
-    auto open(std::string_view, std::string_view) -> std::shared_ptr<plugin> override
-    {
-        return nullptr;
-    }
+	auto open(std::string_view, std::string_view) -> std::shared_ptr<plugin> override
+	{
+		return nullptr;
+	}
 
-    auto find(std::string_view id) noexcept -> std::shared_ptr<plugin> override
-    {
-        if (id == "broken")
-            return std::make_unique<broken>();
+	auto find(std::string_view id) noexcept -> std::shared_ptr<plugin> override
+	{
+		if (id == "broken")
+			return std::make_unique<broken>();
 
-        return nullptr;
-    }
+		return nullptr;
+	}
 };
 
 class sample_loader : public plugin_loader {
 public:
-    sample_loader()
-        : plugin_loader({}, { ".none" })
-    {
-    }
+	sample_loader()
+		: plugin_loader({}, { ".none" })
+	{
+	}
 
-    auto open(std::string_view, std::string_view) -> std::shared_ptr<plugin> override
-    {
-        return nullptr;
-    }
+	auto open(std::string_view, std::string_view) -> std::shared_ptr<plugin> override
+	{
+		return nullptr;
+	}
 
-    auto find(std::string_view id) noexcept -> std::shared_ptr<plugin> override
-    {
-        if (id == "test")
-            return std::make_unique<mock_plugin>("test");
+	auto find(std::string_view id) noexcept -> std::shared_ptr<plugin> override
+	{
+		if (id == "test")
+			return std::make_unique<mock_plugin>("test");
 
-        return nullptr;
-    }
+		return nullptr;
+	}
 };
 
 class plugin_load_fixture : public command_fixture {
 public:
-    plugin_load_fixture()
-    {
-        irccd_.plugins().add_loader(std::make_unique<sample_loader>());
-        irccd_.plugins().add_loader(std::make_unique<broken_loader>());
-        irccd_.plugins().clear();
-        irccd_.plugins().add(std::make_unique<mock_plugin>("already"));
-    }
+	plugin_load_fixture()
+	{
+		irccd_.plugins().add_loader(std::make_unique<sample_loader>());
+		irccd_.plugins().add_loader(std::make_unique<broken_loader>());
+		irccd_.plugins().clear();
+		irccd_.plugins().add(std::make_unique<mock_plugin>("already"));
+	}
 };
 
 } // !namespace
@@ -104,62 +104,62 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-load"   },
-        { "plugin",     "test"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-load"   },
+		{ "plugin",     "test"          }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(irccd_.plugins().has("test"));
+	BOOST_TEST(!code);
+	BOOST_TEST(irccd_.plugins().has("test"));
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-load"   }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-load" }
+	});
 
-    BOOST_TEST(code == plugin_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-load"   },
-        { "plugin",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-load"   },
+		{ "plugin",     "unknown"       }
+	});
 
-    BOOST_TEST(code == plugin_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(already_exists)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-load"   },
-        { "plugin",     "already"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-load"   },
+		{ "plugin",     "already"       }
+	});
 
-    BOOST_TEST(code == plugin_error::already_exists);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::already_exists);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::already_exists);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::already_exists);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(exec_error)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-load"   },
-        { "plugin",     "broken"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-load"   },
+		{ "plugin",     "broken"        }
+	});
 
-    BOOST_TEST(code == plugin_error::exec_error);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::exec_error);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-reload/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-reload/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,83 +29,83 @@
 
 class broken_plugin : public plugin {
 public:
-    broken_plugin()
-        : plugin("broken")
-    {
-    }
+	broken_plugin()
+		: plugin("broken")
+	{
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "broken";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "broken";
+	}
 
-    void handle_reload(irccd&) override
-    {
-        throw std::runtime_error("broken");
-    }
+	void handle_reload(irccd&) override
+	{
+		throw std::runtime_error("broken");
+	}
 };
 
 class plugin_reload_fixture : public command_fixture {
 protected:
-    std::shared_ptr<mock_plugin> plugin_;
+	std::shared_ptr<mock_plugin> plugin_;
 
-    plugin_reload_fixture()
-        : plugin_(std::make_shared<mock_plugin>("test"))
-    {
-        irccd_.plugins().clear();
-        irccd_.plugins().add(plugin_);
-        irccd_.plugins().add(std::make_unique<broken_plugin>());
-    }
+	plugin_reload_fixture()
+		: plugin_(std::make_shared<mock_plugin>("test"))
+	{
+		irccd_.plugins().clear();
+		irccd_.plugins().add(plugin_);
+		irccd_.plugins().add(std::make_unique<broken_plugin>());
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_reload_fixture_suite, plugin_reload_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-reload" },
-        { "plugin",     "test"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-reload" },
+		{ "plugin",     "test"          }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(plugin_->find("handle_reload").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(plugin_->find("handle_reload").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-reload" }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-reload" }
+	});
 
-    BOOST_TEST(code == plugin_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-reload" },
-        { "plugin",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-reload" },
+		{ "plugin",     "unknown"       }
+	});
 
-    BOOST_TEST(code == plugin_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(exec_error)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-reload" },
-        { "plugin",     "broken"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-reload" },
+		{ "plugin",     "broken"        }
+	});
 
-    BOOST_TEST(code == plugin_error::exec_error);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::exec_error);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-plugin-unload/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-unload/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-plugin-unload
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-plugin-unload
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-plugin-unload/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-plugin-unload/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,84 +29,84 @@
 
 class broken_plugin : public plugin {
 public:
-    broken_plugin()
-        : plugin("broken")
-    {
-    }
+	broken_plugin()
+		: plugin("broken")
+	{
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "broken";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "broken";
+	}
 
-    void handle_unload(irccd&) override
-    {
-        throw std::runtime_error("broken");
-    }
+	void handle_unload(irccd&) override
+	{
+		throw std::runtime_error("broken");
+	}
 };
 
 class plugin_unload_fixture : public command_fixture {
 protected:
-    std::shared_ptr<mock_plugin> plugin_;
+	std::shared_ptr<mock_plugin> plugin_;
 
-    plugin_unload_fixture()
-        : plugin_(std::make_shared<mock_plugin>("test"))
-    {
-        irccd_.plugins().clear();
-        irccd_.plugins().add(plugin_);
-        irccd_.plugins().add(std::make_unique<broken_plugin>());
-    }
+	plugin_unload_fixture()
+		: plugin_(std::make_shared<mock_plugin>("test"))
+	{
+		irccd_.plugins().clear();
+		irccd_.plugins().add(plugin_);
+		irccd_.plugins().add(std::make_unique<broken_plugin>());
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(plugin_unload_fixture_suite, plugin_unload_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-unload" },
-        { "plugin",     "test"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-unload" },
+		{ "plugin",     "test"          }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(plugin_->find("handle_unload").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(plugin_->find("handle_unload").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-unload" }
-    });
+	const auto [json, code] = request({
+		{ "command", "plugin-unload" }
+	});
 
-    BOOST_TEST(code == plugin_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-unload" },
-        { "plugin",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-unload" },
+		{ "plugin",     "unknown"       }
+	});
 
-    BOOST_TEST(code == plugin_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(code == plugin_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
 }
 
 BOOST_AUTO_TEST_CASE(exec_error)
 {
-    const auto [json, code] = request({
-        { "command",    "plugin-unload" },
-        { "plugin",     "broken"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "plugin-unload" },
+		{ "plugin",     "broken"        }
+	});
 
-    BOOST_TEST(code == plugin_error::exec_error);
-    BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
-    BOOST_TEST(!irccd_.plugins().has("broken"));
+	BOOST_TEST(code == plugin_error::exec_error);
+	BOOST_TEST(json["error"].get<int>() == plugin_error::exec_error);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "plugin");
+	BOOST_TEST(!irccd_.plugins().has("broken"));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-add/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-add/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-add
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-add
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-add/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-add/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,109 +33,109 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    request({
-        { "command",    "rule-add"          },
-        { "servers",    { "s1", "s2" }      },
-        { "channels",   { "c1", "c2" }      },
-        { "plugins",    { "p1", "p2" }      },
-        { "events",     { "onMessage" }     },
-        { "action",     "accept"            },
-        { "index",      0                   }
-    });
+	request({
+		{ "command",    "rule-add"          },
+		{ "servers",    { "s1", "s2" }      },
+		{ "channels",   { "c1", "c2" }      },
+		{ "plugins",    { "p1", "p2" }      },
+		{ "events",     { "onMessage" }     },
+		{ "action",     "accept"            },
+		{ "index",      0                   }
+	});
 
-    const auto [json, code] = request({
-        { "command", "rule-list" }
-    });
+	const auto [json, code] = request({
+		{ "command", "rule-list" }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
 
-    auto servers = json["list"][0]["servers"];
-    auto channels = json["list"][0]["channels"];
-    auto plugins = json["list"][0]["plugins"];
-    auto events = json["list"][0]["events"];
+	auto servers = json["list"][0]["servers"];
+	auto channels = json["list"][0]["channels"];
+	auto plugins = json["list"][0]["plugins"];
+	auto events = json["list"][0]["events"];
 
-    BOOST_TEST(json_util::contains(servers, "s1"));
-    BOOST_TEST(json_util::contains(servers, "s2"));
-    BOOST_TEST(json_util::contains(channels, "c1"));
-    BOOST_TEST(json_util::contains(channels, "c2"));
-    BOOST_TEST(json_util::contains(plugins, "p1"));
-    BOOST_TEST(json_util::contains(plugins, "p2"));
-    BOOST_TEST(json_util::contains(events, "onMessage"));
-    BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
+	BOOST_TEST(json_util::contains(servers, "s1"));
+	BOOST_TEST(json_util::contains(servers, "s2"));
+	BOOST_TEST(json_util::contains(channels, "c1"));
+	BOOST_TEST(json_util::contains(channels, "c2"));
+	BOOST_TEST(json_util::contains(plugins, "p1"));
+	BOOST_TEST(json_util::contains(plugins, "p2"));
+	BOOST_TEST(json_util::contains(events, "onMessage"));
+	BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
 }
 
 BOOST_AUTO_TEST_CASE(append)
 {
-    request({
-        { "command",    "rule-add"          },
-        { "servers",    { "s1" }            },
-        { "channels",   { "c1" }            },
-        { "plugins",    { "p1" }            },
-        { "events",     { "onMessage" }     },
-        { "action",     "accept"            },
-        { "index",      0                   }
-    });
+	request({
+		{ "command",    "rule-add"          },
+		{ "servers",    { "s1" }            },
+		{ "channels",   { "c1" }            },
+		{ "plugins",    { "p1" }            },
+		{ "events",     { "onMessage" }     },
+		{ "action",     "accept"            },
+		{ "index",      0                   }
+	});
 
-    request({
-        { "command",    "rule-add"          },
-        { "servers",    { "s2" }            },
-        { "channels",   { "c2" }            },
-        { "plugins",    { "p2" }            },
-        { "events",     { "onMessage" }     },
-        { "action",     "drop"              },
-        { "index",      1                   }
-    });
+	request({
+		{ "command",    "rule-add"          },
+		{ "servers",    { "s2" }            },
+		{ "channels",   { "c2" }            },
+		{ "plugins",    { "p2" }            },
+		{ "events",     { "onMessage" }     },
+		{ "action",     "drop"              },
+		{ "index",      1                   }
+	});
 
-    const auto [json, code] = request({
-        { "command", "rule-list" }
-    });
+	const auto [json, code] = request({
+		{ "command", "rule-list" }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["list"].size() == 2U);
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["list"].size() == 2U);
 
-    // Rule 0.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 1.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "drop");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_action)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-add"  },
-        { "action",     "unknown"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-add"  },
+		{ "action",     "unknown"   }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_action);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_action);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_action);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_action);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-edit/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-edit/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-edit
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-edit
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-edit/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-edit/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,367 +31,367 @@
 
 class rule_edit_fixture : public command_fixture {
 public:
-    rule_edit_fixture()
-    {
-        irccd_.rules().add(rule(
-            { "s1", "s2" },
-            { "c1", "c2" },
-            { "o1", "o2" },
-            { "p1", "p2" },
-            { "onMessage", "onCommand" },
-            rule::action::drop
-        ));
-    }
+	rule_edit_fixture()
+	{
+		irccd_.rules().add(rule{
+			{ "s1", "s2" },
+			{ "c1", "c2" },
+			{ "o1", "o2" },
+			{ "p1", "p2" },
+			{ "onMessage", "onCommand" },
+			rule::action_type::drop
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_edit_fixture_suite, rule_edit_fixture)
 
 BOOST_AUTO_TEST_CASE(add_server)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "add-servers",    { "new-s3" }    },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "add-servers",    { "new-s3" }    },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["servers"], "new-s3"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["servers"], "new-s3"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(add_channel)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "add-channels",   { "new-c3" }    },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "add-channels",   { "new-c3" }    },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["channels"], "new-c3"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["channels"], "new-c3"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(add_plugin)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "add-plugins",    { "new-p3" }    },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "add-plugins",    { "new-p3" }    },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "new-p3"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "new-p3"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(add_event)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "add-events",     { "onQuery" }   },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "add-events",     { "onQuery" }   },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json_util::contains(json["events"], "onQuery"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json_util::contains(json["events"], "onQuery"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(add_event_and_server)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "add-servers",    { "new-s3" }    },
-        { "add-events",     { "onQuery" }   },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "add-servers",    { "new-s3" }    },
+		{ "add-events",     { "onQuery" }   },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["servers"], "new-s3"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json_util::contains(json["events"], "onQuery"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["servers"], "new-s3"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json_util::contains(json["events"], "onQuery"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(change_action)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "action",         "accept"        },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "action",         "accept"        },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "accept");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "accept");
 }
 
 BOOST_AUTO_TEST_CASE(remove_server)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "remove-servers", { "s2" }        },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "remove-servers", { "s2" }        },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(!json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(!json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(remove_channel)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "remove-channels", { "c2" }       },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "remove-channels", { "c2" }       },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(!json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(!json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(remove_plugin)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "remove-plugins", { "p2" }        },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "remove-plugins", { "p2" }        },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(!json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(!json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(remove_event)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "remove-events",  { "onCommand" } },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "remove-events",  { "onCommand" } },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(!json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(!json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_CASE(remove_event_and_server)
 {
-    request({
-        { "command",        "rule-edit"     },
-        { "remove-servers", { "s2" }        },
-        { "remove-events",  { "onCommand" } },
-        { "index",          0               }
-    });
+	request({
+		{ "command",        "rule-edit"     },
+		{ "remove-servers", { "s2" }        },
+		{ "remove-events",  { "onCommand" } },
+		{ "index",          0               }
+	});
 
-    const auto [json, code] = request({
-        { "command",        "rule-info"     },
-        { "index",          0               }
-    });
+	const auto [json, code] = request({
+		{ "command",        "rule-info"     },
+		{ "index",          0               }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json_util::contains(json["servers"], "s1"));
-    BOOST_TEST(!json_util::contains(json["servers"], "s2"));
-    BOOST_TEST(json_util::contains(json["channels"], "c1"));
-    BOOST_TEST(json_util::contains(json["channels"], "c2"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p1"));
-    BOOST_TEST(json_util::contains(json["plugins"], "p2"));
-    BOOST_TEST(json_util::contains(json["events"], "onMessage"));
-    BOOST_TEST(!json_util::contains(json["events"], "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json_util::contains(json["servers"], "s1"));
+	BOOST_TEST(!json_util::contains(json["servers"], "s2"));
+	BOOST_TEST(json_util::contains(json["channels"], "c1"));
+	BOOST_TEST(json_util::contains(json["channels"], "c2"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p1"));
+	BOOST_TEST(json_util::contains(json["plugins"], "p2"));
+	BOOST_TEST(json_util::contains(json["events"], "onMessage"));
+	BOOST_TEST(!json_util::contains(json["events"], "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-edit" },
-        { "index",      -100        },
-        { "action",     "drop"      }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-edit" },
+		{ "index",      -100        },
+		{ "action",     "drop"      }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-edit" },
-        { "index",      100         },
-        { "action",     "drop"      }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-edit" },
+		{ "index",      100         },
+		{ "action",     "drop"      }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_3)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-edit" },
-        { "index",      "notaint"   },
-        { "action",     "drop"      }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-edit" },
+		{ "index",      "notaint"   },
+		{ "action",     "drop"      }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_action)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-edit" },
-        { "index",      0           },
-        { "action",     "unknown"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-edit" },
+		{ "index",      0           },
+		{ "action",     "unknown"   }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_action);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_action);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_action);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_action);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-info
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-info
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,89 +31,89 @@
 
 class rule_info_fixture : public command_fixture {
 public:
-    rule_info_fixture()
-    {
-        irccd_.rules().add(rule(
-            { "s1", "s2" },
-            { "c1", "c2" },
-            { "o1", "o2" },
-            { "p1", "p2" },
-            { "onMessage", "onCommand" },
-            rule::action::drop
-        ));
-        irccd_.rules().add(rule(
-            { "s1", },
-            { "c1", },
-            { "o1", },
-            { "p1", },
-            { "onMessage", },
-            rule::action::accept
-        ));
-    }
+	rule_info_fixture()
+	{
+		irccd_.rules().add(rule{
+			{ "s1", "s2" },
+			{ "c1", "c2" },
+			{ "o1", "o2" },
+			{ "p1", "p2" },
+			{ "onMessage", "onCommand" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add(rule{
+			{ "s1", },
+			{ "c1", },
+			{ "o1", },
+			{ "p1", },
+			{ "onMessage", },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_info_fixture_suite, rule_info_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-info" },
-        { "index",      0           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-info" },
+		{ "index",      0           }
+	});
 
-    auto servers = json["servers"];
-    auto channels = json["channels"];
-    auto plugins = json["plugins"];
-    auto events = json["events"];
+	auto servers = json["servers"];
+	auto channels = json["channels"];
+	auto plugins = json["plugins"];
+	auto events = json["events"];
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json_util::contains(servers, "s1"));
-    BOOST_TEST(json_util::contains(servers, "s2"));
-    BOOST_TEST(json_util::contains(channels, "c1"));
-    BOOST_TEST(json_util::contains(channels, "c2"));
-    BOOST_TEST(json_util::contains(plugins, "p1"));
-    BOOST_TEST(json_util::contains(plugins, "p2"));
-    BOOST_TEST(json_util::contains(events, "onMessage"));
-    BOOST_TEST(json_util::contains(events, "onCommand"));
-    BOOST_TEST(json["action"].get<std::string>() == "drop");
+	BOOST_TEST(!code);
+	BOOST_TEST(json_util::contains(servers, "s1"));
+	BOOST_TEST(json_util::contains(servers, "s2"));
+	BOOST_TEST(json_util::contains(channels, "c1"));
+	BOOST_TEST(json_util::contains(channels, "c2"));
+	BOOST_TEST(json_util::contains(plugins, "p1"));
+	BOOST_TEST(json_util::contains(plugins, "p2"));
+	BOOST_TEST(json_util::contains(events, "onMessage"));
+	BOOST_TEST(json_util::contains(events, "onCommand"));
+	BOOST_TEST(json["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-info" },
-        { "index",      -100        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-info" },
+		{ "index",      -100        }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-info" },
-        { "index",      100         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-info" },
+		{ "index",      100         }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_3)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-info" },
-        { "index",      "notaint"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-info" },
+		{ "index",      "notaint"   }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-list
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-list
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,82 +31,82 @@
 
 class rule_list_fixture : public command_fixture {
 public:
-    rule_list_fixture()
-    {
-        irccd_.rules().add(rule(
-            { "s1", "s2" },
-            { "c1", "c2" },
-            { "o1", "o2" },
-            { "p1", "p2" },
-            { "onMessage", "onCommand" },
-            rule::action::drop
-        ));
-        irccd_.rules().add(rule(
-            { "s1", },
-            { "c1", },
-            { "o1", },
-            { "p1", },
-            { "onMessage", },
-            rule::action::accept
-        ));
-    }
+	rule_list_fixture()
+	{
+		irccd_.rules().add(rule{
+			{ "s1", "s2" },
+			{ "c1", "c2" },
+			{ "o1", "o2" },
+			{ "p1", "p2" },
+			{ "onMessage", "onCommand" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add(rule{
+			{ "s1", },
+			{ "c1", },
+			{ "o1", },
+			{ "p1", },
+			{ "onMessage", },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_list_fixture_suite, rule_list_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["list"].is_array());
-    BOOST_TEST(json["list"].size() == 2U);
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["list"].is_array());
+	BOOST_TEST(json["list"].size() == 2U);
 
-    // Rule 0.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json_util::contains(events, "onCommand"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json_util::contains(events, "onCommand"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
+	}
 
-    // Rule 1.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(empty)
 {
-    irccd_.rules().remove(0);
-    irccd_.rules().remove(0);
+	irccd_.rules().remove(0);
+	irccd_.rules().remove(0);
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["list"].is_array());
-    BOOST_TEST(json["list"].empty());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["list"].is_array());
+	BOOST_TEST(json["list"].empty());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-move/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-move/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-move
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-move
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-move/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-move/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,326 +31,326 @@
 
 class rule_move_fixture : public command_fixture {
 public:
-    rule_move_fixture()
-    {
-        irccd_.rules().add(rule(
-            { "s0" },
-            { "c0" },
-            { "o0" },
-            { "p0" },
-            { "onMessage" },
-            rule::action::drop
-        ));
-        irccd_.rules().add(rule(
-            { "s1", },
-            { "c1", },
-            { "o1", },
-            { "p1", },
-            { "onMessage", },
-            rule::action::accept
-        ));
-        irccd_.rules().add(rule(
-            { "s2", },
-            { "c2", },
-            { "o2", },
-            { "p2", },
-            { "onMessage", },
-            rule::action::accept
-        ));
-    }
+	rule_move_fixture()
+	{
+		irccd_.rules().add(rule{
+			{ "s0" },
+			{ "c0" },
+			{ "o0" },
+			{ "p0" },
+			{ "onMessage" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add(rule{
+			{ "s1", },
+			{ "c1", },
+			{ "o1", },
+			{ "p1", },
+			{ "onMessage", },
+			rule::action_type::accept
+		});
+		irccd_.rules().add(rule{
+			{ "s2", },
+			{ "c2", },
+			{ "o2", },
+			{ "p2", },
+			{ "onMessage", },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_move_fixture_suite, rule_move_fixture)
 
 BOOST_AUTO_TEST_CASE(backward)
 {
-    request({
-        { "command",    "rule-move" },
-        { "from",       2           },
-        { "to",         0           }
-    });
+	request({
+		{ "command",    "rule-move" },
+		{ "from",       2           },
+		{ "to",         0           }
+	});
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
 
-    // Rule 2.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 2.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 0.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s0"));
-        BOOST_TEST(json_util::contains(channels, "c0"));
-        BOOST_TEST(json_util::contains(plugins, "p0"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s0"));
+		BOOST_TEST(json_util::contains(channels, "c0"));
+		BOOST_TEST(json_util::contains(plugins, "p0"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "drop");
+	}
 
-    // Rule 1.
-    {
-        auto servers = json["list"][2]["servers"];
-        auto channels = json["list"][2]["channels"];
-        auto plugins = json["list"][2]["plugins"];
-        auto events = json["list"][2]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][2]["servers"];
+		auto channels = json["list"][2]["channels"];
+		auto plugins = json["list"][2]["plugins"];
+		auto events = json["list"][2]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][2]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][2]["action"].get<std::string>() == "accept");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(upward)
 {
-    request({
-        { "command",    "rule-move" },
-        { "from",       0           },
-        { "to",         2           }
-    });
+	request({
+		{ "command",    "rule-move" },
+		{ "from",       0           },
+		{ "to",         2           }
+	});
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
 
-    // Rule 1.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 2.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 2.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 0.
-    {
-        auto servers = json["list"][2]["servers"];
-        auto channels = json["list"][2]["channels"];
-        auto plugins = json["list"][2]["plugins"];
-        auto events = json["list"][2]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][2]["servers"];
+		auto channels = json["list"][2]["channels"];
+		auto plugins = json["list"][2]["plugins"];
+		auto events = json["list"][2]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s0"));
-        BOOST_TEST(json_util::contains(channels, "c0"));
-        BOOST_TEST(json_util::contains(plugins, "p0"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][2]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s0"));
+		BOOST_TEST(json_util::contains(channels, "c0"));
+		BOOST_TEST(json_util::contains(plugins, "p0"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][2]["action"].get<std::string>() == "drop");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(same)
 {
-    request({
-        { "command",    "rule-move" },
-        { "from",       1           },
-        { "to",         1           }
-    });
+	request({
+		{ "command",    "rule-move" },
+		{ "from",       1           },
+		{ "to",         1           }
+	});
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
 
-    // Rule 0.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s0"));
-        BOOST_TEST(json_util::contains(channels, "c0"));
-        BOOST_TEST(json_util::contains(plugins, "p0"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s0"));
+		BOOST_TEST(json_util::contains(channels, "c0"));
+		BOOST_TEST(json_util::contains(plugins, "p0"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
+	}
 
-    // Rule 1.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 2.
-    {
-        auto servers = json["list"][2]["servers"];
-        auto channels = json["list"][2]["channels"];
-        auto plugins = json["list"][2]["plugins"];
-        auto events = json["list"][2]["events"];
+	// Rule 2.
+	{
+		auto servers = json["list"][2]["servers"];
+		auto channels = json["list"][2]["channels"];
+		auto plugins = json["list"][2]["plugins"];
+		auto events = json["list"][2]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][2]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][2]["action"].get<std::string>() == "accept");
+	}
 }
 
 BOOST_AUTO_TEST_CASE(beyond)
 {
-    request({
-        { "command",    "rule-move" },
-        { "from",       0           },
-        { "to",         123         }
-    });
+	request({
+		{ "command",    "rule-move" },
+		{ "from",       0           },
+		{ "to",         123         }
+	});
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
 
-    // Rule 1.
-    {
-        auto servers = json["list"][0]["servers"];
-        auto channels = json["list"][0]["channels"];
-        auto plugins = json["list"][0]["plugins"];
-        auto events = json["list"][0]["events"];
+	// Rule 1.
+	{
+		auto servers = json["list"][0]["servers"];
+		auto channels = json["list"][0]["channels"];
+		auto plugins = json["list"][0]["plugins"];
+		auto events = json["list"][0]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s1"));
-        BOOST_TEST(json_util::contains(channels, "c1"));
-        BOOST_TEST(json_util::contains(plugins, "p1"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s1"));
+		BOOST_TEST(json_util::contains(channels, "c1"));
+		BOOST_TEST(json_util::contains(plugins, "p1"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][0]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 2.
-    {
-        auto servers = json["list"][1]["servers"];
-        auto channels = json["list"][1]["channels"];
-        auto plugins = json["list"][1]["plugins"];
-        auto events = json["list"][1]["events"];
+	// Rule 2.
+	{
+		auto servers = json["list"][1]["servers"];
+		auto channels = json["list"][1]["channels"];
+		auto plugins = json["list"][1]["plugins"];
+		auto events = json["list"][1]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s2"));
-        BOOST_TEST(json_util::contains(channels, "c2"));
-        BOOST_TEST(json_util::contains(plugins, "p2"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
-    }
+		BOOST_TEST(json_util::contains(servers, "s2"));
+		BOOST_TEST(json_util::contains(channels, "c2"));
+		BOOST_TEST(json_util::contains(plugins, "p2"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][1]["action"].get<std::string>() == "accept");
+	}
 
-    // Rule 0.
-    {
-        auto servers = json["list"][2]["servers"];
-        auto channels = json["list"][2]["channels"];
-        auto plugins = json["list"][2]["plugins"];
-        auto events = json["list"][2]["events"];
+	// Rule 0.
+	{
+		auto servers = json["list"][2]["servers"];
+		auto channels = json["list"][2]["channels"];
+		auto plugins = json["list"][2]["plugins"];
+		auto events = json["list"][2]["events"];
 
-        BOOST_TEST(json_util::contains(servers, "s0"));
-        BOOST_TEST(json_util::contains(channels, "c0"));
-        BOOST_TEST(json_util::contains(plugins, "p0"));
-        BOOST_TEST(json_util::contains(events, "onMessage"));
-        BOOST_TEST(json["list"][2]["action"].get<std::string>() == "drop");
-    }
+		BOOST_TEST(json_util::contains(servers, "s0"));
+		BOOST_TEST(json_util::contains(channels, "c0"));
+		BOOST_TEST(json_util::contains(plugins, "p0"));
+		BOOST_TEST(json_util::contains(events, "onMessage"));
+		BOOST_TEST(json["list"][2]["action"].get<std::string>() == "drop");
+	}
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1_from)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-move" },
-        { "from",       -100        },
-        { "to",         0           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-move" },
+		{ "from",       -100        },
+		{ "to",         0           }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_1_to)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-move" },
-        { "from",       0           },
-        { "to",         -100        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-move" },
+		{ "from",       0           },
+		{ "to",         -100        }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2_from)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-move" },
-        { "from",       100         },
-        { "to",         0           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-move" },
+		{ "from",       100         },
+		{ "to",         0           }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_3_from)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-move" },
-        { "from",       "notaint"   },
-        { "to",         0           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-move" },
+		{ "from",       "notaint"   },
+		{ "to",         0           }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_3_to)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-move" },
-        { "from",       0           },
-        { "to",         "notaint"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-move" },
+		{ "from",       0           },
+		{ "to",         "notaint"   }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-rule-remove/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-remove/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-rule-remove
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-rule-remove
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-rule-remove/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-rule-remove/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,94 +31,94 @@
 
 class rule_remove_fixture : public command_fixture {
 public:
-    rule_remove_fixture()
-    {
-        irccd_.rules().add(rule(
-            { "s1", "s2" },
-            { "c1", "c2" },
-            { "o1", "o2" },
-            { "p1", "p2" },
-            { "onMessage", "onCommand" },
-            rule::action::drop
-        ));
-        irccd_.rules().add(rule(
-            { "s1", },
-            { "c1", },
-            { "o1", },
-            { "p1", },
-            { "onMessage", },
-            rule::action::accept
-        ));
-    }
+	rule_remove_fixture()
+	{
+		irccd_.rules().add(rule{
+			{ "s1", "s2" },
+			{ "c1", "c2" },
+			{ "o1", "o2" },
+			{ "p1", "p2" },
+			{ "onMessage", "onCommand" },
+			rule::action_type::drop
+		});
+		irccd_.rules().add(rule{
+			{ "s1", },
+			{ "c1", },
+			{ "o1", },
+			{ "p1", },
+			{ "onMessage", },
+			rule::action_type::accept
+		});
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rule_remove_fixture_suite, rule_remove_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    request({
-        { "command",    "rule-remove"   },
-        { "index",      1               }
-    });
+	request({
+		{ "command",    "rule-remove"   },
+		{ "index",      1               }
+	});
 
-    const auto [json, code] = request({{ "command", "rule-list" }});
+	const auto [json, code] = request({{ "command", "rule-list" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["list"].is_array());
-    BOOST_TEST(json["list"].size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(json["list"].is_array());
+	BOOST_TEST(json["list"].size() == 1U);
 
-    auto servers = json["list"][0]["servers"];
-    auto channels = json["list"][0]["channels"];
-    auto plugins = json["list"][0]["plugins"];
-    auto events = json["list"][0]["events"];
+	auto servers = json["list"][0]["servers"];
+	auto channels = json["list"][0]["channels"];
+	auto plugins = json["list"][0]["plugins"];
+	auto events = json["list"][0]["events"];
 
-    BOOST_TEST(json_util::contains(servers, "s1"));
-    BOOST_TEST(json_util::contains(servers, "s2"));
-    BOOST_TEST(json_util::contains(channels, "c1"));
-    BOOST_TEST(json_util::contains(channels, "c2"));
-    BOOST_TEST(json_util::contains(plugins, "p1"));
-    BOOST_TEST(json_util::contains(plugins, "p2"));
-    BOOST_TEST(json_util::contains(events, "onMessage"));
-    BOOST_TEST(json_util::contains(events, "onCommand"));
-    BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
+	BOOST_TEST(json_util::contains(servers, "s1"));
+	BOOST_TEST(json_util::contains(servers, "s2"));
+	BOOST_TEST(json_util::contains(channels, "c1"));
+	BOOST_TEST(json_util::contains(channels, "c2"));
+	BOOST_TEST(json_util::contains(plugins, "p1"));
+	BOOST_TEST(json_util::contains(plugins, "p2"));
+	BOOST_TEST(json_util::contains(events, "onMessage"));
+	BOOST_TEST(json_util::contains(events, "onCommand"));
+	BOOST_TEST(json["list"][0]["action"].get<std::string>() == "drop");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_index_1)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-remove"   },
-        { "index",      -100            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-remove"   },
+		{ "index",      -100            }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_2)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-remove"   },
-        { "index",      100             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-remove"   },
+		{ "index",      100             }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_index_3)
 {
-    const auto [json, code] = request({
-        { "command",    "rule-remove"   },
-        { "index",      "notaint"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "rule-remove"   },
+		{ "index",      "notaint"       }
+	});
 
-    BOOST_TEST(code == rule_error::invalid_index);
-    BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
+	BOOST_TEST(code == rule_error::invalid_index);
+	BOOST_TEST(json["error"].get<int>() == rule_error::invalid_index);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "rule");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-connect/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-connect/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-connect
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-connect
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-connect/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-connect/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,59 +31,59 @@
 
 BOOST_AUTO_TEST_CASE(minimal)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "local"             },
-        { "host",       "irc.example.org"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "local"             },
+		{ "host",       "irc.example.org"   }
+	});
 
-    const auto s = irccd_.servers().get("local");
+	const auto s = irccd_.servers().get("local");
 
-    BOOST_TEST(!code);
-    BOOST_TEST(s);
-    BOOST_TEST(s->get_id() == "local");
-    BOOST_TEST(s->get_host() == "irc.example.org");
-    BOOST_TEST(s->get_port() == 6667U);
+	BOOST_TEST(!code);
+	BOOST_TEST(s);
+	BOOST_TEST(s->get_id() == "local");
+	BOOST_TEST(s->get_host() == "irc.example.org");
+	BOOST_TEST(s->get_port() == 6667U);
 }
 
 #if defined(IRCCD_HAVE_SSL)
 
 BOOST_AUTO_TEST_CASE(full)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "local2"            },
-        { "host",       "irc.example2.org"  },
-        { "password",   "nonono"            },
-        { "nickname",   "francis"           },
-        { "realname",   "the_francis"       },
-        { "username",   "frc"               },
-        { "ctcpVersion", "ultra bot"        },
-        { "commandChar", "::"               },
-        { "port",       18000               },
-        { "ssl",        true                },
-        { "sslVerify",  true                },
-        { "autoRejoin", true                },
-        { "joinInvite", true                }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "local2"            },
+		{ "host",       "irc.example2.org"  },
+		{ "password",   "nonono"            },
+		{ "nickname",   "francis"           },
+		{ "realname",   "the_francis"       },
+		{ "username",   "frc"               },
+		{ "ctcpVersion", "ultra bot"        },
+		{ "commandChar", "::"               },
+		{ "port",       18000               },
+		{ "ssl",        true                },
+		{ "sslVerify",  true                },
+		{ "autoRejoin", true                },
+		{ "joinInvite", true                }
+	});
 
-    const auto s = irccd_.servers().get("local2");
+	const auto s = irccd_.servers().get("local2");
 
-    BOOST_TEST(!code);
-    BOOST_TEST(s);
-    BOOST_TEST(s->get_id() == "local2");
-    BOOST_TEST(s->get_host() == "irc.example2.org");
-    BOOST_TEST(s->get_port() == 18000U);
-    BOOST_TEST(s->get_password() == "nonono");
-    BOOST_TEST(s->get_nickname() == "francis");
-    BOOST_TEST(s->get_realname() == "the_francis");
-    BOOST_TEST(s->get_username() == "frc");
-    BOOST_TEST(s->get_command_char() == "::");
-    BOOST_TEST(s->get_ctcp_version() == "ultra bot");
-    BOOST_TEST(static_cast<bool>(s->get_options() & server::options::ssl));
-    BOOST_TEST(static_cast<bool>(s->get_options() & server::options::ssl_verify));
-    BOOST_TEST(static_cast<bool>(s->get_options() & server::options::auto_rejoin));
-    BOOST_TEST(static_cast<bool>(s->get_options() & server::options::join_invite));
+	BOOST_TEST(!code);
+	BOOST_TEST(s);
+	BOOST_TEST(s->get_id() == "local2");
+	BOOST_TEST(s->get_host() == "irc.example2.org");
+	BOOST_TEST(s->get_port() == 18000U);
+	BOOST_TEST(s->get_password() == "nonono");
+	BOOST_TEST(s->get_nickname() == "francis");
+	BOOST_TEST(s->get_realname() == "the_francis");
+	BOOST_TEST(s->get_username() == "frc");
+	BOOST_TEST(s->get_command_char() == "::");
+	BOOST_TEST(s->get_ctcp_version() == "ultra bot");
+	BOOST_TEST(static_cast<bool>(s->get_options() & server::options::ssl));
+	BOOST_TEST(static_cast<bool>(s->get_options() & server::options::ssl_verify));
+	BOOST_TEST(static_cast<bool>(s->get_options() & server::options::auto_rejoin));
+	BOOST_TEST(static_cast<bool>(s->get_options() & server::options::join_invite));
 }
 
 #endif // !IRCCD_HAVE_SSL
@@ -92,126 +92,126 @@
 
 BOOST_AUTO_TEST_CASE(already_exists)
 {
-    irccd_.servers().add(std::make_unique<mock_server>(ctx_, "local"));
+	irccd_.servers().add(std::make_unique<mock_server>(ctx_, "local"));
 
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "local"             },
-        { "host",       "127.0.0.1"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "local"             },
+		{ "host",       "127.0.0.1"         }
+	});
 
-    BOOST_TEST(code == server_error::already_exists);
-    BOOST_TEST(json["error"].get<int>() == server_error::already_exists);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::already_exists);
+	BOOST_TEST(json["error"].get<int>() == server_error::already_exists);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_hostname_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+	});
 
-    BOOST_TEST(code == server_error::invalid_hostname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_hostname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_hostname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_hostname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_hostname_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-        { "host",       123456              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+		{ "host",       123456              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_hostname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_hostname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_hostname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_hostname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       ""                  },
-        { "host",       "127.0.0.1"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       ""                  },
+		{ "host",       "127.0.0.1"         }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       123456              },
-        { "host",       "127.0.0.1"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       123456              },
+		{ "host",       "127.0.0.1"         }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_port_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-        { "host",       "127.0.0.1"         },
-        { "port",       "notaint"           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+		{ "host",       "127.0.0.1"         },
+		{ "port",       "notaint"           }
+	});
 
-    BOOST_TEST(code == server_error::invalid_port);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_port);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_port_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-        { "host",       "127.0.0.1"         },
-        { "port",       -123                }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+		{ "host",       "127.0.0.1"         },
+		{ "port",       -123                }
+	});
 
-    BOOST_TEST(code == server_error::invalid_port);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_port);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_port_3)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-        { "host",       "127.0.0.1"         },
-        { "port",       1000000             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+		{ "host",       "127.0.0.1"         },
+		{ "port",       1000000             }
+	});
 
-    BOOST_TEST(code == server_error::invalid_port);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_port);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_port);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 #if !defined(IRCCD_HAVE_SSL)
 
 BOOST_AUTO_TEST_CASE(ssl_disabled)
 {
-    const auto [json, code] = request({
-        { "command",    "server-connect"    },
-        { "name",       "new"               },
-        { "host",       "127.0.0.1"         },
-        { "ssl",        true                }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-connect"    },
+		{ "name",       "new"               },
+		{ "host",       "127.0.0.1"         },
+		{ "ssl",        true                }
+	});
 
-    BOOST_TEST(code == server_error::ssl_disabled);
-    BOOST_TEST(json["error"].get<int>() == server_error::ssl_disabled);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::ssl_disabled);
+	BOOST_TEST(json["error"].get<int>() == server_error::ssl_disabled);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 #endif
--- a/tests/src/libirccd/command-server-disconnect/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-disconnect/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-disconnect
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-disconnect
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-disconnect/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-disconnect/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,70 +29,70 @@
 
 class server_disconnect_fixture : public command_fixture {
 protected:
-    std::shared_ptr<mock_server> s1_;
-    std::shared_ptr<mock_server> s2_;
+	std::shared_ptr<mock_server> s1_;
+	std::shared_ptr<mock_server> s2_;
 
-    server_disconnect_fixture()
-        : s1_(new mock_server(ctx_, "s1", "localhost"))
-        , s2_(new mock_server(ctx_, "s2", "localhost"))
-    {
-        irccd_.servers().add(s1_);
-        irccd_.servers().add(s2_);
-    }
+	server_disconnect_fixture()
+		: s1_(new mock_server(ctx_, "s1", "localhost"))
+		, s2_(new mock_server(ctx_, "s2", "localhost"))
+	{
+		irccd_.servers().add(s1_);
+		irccd_.servers().add(s2_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(server_disconnect_fixture_suite, server_disconnect_fixture)
 
 BOOST_AUTO_TEST_CASE(one)
 {
-    const auto [json, code] = request({
-        { "command",    "server-disconnect" },
-        { "server",     "s1"                }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-disconnect"     },
+		{ "server",     "s1"                    }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["command"].get<std::string>() == "server-disconnect");
-    BOOST_TEST(s1_->find("disconnect").size() == 1U);
-    BOOST_TEST(!irccd_.servers().has("s1"));
-    BOOST_TEST(irccd_.servers().has("s2"));
+	BOOST_TEST(!code);
+	BOOST_TEST(json["command"].get<std::string>() == "server-disconnect");
+	BOOST_TEST(s1_->find("disconnect").size() == 1U);
+	BOOST_TEST(!irccd_.servers().has("s1"));
+	BOOST_TEST(irccd_.servers().has("s2"));
 }
 
 BOOST_AUTO_TEST_CASE(all)
 {
-    const auto [json, code] = request({{ "command", "server-disconnect" }});
+	const auto [json, code] = request({{ "command", "server-disconnect" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json["command"].get<std::string>() == "server-disconnect");
-    BOOST_TEST(s1_->find("disconnect").size() == 1U);
-    BOOST_TEST(s2_->find("disconnect").size() == 1U);
-    BOOST_TEST(!irccd_.servers().has("s1"));
-    BOOST_TEST(!irccd_.servers().has("s2"));
+	BOOST_TEST(!code);
+	BOOST_TEST(json["command"].get<std::string>() == "server-disconnect");
+	BOOST_TEST(s1_->find("disconnect").size() == 1U);
+	BOOST_TEST(s2_->find("disconnect").size() == 1U);
+	BOOST_TEST(!irccd_.servers().has("s1"));
+	BOOST_TEST(!irccd_.servers().has("s2"));
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier)
 {
-    const auto [json, code] = request({
-        { "command",    "server-disconnect" },
-        { "server",     123456              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-disconnect"     },
+		{ "server",     123456                  }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-disconnect" },
-        { "server",     "unknown"           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-disconnect"     },
+		{ "server",     "unknown"               }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-info/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-info/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-info
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-info
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-info/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-info/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,71 +31,71 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    auto server = std::make_unique<mock_server>(ctx_, "test", "example.org");
+	auto server = std::make_unique<mock_server>(ctx_, "test", "example.org");
 
-    server->set_port(8765);
-    server->set_password("none");
-    server->set_nickname("pascal");
-    server->set_username("psc");
-    server->set_realname("Pascal le grand frere");
-    server->set_ctcp_version("yeah");
-    server->set_command_char("@");
-    server->set_ping_timeout(20000);
+	server->set_port(8765);
+	server->set_password("none");
+	server->set_nickname("pascal");
+	server->set_username("psc");
+	server->set_realname("Pascal le grand frere");
+	server->set_ctcp_version("yeah");
+	server->set_command_char("@");
+	server->set_ping_timeout(20000);
 
-    irccd_.servers().clear();
-    irccd_.servers().add(std::move(server));
+	irccd_.servers().clear();
+	irccd_.servers().add(std::move(server));
 
-    const auto [json, code] = request({
-        { "command",    "server-info"       },
-        { "server",     "test"              },
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-info"   },
+		{ "server",     "test"          },
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["host"].get<std::string>() == "example.org");
-    BOOST_TEST(json["name"].get<std::string>() == "test");
-    BOOST_TEST(json["nickname"].get<std::string>() == "pascal");
-    BOOST_TEST(json["port"].get<int>() == 8765);
-    BOOST_TEST(json["realname"].get<std::string>() == "Pascal le grand frere");
-    BOOST_TEST(json["username"].get<std::string>() == "psc");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["host"].get<std::string>() == "example.org");
+	BOOST_TEST(json["name"].get<std::string>() == "test");
+	BOOST_TEST(json["nickname"].get<std::string>() == "pascal");
+	BOOST_TEST(json["port"].get<int>() == 8765);
+	BOOST_TEST(json["realname"].get<std::string>() == "Pascal le grand frere");
+	BOOST_TEST(json["username"].get<std::string>() == "psc");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-info"   },
-        { "server",     123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-info"   },
+		{ "server",     123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-info"   },
-        { "server",     ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-info"   },
+		{ "server",     ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-info"   },
-        { "server",     "unknown"       }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-info"   },
+		{ "server",     "unknown"       }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-invite/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-invite/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-invite
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-invite
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-invite/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-invite/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,118 +31,118 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite"     },
-        { "server",     "test"              },
-        { "target",     "francis"           },
-        { "channel",    "#music"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "test"          },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    const auto cmd = server_->find("invite").back();
+	const auto cmd = server_->find("invite").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#music");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#music");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     123456          },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     123456          },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     ""              },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     ""              },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     "test"          },
-        { "target",     ""              },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "test"          },
+		{ "target",     ""              },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     "test"          },
-        { "target",     123456          },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "test"          },
+		{ "target",     123456          },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     "test"          },
-        { "target",     "jean"          },
-        { "channel",    ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "channel",    ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     "test"          },
-        { "target",     "jean"          },
-        { "channel",    123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "channel",    123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-invite" },
-        { "server",     "unknown"       },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-invite" },
+		{ "server",     "unknown"       },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-join/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-join/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-join
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-join
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-join/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-join/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,114 +31,114 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"       },
-        { "server",     "test"              },
-        { "channel",    "#music"            },
-        { "password",   "plop"              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "test"          },
+		{ "channel",    "#music"        },
+		{ "password",   "plop"          }
+	});
 
-    const auto cmd = server_->find("join").back();
+	const auto cmd = server_->find("join").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#music");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "plop");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#music");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "plop");
 }
 
 BOOST_AUTO_TEST_CASE(nopassword)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"       },
-        { "server",     "test"              },
-        { "channel",    "#music"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "test"          },
+		{ "channel",    "#music"        }
+	});
 
-    const auto cmd = server_->find("join").back();
+	const auto cmd = server_->find("join").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#music");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#music");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     123456          },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     123456          },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     ""              },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     ""              },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     "test"          },
-        { "channel",    ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "test"          },
+		{ "channel",    ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     "test"          },
-        { "channel",    123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "test"          },
+		{ "channel",    123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_password)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     "test"          },
-        { "channel",    "#staff"        },
-        { "password",   123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "test"          },
+		{ "channel",    "#staff"        },
+		{ "password",   123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_password);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_password);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_password);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_password);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-join"   },
-        { "server",     "unknown"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-join"   },
+		{ "server",     "unknown"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-kick/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-kick/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-kick
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-kick
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-kick/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-kick/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,152 +31,152 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"       },
-        { "server",     "test"              },
-        { "target",     "francis"           },
-        { "channel",    "#staff"            },
-        { "reason",     "too noisy"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     "francis"       },
+		{ "channel",    "#staff"        },
+		{ "reason",     "too noisy"     }
+	});
 
-    const auto cmd = server_->find("kick").back();
+	const auto cmd = server_->find("kick").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[2]) == "too noisy");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[2]) == "too noisy");
 }
 
 BOOST_AUTO_TEST_CASE(noreason)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"       },
-        { "server",     "test"              },
-        { "target",     "francis"           },
-        { "channel",    "#staff"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     "francis"       },
+		{ "channel",    "#staff"        }
+	});
 
-    const auto cmd = server_->find("kick").back();
+	const auto cmd = server_->find("kick").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
-    BOOST_TEST(std::any_cast<std::string>(cmd[2]) == "");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "francis");
+	BOOST_TEST(std::any_cast<std::string>(cmd[2]) == "");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     123456          },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     123456          },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     ""              },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     ""              },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "test"          },
-        { "target",     ""              },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     ""              },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "test"          },
-        { "target",     123456          },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     123456          },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "test"          },
-        { "target",     "jean"          },
-        { "channel",    ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "channel",    ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "test"          },
-        { "target",     "jean"          },
-        { "channel",    123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "channel",    123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_message)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "test"          },
-        { "target",     "jean"          },
-        { "channel",    "#staff"        },
-        { "reason",     123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "channel",    "#staff"        },
+		{ "reason",     123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_message);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_message);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_message);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_message);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-kick"   },
-        { "server",     "unknown"       },
-        { "target",     "francis"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-kick"   },
+		{ "server",     "unknown"       },
+		{ "target",     "francis"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-list/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-list/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-list
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-list
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-list/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-list/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,28 +29,28 @@
 
 class server_list_fixture : public command_fixture {
 protected:
-    server_list_fixture()
-    {
-        irccd_.servers().clear();
-        irccd_.servers().add(std::make_unique<mock_server>(ctx_, "s1", "localhost"));
-        irccd_.servers().add(std::make_unique<mock_server>(ctx_, "s2", "localhost"));
-    }
+	server_list_fixture()
+	{
+		irccd_.servers().clear();
+		irccd_.servers().add(std::make_unique<mock_server>(ctx_, "s1", "localhost"));
+		irccd_.servers().add(std::make_unique<mock_server>(ctx_, "s2", "localhost"));
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(server_list_fixture_suite, server_list_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command", "server-list" }
-    });
+	const auto [json, code] = request({
+		{ "command", "server-list" }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(json["list"].is_array());
-    BOOST_TEST(json["list"].size() == 2U);
-    BOOST_TEST(json["list"][0].get<std::string>() == "s1");
-    BOOST_TEST(json["list"][1].get<std::string>() == "s2");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(json["list"].is_array());
+	BOOST_TEST(json["list"].size() == 2U);
+	BOOST_TEST(json["list"][0].get<std::string>() == "s1");
+	BOOST_TEST(json["list"][1].get<std::string>() == "s2");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-me/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-me/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-me
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-me
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-me/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-me/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,90 +31,90 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     "test"      },
-        { "target",     "jean"      },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     "test"          },
+		{ "target",     "jean"          },
+		{ "message",    "hello!"        }
+	});
 
-    const auto cmd = server_->find("me").back();
+	const auto cmd = server_->find("me").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "hello!");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "hello!");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     123456      },
-        { "target",     "#music"    },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     123456          },
+		{ "target",     "#music"        },
+		{ "message",    "hello!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     ""          },
-        { "target",     "#music"    },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     ""              },
+		{ "target",     "#music"        },
+		{ "message",    "hello!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     "test"      },
-        { "target",     ""          },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     "test"          },
+		{ "target",     ""              },
+		{ "message",    "hello!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     "test"      },
-        { "target",     123456      },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     "test"          },
+		{ "target",     123456          },
+		{ "message",    "hello!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-me" },
-        { "server",     "unknown"   },
-        { "target",     "#music"    },
-        { "message",    "hello!"    }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-me"     },
+		{ "server",     "unknown"       },
+		{ "target",     "#music"        },
+		{ "message",    "hello!"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-message/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-message/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-message
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-message
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-message/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-message/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,90 +31,90 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     "test"              },
-        { "target",     "#staff"            },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     "test"                  },
+		{ "target",     "#staff"                },
+		{ "message",    "plop!"                 }
+	});
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "plop!");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "plop!");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     123456              },
-        { "target",     "#music"            },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     123456                  },
+		{ "target",     "#music"                },
+		{ "message",    "plop!"                 }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     ""                  },
-        { "target",     "#music"            },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     ""                      },
+		{ "target",     "#music"                },
+		{ "message",    "plop!"                 }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     "test"              },
-        { "target",     ""                  },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     "test"                  },
+		{ "target",     ""                      },
+		{ "message",    "plop!"                 }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     "test"              },
-        { "target",     123456              },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     "test"                  },
+		{ "target",     123456                  },
+		{ "message",    "plop!"                 }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-message"    },
-        { "server",     "unknown"           },
-        { "target",     "#music"            },
-        { "message",    "plop!"             }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-message"        },
+		{ "server",     "unknown"               },
+		{ "target",     "#music"                },
+		{ "message",    "plop!"                 }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-mode/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-mode/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-mode
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-mode
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-mode/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-mode/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,117 +31,117 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "test"          },
-        { "channel",    "#irccd"        },
-        { "mode",       "+t"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "test"          },
+		{ "channel",    "#irccd"        },
+		{ "mode",       "+t"            }
+	});
 
-    const auto cmd = server_->find("mode").back();
+	const auto cmd = server_->find("mode").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#irccd");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "+t");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#irccd");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "+t");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     123456          },
-        { "channel",    "#music"        },
-        { "mode",       "+i"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     123456          },
+		{ "channel",    "#music"        },
+		{ "mode",       "+i"            }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     ""              },
-        { "channel",    "#music"        },
-        { "mode",       "+i"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     ""              },
+		{ "channel",    "#music"        },
+		{ "mode",       "+i"            }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "test"          },
-        { "channel",    ""              },
-        { "mode",       "+i"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "test"          },
+		{ "channel",    ""              },
+		{ "mode",       "+i"            }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "test"          },
-        { "channel",    123456          },
-        { "mode",       "+i"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "test"          },
+		{ "channel",    123456          },
+		{ "mode",       "+i"            }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_mode_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "test"          },
-        { "channel",    "#music"        },
-        { "mode",       ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "test"          },
+		{ "channel",    "#music"        },
+		{ "mode",       ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_mode);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_mode);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_mode);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_mode);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_mode_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "test"          },
-        { "channel",    "#music"        },
-        { "mode",       123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "test"          },
+		{ "channel",    "#music"        },
+		{ "mode",       123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_mode);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_mode);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_mode);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_mode);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-mode"   },
-        { "server",     "unknown"       },
-        { "channel",    "#music"        },
-        { "mode",       "+i"            }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-mode"   },
+		{ "server",     "unknown"       },
+		{ "channel",    "#music"        },
+		{ "mode",       "+i"            }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-nick/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-nick/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-nick
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-nick
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-nick/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-nick/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,81 +31,81 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     "test"          },
-        { "nickname",   "chris"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     "test"          },
+		{ "nickname",   "chris"         }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(json.is_object());
-    BOOST_TEST(server_->get_nickname() == "chris");
+	BOOST_TEST(!code);
+	BOOST_TEST(json.is_object());
+	BOOST_TEST(server_->get_nickname() == "chris");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     123456          },
-        { "nickname",   "chris"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     123456          },
+		{ "nickname",   "chris"         }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     ""              },
-        { "nickname",   "chris"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     ""              },
+		{ "nickname",   "chris"         }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     "test"          },
-        { "nickname",   ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     "test"          },
+		{ "nickname",   ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_nickname_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     "test"          },
-        { "nickname",   123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     "test"          },
+		{ "nickname",   123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_nickname);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_nickname);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_nickname);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-nick"   },
-        { "server",     "unknown"       },
-        { "nickname",   "chris"         }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-nick"   },
+		{ "server",     "unknown"       },
+		{ "nickname",   "chris"         }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-notice/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-notice/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-notice
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-notice
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-notice/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-notice/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,90 +31,90 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     "test"          },
-        { "target",     "#staff"        },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     "test"          },
+		{ "target",     "#staff"        },
+		{ "message",    "quiet!"        }
+	});
 
-    const auto cmd = server_->find("notice").back();
+	const auto cmd = server_->find("notice").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "quiet!");
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "quiet!");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     123456          },
-        { "target",     "#music"        },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     123456          },
+		{ "target",     "#music"        },
+		{ "message",    "quiet!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     ""              },
-        { "target",     "#music"        },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     ""              },
+		{ "target",     "#music"        },
+		{ "message",    "quiet!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     "test"          },
-        { "target",     ""              },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     "test"          },
+		{ "target",     ""              },
+		{ "message",    "quiet!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     "test"          },
-        { "target",     123456          },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     "test"          },
+		{ "target",     123456          },
+		{ "message",    "quiet!"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-notice" },
-        { "server",     "unknown"       },
-        { "target",     "#music"        },
-        { "message",    "quiet!"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-notice" },
+		{ "server",     "unknown"       },
+		{ "target",     "#music"        },
+		{ "message",    "quiet!"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-part/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-part/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-part
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-part
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-part/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-part/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,100 +31,100 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     "test"          },
-        { "channel",    "#staff"        },
-        { "reason",     "too noisy"     }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     "test"          },
+		{ "channel",    "#staff"        },
+		{ "reason",     "too noisy"     }
+	});
 
-    const auto cmd = server_->find("part").back();
+	const auto cmd = server_->find("part").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "too noisy");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "too noisy");
 }
 
 BOOST_AUTO_TEST_CASE(noreason)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     "test"          },
-        { "channel",    "#staff"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     "test"          },
+		{ "channel",    "#staff"        }
+	});
 
-    const auto cmd = server_->find("part").back();
+	const auto cmd = server_->find("part").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     123456          },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     123456          },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     ""              },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     ""              },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     "test"          },
-        { "channel",    ""              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     "test"          },
+		{ "channel",    ""              }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     "test"          },
-        { "channel",    123456          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     "test"          },
+		{ "channel",    123456          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-part"   },
-        { "server",     "unknown"       },
-        { "channel",    "#music"        }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-part"   },
+		{ "server",     "unknown"       },
+		{ "channel",    "#music"        }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-reconnect/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-reconnect/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-reconnect
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-reconnect
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-reconnect/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-reconnect/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,83 +29,83 @@
 
 class server_reconnect_fixture : public command_fixture {
 protected:
-    std::shared_ptr<mock_server> s1_;
-    std::shared_ptr<mock_server> s2_;
+	std::shared_ptr<mock_server> s1_;
+	std::shared_ptr<mock_server> s2_;
 
-    server_reconnect_fixture()
-        : s1_(new mock_server(ctx_, "s1", "localhost"))
-        , s2_(new mock_server(ctx_, "s2", "localhost"))
-    {
-        irccd_.servers().clear();
-        irccd_.servers().add(s1_);
-        irccd_.servers().add(s2_);
-        s1_->clear();
-        s2_->clear();
-    }
+	server_reconnect_fixture()
+		: s1_(new mock_server(ctx_, "s1", "localhost"))
+		, s2_(new mock_server(ctx_, "s2", "localhost"))
+	{
+		irccd_.servers().clear();
+		irccd_.servers().add(s1_);
+		irccd_.servers().add(s2_);
+		s1_->clear();
+		s2_->clear();
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(server_reconnect_fixture_suite, server_reconnect_fixture)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [_, code] = request({
-        { "command",    "server-reconnect"  },
-        { "server",     "s1"                }
-    });
+	const auto [_, code] = request({
+		{ "command",    "server-reconnect"      },
+		{ "server",     "s1"                    }
+	});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(s1_->find("disconnect").size() == 1U);
-    BOOST_TEST(s1_->find("connect").size() == 1U);
-    BOOST_TEST(s2_->empty());
+	BOOST_TEST(!code);
+	BOOST_TEST(s1_->find("disconnect").size() == 1U);
+	BOOST_TEST(s1_->find("connect").size() == 1U);
+	BOOST_TEST(s2_->empty());
 }
 
 BOOST_AUTO_TEST_CASE(all)
 {
-    const auto [_, code] = request({{ "command", "server-reconnect" }});
+	const auto [_, code] = request({{ "command", "server-reconnect" }});
 
-    BOOST_TEST(!code);
-    BOOST_TEST(s1_->find("disconnect").size() == 1U);
-    BOOST_TEST(s1_->find("connect").size() == 1U);
-    BOOST_TEST(s2_->find("disconnect").size() == 1U);
-    BOOST_TEST(s2_->find("connect").size() == 1U);
+	BOOST_TEST(!code);
+	BOOST_TEST(s1_->find("disconnect").size() == 1U);
+	BOOST_TEST(s1_->find("connect").size() == 1U);
+	BOOST_TEST(s2_->find("disconnect").size() == 1U);
+	BOOST_TEST(s2_->find("connect").size() == 1U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-reconnect"  },
-        { "server",     123456              }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-reconnect"      },
+		{ "server",     123456                  }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-reconnect"  },
-        { "server",     ""                  }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-reconnect"      },
+		{ "server",     ""                      }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-reconnect"  },
-        { "server",     "unknown"           }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-reconnect"      },
+		{ "server",     "unknown"               }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/command-server-topic/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-topic/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME command-server-topic
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-ctl
+	NAME command-server-topic
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-ctl
 )
--- a/tests/src/libirccd/command-server-topic/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/command-server-topic/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,90 +31,90 @@
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     "test"          },
-        { "channel",    "#staff"        },
-        { "topic",      "new version"   }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     "test"          },
+		{ "channel",    "#staff"        },
+		{ "topic",      "new version"   }
+	});
 
-    const auto cmd = server_->find("topic").back();
+	const auto cmd = server_->find("topic").back();
 
-    BOOST_TEST(!code);
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "new version");
+	BOOST_TEST(!code);
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "new version");
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     123456          },
-        { "channel",    "#music"        },
-        { "topic",      "plop"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     123456          },
+		{ "channel",    "#music"        },
+		{ "topic",      "plop"          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_identifier_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     ""              },
-        { "channel",    "#music"        },
-        { "topic",      "plop"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     ""              },
+		{ "channel",    "#music"        },
+		{ "topic",      "plop"          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_identifier);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_identifier);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_identifier);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_1)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     "test"          },
-        { "channel",    ""              },
-        { "topic",      "plop"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     "test"          },
+		{ "channel",    ""              },
+		{ "topic",      "plop"          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(invalid_channel_2)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     "test"          },
-        { "channel",    123456          },
-        { "topic",      "plop"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     "test"          },
+		{ "channel",    123456          },
+		{ "topic",      "plop"          }
+	});
 
-    BOOST_TEST(code == server_error::invalid_channel);
-    BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::invalid_channel);
+	BOOST_TEST(json["error"].get<int>() == server_error::invalid_channel);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    const auto [json, code] = request({
-        { "command",    "server-topic"  },
-        { "server",     "unknown"       },
-        { "channel",    "#music"        },
-        { "topic",      "plop"          }
-    });
+	const auto [json, code] = request({
+		{ "command",    "server-topic"  },
+		{ "server",     "unknown"       },
+		{ "channel",    "#music"        },
+		{ "topic",      "plop"          }
+	});
 
-    BOOST_TEST(code == server_error::not_found);
-    BOOST_TEST(json["error"].get<int>() == server_error::not_found);
-    BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
+	BOOST_TEST(code == server_error::not_found);
+	BOOST_TEST(json["error"].get<int>() == server_error::not_found);
+	BOOST_TEST(json["errorCategory"].get<std::string>() == "server");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/dynlib-plugin/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -21,24 +21,24 @@
 add_library(test-plugin MODULE test_plugin.cpp)
 target_link_libraries(test-plugin libirccd Boost::boost)
 set_target_properties(
-    test-plugin
-    PROPERTIES
-        PREFIX ""
-        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+	test-plugin
+	PROPERTIES
+		PREFIX ""
+		RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
 )
 
 foreach (c ${CMAKE_CONFIGURATION_TYPES})
-    string(TOUPPER ${c} c)
-    set_target_properties(
-        test-plugin
-        PROPERTIES
-            RUNTIME_OUTPUT_DIRECTORY_${c} ${CMAKE_CURRENT_BINARY_DIR}
-    )
+	string(TOUPPER ${c} c)
+	set_target_properties(
+		test-plugin
+		PROPERTIES
+			RUNTIME_OUTPUT_DIRECTORY_${c} ${CMAKE_CURRENT_BINARY_DIR}
+	)
 endforeach ()
 
 irccd_define_test(
-    NAME dynlib-plugin
-    SOURCES main.cpp
-    LIBRARIES libirccd libirccd-test
-    DEPENDS test-plugin
+	NAME dynlib-plugin
+	SOURCES main.cpp
+	LIBRARIES libirccd libirccd-test
+	DEPENDS test-plugin
 )
--- a/tests/src/libirccd/dynlib-plugin/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -34,155 +34,155 @@
 
 class fixture {
 protected:
-    boost::asio::io_service service_;
-    std::shared_ptr<plugin> plugin_;
-    irccd irccd_{service_};
+	boost::asio::io_service service_;
+	std::shared_ptr<plugin> plugin_;
+	irccd irccd_{service_};
 
-    fixture()
-    {
-        plugin_ = dynlib_plugin_loader({CMAKE_CURRENT_BINARY_DIR}).find("test-plugin");
+	fixture()
+	{
+		plugin_ = dynlib_plugin_loader({CMAKE_CURRENT_BINARY_DIR}).find("test-plugin");
 
-        if (!plugin_)
-            throw std::runtime_error("test plugin not found");
-    }
+		if (!plugin_)
+			throw std::runtime_error("test plugin not found");
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(dynlib_plugin_suite, fixture)
 
 BOOST_AUTO_TEST_CASE(handle_command)
 {
-    plugin_->handle_command(irccd_, {});
+	plugin_->handle_command(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["command"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["command"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_connect)
 {
-    plugin_->handle_connect(irccd_, {});
+	plugin_->handle_connect(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["connect"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["connect"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_invite)
 {
-    plugin_->handle_invite(irccd_, {});
+	plugin_->handle_invite(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["invite"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["invite"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_join)
 {
-    plugin_->handle_join(irccd_, {});
+	plugin_->handle_join(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["join"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["join"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_kick)
 {
-    plugin_->handle_kick(irccd_, {});
+	plugin_->handle_kick(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["kick"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["kick"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_load)
 {
-    plugin_->handle_load(irccd_);
+	plugin_->handle_load(irccd_);
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["load"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["load"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_message)
 {
-    plugin_->handle_message(irccd_, {});
+	plugin_->handle_message(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["message"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["message"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_me)
 {
-    plugin_->handle_me(irccd_, {});
+	plugin_->handle_me(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["me"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["me"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_mode)
 {
-    plugin_->handle_mode(irccd_, {});
+	plugin_->handle_mode(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["mode"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["mode"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_names)
 {
-    plugin_->handle_names(irccd_, {});
+	plugin_->handle_names(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["names"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["names"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_nick)
 {
-    plugin_->handle_nick(irccd_, {});
+	plugin_->handle_nick(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["nick"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["nick"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_notice)
 {
-    plugin_->handle_notice(irccd_, {});
+	plugin_->handle_notice(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["notice"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["notice"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_part)
 {
-    plugin_->handle_part(irccd_, {});
+	plugin_->handle_part(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["part"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["part"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_reload)
 {
-    plugin_->handle_reload(irccd_);
+	plugin_->handle_reload(irccd_);
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["reload"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["reload"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_topic)
 {
-    plugin_->handle_topic(irccd_, {});
+	plugin_->handle_topic(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["topic"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["topic"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_unload)
 {
-    plugin_->handle_unload(irccd_);
+	plugin_->handle_unload(irccd_);
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["unload"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["unload"] == "true");
 }
 
 BOOST_AUTO_TEST_CASE(handle_whois)
 {
-    plugin_->handle_whois(irccd_, {});
+	plugin_->handle_whois(irccd_, {});
 
-    BOOST_TEST(plugin_->get_options().size() == 1U);
-    BOOST_TEST(plugin_->get_options()["whois"] == "true");
+	BOOST_TEST(plugin_->get_options().size() == 1U);
+	BOOST_TEST(plugin_->get_options()["whois"] == "true");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/dynlib-plugin/test_plugin.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/dynlib-plugin/test_plugin.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -24,118 +24,118 @@
 
 class test_plugin : public plugin {
 private:
-    map config_;
+	map config_;
 
 public:
-    test_plugin()
-        : plugin("test")
-    {
-    }
+	test_plugin()
+		: plugin("test")
+	{
+	}
 
-    auto get_options() const -> map override
-    {
-        return config_;
-    }
+	auto get_options() const -> map override
+	{
+		return config_;
+	}
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "test";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "test";
+	}
 
-    void handle_command(irccd&, const message_event&) override
-    {
-        config_["command"] = "true";
-    }
+	void handle_command(irccd&, const message_event&) override
+	{
+		config_["command"] = "true";
+	}
 
-    void handle_connect(irccd&, const connect_event&) override
-    {
-        config_["connect"] = "true";
-    }
+	void handle_connect(irccd&, const connect_event&) override
+	{
+		config_["connect"] = "true";
+	}
 
-    void handle_invite(irccd&, const invite_event&) override
-    {
-        config_["invite"] = "true";
-    }
+	void handle_invite(irccd&, const invite_event&) override
+	{
+		config_["invite"] = "true";
+	}
 
-    void handle_join(irccd&, const join_event&) override
-    {
-        config_["join"] = "true";
-    }
+	void handle_join(irccd&, const join_event&) override
+	{
+		config_["join"] = "true";
+	}
 
-    void handle_kick(irccd&, const kick_event&) override
-    {
-        config_["kick"] = "true";
-    }
+	void handle_kick(irccd&, const kick_event&) override
+	{
+		config_["kick"] = "true";
+	}
 
-    void handle_load(irccd&) override
-    {
-        config_["load"] = "true";
-    }
+	void handle_load(irccd&) override
+	{
+		config_["load"] = "true";
+	}
 
-    void handle_message(irccd&, const message_event&) override
-    {
-        config_["message"] = "true";
-    }
+	void handle_message(irccd&, const message_event&) override
+	{
+		config_["message"] = "true";
+	}
 
-    void handle_me(irccd&, const me_event&) override
-    {
-        config_["me"] = "true";
-    }
+	void handle_me(irccd&, const me_event&) override
+	{
+		config_["me"] = "true";
+	}
 
-    void handle_mode(irccd&, const mode_event&) override
-    {
-        config_["mode"] = "true";
-    }
+	void handle_mode(irccd&, const mode_event&) override
+	{
+		config_["mode"] = "true";
+	}
 
-    void handle_names(irccd&, const names_event&) override
-    {
-        config_["names"] = "true";
-    }
+	void handle_names(irccd&, const names_event&) override
+	{
+		config_["names"] = "true";
+	}
 
-    void handle_nick(irccd&, const nick_event&) override
-    {
-        config_["nick"] = "true";
-    }
+	void handle_nick(irccd&, const nick_event&) override
+	{
+		config_["nick"] = "true";
+	}
 
-    void handle_notice(irccd&, const notice_event&) override
-    {
-        config_["notice"] = "true";
-    }
+	void handle_notice(irccd&, const notice_event&) override
+	{
+		config_["notice"] = "true";
+	}
 
-    void handle_part(irccd&, const part_event&) override
-    {
-        config_["part"] = "true";
-    }
+	void handle_part(irccd&, const part_event&) override
+	{
+		config_["part"] = "true";
+	}
 
-    void handle_reload(irccd&) override
-    {
-        config_["reload"] = "true";
-    }
+	void handle_reload(irccd&) override
+	{
+		config_["reload"] = "true";
+	}
 
-    void handle_topic(irccd&, const topic_event&) override
-    {
-        config_["topic"] = "true";
-    }
+	void handle_topic(irccd&, const topic_event&) override
+	{
+		config_["topic"] = "true";
+	}
 
-    void handle_unload(irccd&) override
-    {
-        config_["unload"] = "true";
-    }
+	void handle_unload(irccd&) override
+	{
+		config_["unload"] = "true";
+	}
 
-    void handle_whois(irccd&, const whois_event&) override
-    {
-        config_["whois"] = "true";
-    }
+	void handle_whois(irccd&, const whois_event&) override
+	{
+		config_["whois"] = "true";
+	}
 
-    static auto abi() -> version
-    {
-        return version();
-    }
+	static auto abi() -> version
+	{
+		return version();
+	}
 
-    static auto init(std::string) -> std::unique_ptr<plugin>
-    {
-        return std::make_unique<test_plugin>();
-    }
+	static auto init(std::string) -> std::unique_ptr<plugin>
+	{
+		return std::make_unique<test_plugin>();
+	}
 };
 
 BOOST_DLL_ALIAS(test_plugin::abi, irccd_abi_test_plugin)
--- a/tests/src/libirccd/irc/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/irc/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME irc
-    SOURCES main.cpp
-    LIBRARIES libirccd
+	NAME irc
+	SOURCES main.cpp
+	LIBRARIES libirccd
 )
--- a/tests/src/libirccd/irc/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/irc/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -29,24 +29,24 @@
 
 BOOST_AUTO_TEST_CASE(no_prefix)
 {
-    const auto m = irc::message::parse("PRIVMSG jean :bonjour à toi");
+	const auto m = irc::message::parse("PRIVMSG jean :bonjour à toi");
 
-    BOOST_TEST(m.prefix.empty());
-    BOOST_TEST(m.command == "PRIVMSG");
-    BOOST_TEST(m.args.size() == 2U);
-    BOOST_TEST(m.args[0] == "jean");
-    BOOST_TEST(m.args[1] == "bonjour à toi");
+	BOOST_TEST(m.prefix.empty());
+	BOOST_TEST(m.command == "PRIVMSG");
+	BOOST_TEST(m.args.size() == 2U);
+	BOOST_TEST(m.args[0] == "jean");
+	BOOST_TEST(m.args[1] == "bonjour à toi");
 }
 
 BOOST_AUTO_TEST_CASE(prefix)
 {
-    const auto m = irc::message::parse(":127.0.0.1 PRIVMSG jean :bonjour à toi");
+	const auto m = irc::message::parse(":127.0.0.1 PRIVMSG jean :bonjour à toi");
 
-    BOOST_TEST(m.prefix == "127.0.0.1");
-    BOOST_TEST(m.command == "PRIVMSG");
-    BOOST_TEST(m.args.size() == 2U);
-    BOOST_TEST(m.args[0] == "jean");
-    BOOST_TEST(m.args[1] == "bonjour à toi");
+	BOOST_TEST(m.prefix == "127.0.0.1");
+	BOOST_TEST(m.command == "PRIVMSG");
+	BOOST_TEST(m.args.size() == 2U);
+	BOOST_TEST(m.args[0] == "jean");
+	BOOST_TEST(m.args[1] == "bonjour à toi");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -55,23 +55,23 @@
 
 BOOST_AUTO_TEST_CASE(basics)
 {
-    const auto user = irc::user::parse("jean!~jean@127.0.0.1");
+	const auto user = irc::user::parse("jean!~jean@127.0.0.1");
 
-    BOOST_TEST(user.nick == "jean");
-    BOOST_TEST(user.host == "~jean@127.0.0.1");
+	BOOST_TEST(user.nick == "jean");
+	BOOST_TEST(user.host == "~jean@127.0.0.1");
 
-    const auto usersimple = irc::user::parse("jean");
+	const auto usersimple = irc::user::parse("jean");
 
-    BOOST_TEST(usersimple.nick == "jean");
-    BOOST_TEST(usersimple.host.empty());
+	BOOST_TEST(usersimple.nick == "jean");
+	BOOST_TEST(usersimple.host.empty());
 }
 
 BOOST_AUTO_TEST_CASE(empty)
 {
-    const auto user = irc::user::parse("");
+	const auto user = irc::user::parse("");
 
-    BOOST_TEST(user.nick.empty());
-    BOOST_TEST(user.host.empty());
+	BOOST_TEST(user.nick.empty());
+	BOOST_TEST(user.host.empty());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/logger/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/logger/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME logger
-    SOURCES main.cpp
-    LIBRARIES libirccd
+	NAME logger
+	SOURCES main.cpp
+	LIBRARIES libirccd
 )
--- a/tests/src/libirccd/logger/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/logger/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,59 +33,59 @@
 
 class sample_sink : public logger::sink {
 public:
-    std::string line_debug;
-    std::string line_info;
-    std::string line_warning;
+	std::string line_debug;
+	std::string line_info;
+	std::string line_warning;
 
-    void write_debug(const std::string& line) override
-    {
-        line_debug = line;
-    }
+	void write_debug(const std::string& line) override
+	{
+		line_debug = line;
+	}
 
-    void write_info(const std::string& line) override
-    {
-        line_info = line;
-    }
+	void write_info(const std::string& line) override
+	{
+		line_info = line;
+	}
 
-    void write_warning(const std::string& line) override
-    {
-        line_warning = line;
-    }
+	void write_warning(const std::string& line) override
+	{
+		line_warning = line;
+	}
 };
 
 class sample_filter : public logger::filter {
 public:
-    auto pre_debug(std::string_view category,
-                   std::string_view component,
-                   std::string_view message) const -> std::string override
-    {
-        return str(format("DEBUG %s:%s:%s") % category % component % message);
-    }
+	auto pre_debug(std::string_view category,
+	               std::string_view component,
+	               std::string_view message) const -> std::string override
+	{
+		return str(format("DEBUG %s:%s:%s") % category % component % message);
+	}
 
-    auto pre_info(std::string_view category,
-                  std::string_view component,
-                  std::string_view message) const -> std::string override
-    {
-        return str(format("INFO %s:%s:%s") % category % component % message);
-    }
+	auto pre_info(std::string_view category,
+	              std::string_view component,
+	              std::string_view message) const -> std::string override
+	{
+		return str(format("INFO %s:%s:%s") % category % component % message);
+	}
 
-    auto pre_warning(std::string_view category,
-                     std::string_view component,
-                     std::string_view message) const -> std::string override
-    {
-        return str(format("WARN %s:%s:%s") % category % component % message);
-    }
+	auto pre_warning(std::string_view category,
+	                 std::string_view component,
+	                 std::string_view message) const -> std::string override
+	{
+		return str(format("WARN %s:%s:%s") % category % component % message);
+	}
 };
 
 class logger_test {
 public:
-    sample_sink log_;
+	sample_sink log_;
 
-    logger_test()
-    {
-        log_.set_filter(std::make_unique<sample_filter>());
-        log_.set_verbose(true);
-    }
+	logger_test()
+	{
+		log_.set_filter(std::make_unique<sample_filter>());
+		log_.set_verbose(true);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(logger_test_suite, logger_test)
@@ -94,33 +94,33 @@
 
 BOOST_AUTO_TEST_CASE(debug)
 {
-    log_.debug("test", "debug") << "success" << std::endl;
+	log_.debug("test", "debug") << "success" << std::endl;
 
-    BOOST_TEST(log_.line_debug == "DEBUG test:debug:success");
+	BOOST_TEST(log_.line_debug == "DEBUG test:debug:success");
 }
 
 #endif
 
 BOOST_AUTO_TEST_CASE(info)
 {
-    log_.info("test", "info") << "success" << std::endl;
+	log_.info("test", "info") << "success" << std::endl;
 
-    BOOST_TEST(log_.line_info == "INFO test:info:success");
+	BOOST_TEST(log_.line_info == "INFO test:info:success");
 }
 
 BOOST_AUTO_TEST_CASE(info_quiet)
 {
-    log_.set_verbose(false);
-    log_.info("test", "info") << "success" << std::endl;
+	log_.set_verbose(false);
+	log_.info("test", "info") << "success" << std::endl;
 
-    BOOST_REQUIRE(log_.line_info.empty());
+	BOOST_REQUIRE(log_.line_info.empty());
 }
 
 BOOST_AUTO_TEST_CASE(warning)
 {
-    log_.warning("test", "warning") << "success" << std::endl;
+	log_.warning("test", "warning") << "success" << std::endl;
 
-    BOOST_TEST(log_.line_warning == "WARN test:warning:success");
+	BOOST_TEST(log_.line_warning == "WARN test:warning:success");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/rule-util/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/rule-util/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME rule-util
-    SOURCES main.cpp
-    LIBRARIES libirccd
+	NAME rule-util
+	SOURCES main.cpp
+	LIBRARIES libirccd
 )
--- a/tests/src/libirccd/rule-util/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/rule-util/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -31,12 +31,12 @@
 
 auto open(const std::string& config) -> ini::document
 {
-    boost::filesystem::path path;
+	boost::filesystem::path path;
 
-    path /= CMAKE_CURRENT_SOURCE_DIR;
-    path /= config;
+	path /= CMAKE_CURRENT_SOURCE_DIR;
+	path /= config;
 
-    return ini::read_file(path.string());
+	return ini::read_file(path.string());
 }
 
 BOOST_AUTO_TEST_SUITE(from_config)
@@ -45,59 +45,59 @@
 
 BOOST_AUTO_TEST_CASE(servers)
 {
-    const auto rule = rule_util::from_config(open("simple.conf")[0]);
+	const auto rule = rule_util::from_config(open("simple.conf")[0]);
 
-    BOOST_TEST(rule.get_servers().size() == 1U);
-    BOOST_TEST(rule.get_servers().count("s1"));
-    BOOST_TEST(rule.get_channels().empty());
-    BOOST_TEST(rule.get_plugins().empty());
-    BOOST_TEST(rule.get_events().empty());
+	BOOST_TEST(rule.servers.size() == 1U);
+	BOOST_TEST(rule.servers.count("s1"));
+	BOOST_TEST(rule.channels.empty());
+	BOOST_TEST(rule.plugins.empty());
+	BOOST_TEST(rule.events.empty());
 }
 
 BOOST_AUTO_TEST_CASE(channels)
 {
-    const auto rule = rule_util::from_config(open("simple.conf")[1]);
+	const auto rule = rule_util::from_config(open("simple.conf")[1]);
 
-    BOOST_TEST(rule.get_servers().empty());
-    BOOST_TEST(rule.get_channels().size() == 1U);
-    BOOST_TEST(rule.get_channels().count("#c1"));
-    BOOST_TEST(rule.get_plugins().empty());
-    BOOST_TEST(rule.get_events().empty());
+	BOOST_TEST(rule.servers.empty());
+	BOOST_TEST(rule.channels.size() == 1U);
+	BOOST_TEST(rule.channels.count("#c1"));
+	BOOST_TEST(rule.plugins.empty());
+	BOOST_TEST(rule.events.empty());
 }
 
 BOOST_AUTO_TEST_CASE(plugins)
 {
-    const auto rule = rule_util::from_config(open("simple.conf")[2]);
+	const auto rule = rule_util::from_config(open("simple.conf")[2]);
 
-    BOOST_TEST(rule.get_servers().empty());
-    BOOST_TEST(rule.get_channels().empty());
-    BOOST_TEST(rule.get_plugins().size() == 1U);
-    BOOST_TEST(rule.get_plugins().count("hangman"));
-    BOOST_TEST(rule.get_events().empty());
+	BOOST_TEST(rule.servers.empty());
+	BOOST_TEST(rule.channels.empty());
+	BOOST_TEST(rule.plugins.size() == 1U);
+	BOOST_TEST(rule.plugins.count("hangman"));
+	BOOST_TEST(rule.events.empty());
 }
 
 BOOST_AUTO_TEST_CASE(events)
 {
-    const auto rule = rule_util::from_config(open("simple.conf")[3]);
+	const auto rule = rule_util::from_config(open("simple.conf")[3]);
 
-    BOOST_TEST(rule.get_servers().empty());
-    BOOST_TEST(rule.get_channels().empty());
-    BOOST_TEST(rule.get_plugins().empty());
-    BOOST_TEST(rule.get_events().size() == 1U);
-    BOOST_TEST(rule.get_events().count("onCommand"));
+	BOOST_TEST(rule.servers.empty());
+	BOOST_TEST(rule.channels.empty());
+	BOOST_TEST(rule.plugins.empty());
+	BOOST_TEST(rule.events.size() == 1U);
+	BOOST_TEST(rule.events.count("onCommand"));
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(invalid_action)
 {
-    BOOST_REQUIRE_THROW(rule_util::from_config(open("error-invalid-action.conf")[0]), rule_error);
+	BOOST_REQUIRE_THROW(rule_util::from_config(open("error-invalid-action.conf")[0]), rule_error);
 
-    try {
-        rule_util::from_config(open("error-invalid-action.conf")[0]);
-    } catch (const rule_error& ex) {
-        BOOST_TEST(ex.code() == rule_error::invalid_action);
-    }
+	try {
+		rule_util::from_config(open("error-invalid-action.conf")[0]);
+	} catch (const rule_error& ex) {
+		BOOST_TEST(ex.code() == rule_error::invalid_action);
+	}
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/libirccd/rules/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/rules/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,7 +17,7 @@
 #
 
 irccd_define_test(
-    NAME rules
-    SOURCES main.cpp
-    LIBRARIES libirccd
+	NAME rules
+	SOURCES main.cpp
+	LIBRARIES libirccd
 )
--- a/tests/src/libirccd/rules/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/libirccd/rules/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -69,178 +69,178 @@
  */
 class rules_test {
 protected:
-    boost::asio::io_service service_;
-    irccd daemon_{service_};
-    rule_service rules_{daemon_};
+	boost::asio::io_service service_;
+	irccd daemon_{service_};
+	rule_service rules_{daemon_};
 
-    rules_test()
-    {
-        daemon_.set_log(std::make_unique<logger::silent_sink>());
+	rules_test()
+	{
+		daemon_.set_log(std::make_unique<logger::silent_sink>());
 
-        // #1
-        {
-            rules_.add({
-                rule::set{                }, // Servers
-                rule::set{ "#staff"       }, // Channels
-                rule::set{                }, // Origins
-                rule::set{                }, // Plugins
-                rule::set{ "onCommand"    }, // Events
-                rule::action::drop
-            });
-        }
+		// #1
+		{
+			rules_.add({
+				rule::set{                }, // Servers
+				rule::set{ "#staff"       }, // Channels
+				rule::set{                }, // Origins
+				rule::set{                }, // Plugins
+				rule::set{ "onCommand"    }, // Events
+				rule::action_type::drop
+			});
+		}
 
-        // #2
-        {
-            rules_.add({
-                rule::set{ "unsafe"       },
-                rule::set{ "#staff"       },
-                rule::set{                },
-                rule::set{                },
-                rule::set{ "onCommand"    },
-                rule::action::accept
-            });
-        }
+		// #2
+		{
+			rules_.add({
+				rule::set{ "unsafe"       },
+				rule::set{ "#staff"       },
+				rule::set{                },
+				rule::set{                },
+				rule::set{ "onCommand"    },
+				rule::action_type::accept
+			});
+		}
 
-        // #3-1
-        {
-            rules_.add({
-                rule::set{},
-                rule::set{},
-                rule::set{},
-                rule::set{"game"},
-                rule::set{},
-                rule::action::drop
-            });
-        }
+		// #3-1
+		{
+			rules_.add({
+				rule::set{},
+				rule::set{},
+				rule::set{},
+				rule::set{"game"},
+				rule::set{},
+				rule::action_type::drop
+			});
+		}
 
-        // #3-2
-        {
-            rules_.add({
-                rule::set{ "malikania", "localhost"   },
-                rule::set{ "#games"                   },
-                rule::set{                            },
-                rule::set{ "game"                     },
-                rule::set{ "onCommand", "onMessage"   },
-                rule::action::accept
-            });
-        }
-    }
+		// #3-2
+		{
+			rules_.add({
+				rule::set{ "malikania", "localhost"   },
+				rule::set{ "#games"                   },
+				rule::set{                            },
+				rule::set{ "game"                     },
+				rule::set{ "onCommand", "onMessage"   },
+				rule::action_type::accept
+			});
+		}
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(rules_test_suite, rules_test)
 
 BOOST_AUTO_TEST_CASE(basic_match1)
 {
-    rule m;
+	rule m;
 
-    /*
-     * [rule]
-     */
-    BOOST_REQUIRE(m.match("freenode", "#test", "a", "", ""));
-    BOOST_REQUIRE(m.match("", "", "", "", ""));
+	/*
+	 * [rule]
+	 */
+	BOOST_REQUIRE(m.match("freenode", "#test", "a", "", ""));
+	BOOST_REQUIRE(m.match("", "", "", "", ""));
 }
 
 BOOST_AUTO_TEST_CASE(basic_match2)
 {
-    rule m(rule::set{"freenode"});
+	rule m{rule::set{"freenode"}};
 
-    /*
-     * [rule]
-     * servers    = "freenode"
-     */
+	/*
+	 * [rule]
+	 * servers	= "freenode"
+	 */
 
-    BOOST_REQUIRE(m.match("freenode", "#test", "a", "", ""));
-    BOOST_REQUIRE(!m.match("malikania", "#test", "a", "", ""));
-    BOOST_REQUIRE(m.match("freenode", "", "jean", "", "onMessage"));
+	BOOST_REQUIRE(m.match("freenode", "#test", "a", "", ""));
+	BOOST_REQUIRE(!m.match("malikania", "#test", "a", "", ""));
+	BOOST_REQUIRE(m.match("freenode", "", "jean", "", "onMessage"));
 }
 
 BOOST_AUTO_TEST_CASE(basic_match3)
 {
-    rule m(rule::set{"freenode"}, rule::set{"#staff"});
+	rule m{rule::set{"freenode"}, rule::set{"#staff"}};
 
-    /*
-     * [rule]
-     * servers    = "freenode"
-     * channels    = "#staff"
-     */
+	/*
+	 * [rule]
+	 * servers	= "freenode"
+	 * channels	= "#staff"
+	 */
 
-    BOOST_REQUIRE(m.match("freenode", "#staff", "a", "", ""));
-    BOOST_REQUIRE(!m.match("freenode", "#test", "a", "", ""));
-    BOOST_REQUIRE(!m.match("malikania", "#staff", "a", "", ""));
+	BOOST_REQUIRE(m.match("freenode", "#staff", "a", "", ""));
+	BOOST_REQUIRE(!m.match("freenode", "#test", "a", "", ""));
+	BOOST_REQUIRE(!m.match("malikania", "#staff", "a", "", ""));
 }
 
 BOOST_AUTO_TEST_CASE(basic_match4)
 {
-    rule m(rule::set{"malikania"}, rule::set{"#staff"}, rule::set{"a"});
+	rule m{rule::set{"malikania"}, rule::set{"#staff"}, rule::set{"a"}};
 
-    /*
-     * [rule]
-     * servers    = "malikania"
-     * channels    = "#staff"
-     * plugins    = "a"
-     */
+	/*
+	 * [rule]
+	 * servers	= "malikania"
+	 * channels	= "#staff"
+	 * plugins	= "a"
+	 */
 
-    BOOST_REQUIRE(m.match("malikania", "#staff", "a", "",""));
-    BOOST_REQUIRE(!m.match("malikania", "#staff", "b", "", ""));
-    BOOST_REQUIRE(!m.match("freenode", "#staff", "a", "", ""));
+	BOOST_REQUIRE(m.match("malikania", "#staff", "a", "",""));
+	BOOST_REQUIRE(!m.match("malikania", "#staff", "b", "", ""));
+	BOOST_REQUIRE(!m.match("freenode", "#staff", "a", "", ""));
 }
 
 BOOST_AUTO_TEST_CASE(complex_match1)
 {
-    rule m(rule::set{"malikania", "freenode"});
+	rule m{rule::set{"malikania", "freenode"}};
 
-    /*
-     * [rule]
-     * servers    = "malikania freenode"
-     */
+	/*
+	 * [rule]
+	 * servers	= "malikania freenode"
+	 */
 
-    BOOST_REQUIRE(m.match("malikania", "", "", "", ""));
-    BOOST_REQUIRE(m.match("freenode", "", "", "", ""));
-    BOOST_REQUIRE(!m.match("no", "", "", "", ""));
+	BOOST_REQUIRE(m.match("malikania", "", "", "", ""));
+	BOOST_REQUIRE(m.match("freenode", "", "", "", ""));
+	BOOST_REQUIRE(!m.match("no", "", "", "", ""));
 }
 
 BOOST_AUTO_TEST_CASE(basic_solve)
 {
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("malikania", "#staff", "", "a", "onMessage"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("malikania", "#staff", "", "a", "onMessage"));
 
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("freenode", "#staff", "", "b", "onTopic"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("freenode", "#staff", "", "b", "onTopic"));
 
-    /* Not allowed */
-    BOOST_REQUIRE(!rules_.solve("malikania", "#staff", "", "", "onCommand"));
+	/* Not allowed */
+	BOOST_REQUIRE(!rules_.solve("malikania", "#staff", "", "", "onCommand"));
 
-    /* Not allowed */
-    BOOST_REQUIRE(!rules_.solve("freenode", "#staff", "", "c", "onCommand"));
+	/* Not allowed */
+	BOOST_REQUIRE(!rules_.solve("freenode", "#staff", "", "c", "onCommand"));
 
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("unsafe", "#staff", "", "c", "onCommand"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("unsafe", "#staff", "", "c", "onCommand"));
 }
 
 BOOST_AUTO_TEST_CASE(games_solve)
 {
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("malikania", "#games", "", "game", "onMessage"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("malikania", "#games", "", "game", "onMessage"));
 
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("localhost", "#games", "", "game", "onMessage"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("localhost", "#games", "", "game", "onMessage"));
 
-    /* Allowed */
-    BOOST_REQUIRE(rules_.solve("malikania", "#games", "", "game", "onCommand"));
+	/* Allowed */
+	BOOST_REQUIRE(rules_.solve("malikania", "#games", "", "game", "onCommand"));
 
-    /* Not allowed */
-    BOOST_REQUIRE(!rules_.solve("malikania", "#games", "", "game", "onQuery"));
+	/* Not allowed */
+	BOOST_REQUIRE(!rules_.solve("malikania", "#games", "", "game", "onQuery"));
 
-    /* Not allowed */
-    BOOST_REQUIRE(!rules_.solve("freenode", "#no", "", "game", "onMessage"));
+	/* Not allowed */
+	BOOST_REQUIRE(!rules_.solve("freenode", "#no", "", "game", "onMessage"));
 
-    /* Not allowed */
-    BOOST_REQUIRE(!rules_.solve("malikania", "#test", "", "game", "onMessage"));
+	/* Not allowed */
+	BOOST_REQUIRE(!rules_.solve("malikania", "#test", "", "game", "onMessage"));
 }
 
 BOOST_AUTO_TEST_CASE(fix_645)
 {
-    BOOST_REQUIRE(!rules_.solve("MALIKANIA", "#STAFF", "", "SYSTEM", "onCommand"));
+	BOOST_REQUIRE(!rules_.solve("MALIKANIA", "#STAFF", "", "SYSTEM", "onCommand"));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/ask/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/ask/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,10 +17,10 @@
 #
 
 irccd_define_test(
-    NAME plugin-ask
-    SOURCES
-        ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/answers.conf
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/ask/ask.js"
+	NAME plugin-ask
+	SOURCES
+		${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
+		${CMAKE_CURRENT_SOURCE_DIR}/answers.conf
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/ask/ask.js"
 )
--- a/tests/src/plugins/ask/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/ask/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,46 +30,46 @@
 
 class ask_test : public js_plugin_fixture {
 public:
-    ask_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        plugin_->set_options({
-            { "file", CMAKE_CURRENT_SOURCE_DIR "/answers.conf" }
-        });
-        plugin_->handle_load(irccd_);
-    }
+	ask_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		plugin_->set_options({
+			{ "file", CMAKE_CURRENT_SOURCE_DIR "/answers.conf" }
+		});
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(ask_test_suite, ask_test)
 
 BOOST_AUTO_TEST_CASE(basic)
 {
-    bool no = false;
-    bool yes = false;
+	bool no = false;
+	bool yes = false;
 
-    /*
-     * Invoke the plugin 1000 times, it will be very unlucky to not have both
-     * answers in that amount of tries.
-     */
-    for (int i = 0; i < 1000; ++i) {
-        plugin_->handle_command(irccd_, {server_, "tester", "#dummy", ""});
+	/*
+	 * Invoke the plugin 1000 times, it will be very unlucky to not have
+	 * both answers in that amount of tries.
+	 */
+	for (int i = 0; i < 1000; ++i) {
+		plugin_->handle_command(irccd_, {server_, "tester", "#dummy", ""});
 
-        const auto cmd = server_->find("message").back();
+		const auto cmd = server_->find("message").back();
 
-        BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#dummy");
+		BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#dummy");
 
-        const auto msg = std::any_cast<std::string>(cmd[1]);
+		const auto msg = std::any_cast<std::string>(cmd[1]);
 
-        if (msg == "tester, YES")
-            yes = true;
-        if (msg == "tester, NO")
-            no = true;
+		if (msg == "tester, YES")
+			yes = true;
+		if (msg == "tester, NO")
+			no = true;
 
-        server_->clear();
-    }
+		server_->clear();
+	}
 
-    BOOST_TEST(no);
-    BOOST_TEST(yes);
+	BOOST_TEST(no);
+	BOOST_TEST(yes);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/auth/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/auth/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME plugin-auth
-    SOURCES main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/auth/auth.js"
+	NAME plugin-auth
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/auth/auth.js"
 )
--- a/tests/src/plugins/auth/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/auth/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -30,61 +30,61 @@
 
 class auth_test : public js_plugin_fixture {
 protected:
-    std::shared_ptr<mock_server> nickserv1_;
-    std::shared_ptr<mock_server> nickserv2_;
-    std::shared_ptr<mock_server> quakenet_;
+	std::shared_ptr<mock_server> nickserv1_;
+	std::shared_ptr<mock_server> nickserv2_;
+	std::shared_ptr<mock_server> quakenet_;
 
 public:
-    auth_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-        , nickserv1_(std::make_shared<mock_server>(service_, "nickserv1", "localhost"))
-        , nickserv2_(std::make_shared<mock_server>(service_, "nickserv2", "localhost"))
-        , quakenet_(std::make_shared<mock_server>(service_, "quakenet", "localhost"))
-    {
-        plugin_->set_options({
-            { "nickserv1.type",     "nickserv"      },
-            { "nickserv1.password", "plopation"     },
-            { "nickserv2.type",     "nickserv"      },
-            { "nickserv2.password", "something"     },
-            { "nickserv2.username", "jean"          },
-            { "quakenet.type",      "quakenet"      },
-            { "quakenet.password",  "hello"         },
-            { "quakenet.username",  "mario"         }
-        });
-        plugin_->handle_load(irccd_);
-    }
+	auth_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+		, nickserv1_(std::make_shared<mock_server>(service_, "nickserv1", "localhost"))
+		, nickserv2_(std::make_shared<mock_server>(service_, "nickserv2", "localhost"))
+		, quakenet_(std::make_shared<mock_server>(service_, "quakenet", "localhost"))
+	{
+		plugin_->set_options({
+			{ "nickserv1.type",     "nickserv"      },
+			{ "nickserv1.password", "plopation"     },
+			{ "nickserv2.type",     "nickserv"      },
+			{ "nickserv2.password", "something"     },
+			{ "nickserv2.username", "jean"          },
+			{ "quakenet.type",      "quakenet"      },
+			{ "quakenet.password",  "hello"         },
+			{ "quakenet.username",  "mario"         }
+		});
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(auth_test_suite, auth_test)
 
 BOOST_AUTO_TEST_CASE(nickserv1)
 {
-    plugin_->handle_connect(irccd_, { nickserv1_ });
+	plugin_->handle_connect(irccd_, { nickserv1_ });
 
-    const auto cmd = nickserv1_->find("message").front();
+	const auto cmd = nickserv1_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "NickServ");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "identify plopation");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "NickServ");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "identify plopation");
 }
 
 BOOST_AUTO_TEST_CASE(nickserv2)
 {
-    plugin_->handle_connect(irccd_, { nickserv2_ });
+	plugin_->handle_connect(irccd_, { nickserv2_ });
 
-    const auto cmd = nickserv2_->find("message").front();
+	const auto cmd = nickserv2_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "NickServ");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "identify jean something");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "NickServ");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "identify jean something");
 }
 
 BOOST_AUTO_TEST_CASE(quakenet)
 {
-    plugin_->handle_connect(irccd_, { quakenet_ });
+	plugin_->handle_connect(irccd_, { quakenet_ });
 
-    const auto cmd = quakenet_->find("message").front();
+	const auto cmd = quakenet_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "Q@CServe.quakenet.org");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "AUTH mario hello");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "Q@CServe.quakenet.org");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "AUTH mario hello");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/hangman/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/hangman/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,11 +17,11 @@
 #
 
 irccd_define_test(
-    NAME plugin-hangman
-    SOURCES
-        main.cpp
-        words.conf
-        issue-644.conf
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/hangman/hangman.js"
+	NAME plugin-hangman
+	SOURCES
+		main.cpp
+		words.conf
+		issue-644.conf
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/hangman/hangman.js"
 )
--- a/tests/src/plugins/hangman/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/hangman/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,325 +33,325 @@
 
 class hangman_test : public js_plugin_fixture {
 public:
-    hangman_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        plugin_->set_formats({
-            { "asked", "asked=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
-            { "dead", "dead=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
-            { "found", "found=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
-            { "start", "start=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
-            { "running", "running=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
-            { "win", "win=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
-            { "wrong-letter", "wrong-letter=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
-            { "wrong-player", "wrong-player=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
-            { "wrong-word", "wrong-word=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" }
-        });
-    }
+	hangman_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		plugin_->set_formats({
+			{ "asked", "asked=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
+			{ "dead", "dead=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
+			{ "found", "found=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
+			{ "start", "start=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
+			{ "running", "running=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
+			{ "win", "win=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" },
+			{ "wrong-letter", "wrong-letter=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
+			{ "wrong-player", "wrong-player=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{letter}" },
+			{ "wrong-word", "wrong-word=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{word}" }
+		});
+	}
 
-    void load(plugin::map config = {})
-    {
-        // Add file if not there.
-        if (config.count("file") == 0)
-            config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/words.conf");
+	void load(plugin::map config = {})
+	{
+		// Add file if not there.
+		if (config.count("file") == 0)
+			config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/words.conf");
 
-        plugin_->set_options(config);
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->set_options(config);
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(hangman_test_suite, hangman_test)
 
 BOOST_AUTO_TEST_CASE(asked)
 {
-    load({{ "collaborative", "false" }});
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
 
-    plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 
-    plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#hangman", "s"});
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "asked=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "asked=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s");
 }
 
 BOOST_AUTO_TEST_CASE(dead)
 {
-    load({{ "collaborative", "false" }});
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "a" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "b" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "c" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "d" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "e" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "f" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "g" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "h" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "i" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "j" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "a" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "b" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "c" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "d" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "e" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "f" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "g" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "h" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "i" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "j" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "dead=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "dead=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
 BOOST_AUTO_TEST_CASE(found)
 {
-    load({{ "collaborative", "false" }});
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 }
 
 BOOST_AUTO_TEST_CASE(start)
 {
-    load();
+	load();
 
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ _");
 }
 
 BOOST_AUTO_TEST_CASE(win1)
 {
-    load({{ "collaborative", "false" }});
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "y" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "y" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
 BOOST_AUTO_TEST_CASE(win2)
 {
-    load({{ "collaborative", "false" }});
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "sky" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "sky" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:sky");
 }
 
 BOOST_AUTO_TEST_CASE(wrong_letter)
 {
-    load();
+	load();
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "x" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "x" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-letter=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:x");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-letter=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:x");
 }
 
 BOOST_AUTO_TEST_CASE(wrong_word)
 {
-    load();
+	load();
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "cheese" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "cheese" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-word=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:cheese");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-word=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:cheese");
 }
 
 BOOST_AUTO_TEST_CASE(collaborative_disabled)
 {
-    // Disable collaborative mode.
-    load({{ "collaborative", "false" }});
+	// Disable collaborative mode.
+	load({{ "collaborative", "false" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s k _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s k _");
 }
 
 BOOST_AUTO_TEST_CASE(collaborative_enabled)
 {
-    // Enable collaborative mode.
-    load({{ "collaborative", "true" }});
+	// Enable collaborative mode.
+	load({{ "collaborative", "true" }});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "s" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
 
-    plugin_->handle_message(irccd_, { server_, "francis!francis@localhost", "#hangman", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "francis!francis@localhost", "#hangman", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
 }
 
 BOOST_AUTO_TEST_CASE(issue_642)
 {
-    load();
+	load();
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#HANGMAN", "s" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#HANGMAN", "s" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:s _ _");
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#HaNGMaN", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#HaNGMaN", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "wrong-player=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:k");
 
-    plugin_->handle_message(irccd_, { server_, "francis!francis@localhost", "#hAngmAn", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "francis!francis@localhost", "#hAngmAn", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:#hangman:francis!francis@localhost:francis:s k _");
 }
 
 BOOST_AUTO_TEST_CASE(query)
 {
-    load();
+	load();
 
-    // Query mode is never collaborative.
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "irccd", "" });
+	// Query mode is never collaborative.
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "irccd", "" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:_ _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "start=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:_ _ _");
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "irccd", "s" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "irccd", "s" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:s _ _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:s _ _");
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "irccd", "k" });
-    cmd = server_->find("message").back();
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "irccd", "k" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:s k _");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "found=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:s k _");
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "irccd", "sky" });
-    cmd = server_->find("message").back();
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "irccd", "sky" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:sky");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "jean!jean@localhost");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "win=hangman:!hangman:test:jean!jean@localhost:jean!jean@localhost:jean:sky");
 }
 
 BOOST_AUTO_TEST_CASE(running)
 {
-    load();
+	load();
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "y" });
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#hangman", "y" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#hangman", "" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "running=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ y");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#hangman");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "running=hangman:!hangman:test:#hangman:jean!jean@localhost:jean:_ _ y");
 }
 
 BOOST_AUTO_TEST_CASE(issue_644)
 {
-    /*
-     * To be sure that the selection use the same list, we create a list of
-     * three words that has different size to determine which one was selected.
-     *
-     * Then we run 3 games and verify that the old selection is not the same
-     * as the current.
-     *
-     * This is not very accurate but it's better than nothing.
-     */
-    load({{ "file", CMAKE_CURRENT_SOURCE_DIR "/issue-644.conf" }});
+	/*
+	 * To be sure that the selection use the same list, we create a list of
+	 * three words that has different size to determine which one was selected.
+	 *
+	 * Then we run 3 games and verify that the old selection is not the same
+	 * as the current.
+	 *
+	 * This is not very accurate but it's better than nothing.
+	 */
+	load({{ "file", CMAKE_CURRENT_SOURCE_DIR "/issue-644.conf" }});
 
-    std::unordered_map<unsigned, std::string> words{
-        { 5, "abc"     },
-        { 7, "abcd"    },
-        { 9, "abcde"   }
-    };
-    std::unordered_set<unsigned> found;
+	std::unordered_map<unsigned, std::string> words{
+		{ 5, "abc"      },
+		{ 7, "abcd"     },
+		{ 9, "abcde"    }
+	};
+	std::unordered_set<unsigned> found;
 
-    plugin_->set_formats({
-        { "start", "#{word}" }
-    });
+	plugin_->set_formats({
+		{ "start", "#{word}" }
+	});
 
-    unsigned last, current;
+	unsigned last, current;
 
-    // 1. Initial game + finish.
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
-    last = std::any_cast<std::string>(server_->find("message").back()[1]).length();
-    found.insert(last);
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[last]});
+	// 1. Initial game + finish.
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+	last = std::any_cast<std::string>(server_->find("message").back()[1]).length();
+	found.insert(last);
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[last]});
 
-    // 2. Current must not be the last one.
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
-    current = std::any_cast<std::string>(server_->find("message").back()[1]).length();
+	// 2. Current must not be the last one.
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+	current = std::any_cast<std::string>(server_->find("message").back()[1]).length();
 
-    BOOST_TEST(last != current);
-    BOOST_TEST(0U == found.count(current));
+	BOOST_TEST(last != current);
+	BOOST_TEST(0U == found.count(current));
 
-    found.insert(current);
-    last = current;
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[current]});
+	found.insert(current);
+	last = current;
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", words[current]});
 
-    // 3. Last word must be the one that is kept into the map.
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
-    current = std::any_cast<std::string>(server_->find("message").back()[1]).length();
+	// 3. Last word must be the one that is kept into the map.
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#hangman", ""});
+	current = std::any_cast<std::string>(server_->find("message").back()[1]).length();
 
-    BOOST_TEST(last != current);
-    BOOST_TEST(0U == found.count(current));
+	BOOST_TEST(last != current);
+	BOOST_TEST(0U == found.count(current));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/history/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/history/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME plugin-history
-    SOURCES main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/history/history.js"
+	NAME plugin-history
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/history/history.js"
 )
--- a/tests/src/plugins/history/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/history/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -32,111 +32,111 @@
 
 class history_test : public js_plugin_fixture {
 public:
-    history_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        plugin_->set_formats({
-            { "error", "error=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" },
-            { "seen", "seen=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}:%H:%M" },
-            { "said", "said=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}:#{message}:%H:%M" },
-            { "unknown", "unknown=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}" },
-        });
-    }
+	history_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		plugin_->set_formats({
+			{ "error", "error=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" },
+			{ "seen", "seen=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}:%H:%M" },
+			{ "said", "said=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}:#{message}:%H:%M" },
+			{ "unknown", "unknown=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{target}" },
+		});
+	}
 
-    void load(plugin::map config = {})
-    {
-        // Add file if not there.
-        if (config.count("file") == 0)
-            config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/words.conf");
+	void load(plugin::map config = {})
+	{
+		// Add file if not there.
+		if (config.count("file") == 0)
+			config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/words.conf");
 
-        plugin_->set_options(config);
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->set_options(config);
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(history_test_suite, history_test)
 
 BOOST_AUTO_TEST_CASE(format_error)
 {
-    load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error.json"}});
+	load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error.json"}});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#history", "seen francis" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#history", "seen francis" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=history:!history:test:#history:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=history:!history:test:#history:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_CASE(format_seen)
 {
-    static const std::regex rule("seen=history:!history:test:#history:destructor!dst@localhost:destructor:jean:\\d{2}:\\d{2}");
+	static const std::regex rule("seen=history:!history:test:#history:destructor!dst@localhost:destructor:jean:\\d{2}:\\d{2}");
 
-    remove(CMAKE_CURRENT_BINARY_DIR "/seen.json");
-    load({{ "file", CMAKE_CURRENT_BINARY_DIR "/seen.json" }});
+	remove(CMAKE_CURRENT_BINARY_DIR "/seen.json");
+	load({{ "file", CMAKE_CURRENT_BINARY_DIR "/seen.json" }});
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
-    plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "seen jean" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
+	plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "seen jean" });
 
-    auto cmd = server_->find("message").front();
+	auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
 }
 
 BOOST_AUTO_TEST_CASE(format_said)
 {
-    std::regex rule("said=history:!history:test:#history:destructor!dst@localhost:destructor:jean:hello:\\d{2}:\\d{2}");
+	std::regex rule("said=history:!history:test:#history:destructor!dst@localhost:destructor:jean:hello:\\d{2}:\\d{2}");
 
-    remove(CMAKE_CURRENT_BINARY_DIR "/said.json");
-    load({{ "file", CMAKE_CURRENT_BINARY_DIR "/said.json" }});
+	remove(CMAKE_CURRENT_BINARY_DIR "/said.json");
+	load({{ "file", CMAKE_CURRENT_BINARY_DIR "/said.json" }});
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
-    plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "said jean" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
+	plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "said jean" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
 }
 
 BOOST_AUTO_TEST_CASE(format_unknown)
 {
-    remove(CMAKE_CURRENT_BINARY_DIR "/unknown.json");
-    load({{ "file", CMAKE_CURRENT_BINARY_DIR "/unknown.json" }});
+	remove(CMAKE_CURRENT_BINARY_DIR "/unknown.json");
+	load({{ "file", CMAKE_CURRENT_BINARY_DIR "/unknown.json" }});
 
-    plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
-    plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "seen nobody" });
+	plugin_->handle_message(irccd_, { server_, "jean!jean@localhost", "#history", "hello" });
+	plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#history", "seen nobody" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "unknown=history:!history:test:#history:destructor!dst@localhost:destructor:nobody");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "unknown=history:!history:test:#history:destructor!dst@localhost:destructor:nobody");
 }
 
 BOOST_AUTO_TEST_CASE(issue_642)
 {
-    static const std::regex rule("said=history:!history:test:#history:destructor!dst@localhost:destructor:jean:hello:\\d{2}:\\d{2}");
+	static const std::regex rule("said=history:!history:test:#history:destructor!dst@localhost:destructor:jean:hello:\\d{2}:\\d{2}");
 
-    remove(CMAKE_CURRENT_BINARY_DIR "/issue-642.json");
-    load({{"file", CMAKE_CURRENT_BINARY_DIR "/issue-642.json"}});
+	remove(CMAKE_CURRENT_BINARY_DIR "/issue-642.json");
+	load({{"file", CMAKE_CURRENT_BINARY_DIR "/issue-642.json"}});
 
-    plugin_->handle_message(irccd_, { server_, "JeaN!JeaN@localhost", "#history", "hello" });
+	plugin_->handle_message(irccd_, { server_, "JeaN!JeaN@localhost", "#history", "hello" });
 
-    // Full caps.
-    plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#HISTORY", "said JEAN" });
+	// Full caps.
+	plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#HISTORY", "said JEAN" });
 
-    auto cmd = server_->find("message").front();
+	auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
 
-    // Random caps.
-    plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#HiSToRy", "said JeaN" });
-    cmd = server_->find("message").back();
+	// Random caps.
+	plugin_->handle_command(irccd_, { server_, "destructor!dst@localhost", "#HiSToRy", "said JeaN" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
-    BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#history");
+	BOOST_TEST(std::regex_match(std::any_cast<std::string>(cmd[1]), rule));
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/joke/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,14 +17,14 @@
 #
 
 irccd_define_test(
-    NAME plugin-joke
-    SOURCES
-        error-empty.json
-        error-invalid.json
-        error-not-array.json
-        error-toobig.json
-        jokes.json
-        main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/joke/joke.js"
+	NAME plugin-joke
+	SOURCES
+		error-empty.json
+		error-invalid.json
+		error-not-array.json
+		error-toobig.json
+		jokes.json
+		main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/joke/joke.js"
 )
--- a/tests/src/plugins/joke/error-empty.json	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/error-empty.json	Fri Oct 26 13:01:00 2018 +0200
@@ -1,9 +1,9 @@
 [
-    [
-    ],
-    [
-    ],
-    [
-        false
-    ]
+	[
+	],
+	[
+	],
+	[
+		false
+	]
 ]
--- a/tests/src/plugins/joke/error-invalid.json	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/error-invalid.json	Fri Oct 26 13:01:00 2018 +0200
@@ -1,12 +1,12 @@
 [
-    [
-    ],
-    [
-        1234,
-        true,
-        "still hav a string though"
-    ],
-    [
-        "a"
-    ]
+	[
+	],
+	[
+		1234,
+		true,
+		"still hav a string though"
+	],
+	[
+		"a"
+	]
 ]
--- a/tests/src/plugins/joke/error-not-array.json	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/error-not-array.json	Fri Oct 26 13:01:00 2018 +0200
@@ -1,3 +1,3 @@
 {
-    "reason": "this is not a valid jokes database"
+	"reason": "this is not a valid jokes database"
 }
--- a/tests/src/plugins/joke/error-toobig.json	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/error-toobig.json	Fri Oct 26 13:01:00 2018 +0200
@@ -1,15 +1,15 @@
 [
-    [
-        "xxx",
-        "xxx",
-        "xxx"
-    ],
-    [
-        "a"
-    ],
-    [
-        "yyy",
-        "yyy",
-        "yyy"
-    ]
+	[
+		"xxx",
+		"xxx",
+		"xxx"
+	],
+	[
+		"a"
+	],
+	[
+		"yyy",
+		"yyy",
+		"yyy"
+	]
 ]
--- a/tests/src/plugins/joke/jokes.json	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/jokes.json	Fri Oct 26 13:01:00 2018 +0200
@@ -1,9 +1,9 @@
 [
-    [
-        "aaa"
-    ],
-    [
-        "bbbb",
-        "bbbb"
-    ]
+	[
+		"aaa"
+	],
+	[
+		"bbbb",
+		"bbbb"
+	]
 ]
--- a/tests/src/plugins/joke/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/joke/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -27,172 +27,170 @@
 
 class joke_test : public js_plugin_fixture {
 public:
-    joke_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        plugin_->set_formats({
-            { "error", "error=#{server}:#{channel}:#{origin}:#{nickname}" }
-        });
-    }
+	joke_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		plugin_->set_formats({
+			{ "error", "error=#{server}:#{channel}:#{origin}:#{nickname}" }
+		});
+	}
 
-    void load(plugin::map config = {})
-    {
-        // Add file if not there.
-        if (config.count("file") == 0)
-            config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/jokes.json");
+	void load(plugin::map config = {})
+	{
+		// Add file if not there.
+		if (config.count("file") == 0)
+			config.emplace("file", CMAKE_CURRENT_SOURCE_DIR "/jokes.json");
 
-        plugin_->set_options(config);
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->set_options(config);
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(joke_test_suite, joke_test)
 
 BOOST_AUTO_TEST_CASE(simple)
 {
-    /*
-     * Jokes.json have two jokes.
-     *
-     * aaa
-     *
-     * And
-     *
-     * bbbb
-     * bbbb
-     */
-    std::unordered_map<std::string, int> said{
-        { "aaa",    0 },
-        { "bbbb",   0 }
-    };
+	/*
+	 * Jokes.json have two jokes.
+	 *
+	 * aaa
+	 *
+	 * And
+	 *
+	 * bbbb
+	 * bbbb
+	 */
+	std::unordered_map<std::string, int> said{
+		{ "aaa",        0 },
+		{ "bbbb",       0 }
+	};
 
-    load();
+	load();
 
-    const auto call = [&] () {
-        plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
+	const auto call = [&] () {
+		plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
 
-        const auto cmd = server_->find("message").back();
-        const auto msg = std::any_cast<std::string>(cmd[1]);
+		const auto cmd = server_->find("message").back();
+		const auto msg = std::any_cast<std::string>(cmd[1]);
 
-        // "bbbb" is two lines.
-        if (msg == "bbbb") {
-            const auto first = server_->find("message").front();
+		// "bbbb" is two lines.
+		if (msg == "bbbb") {
+			const auto first = server_->find("message").front();
 
-            BOOST_TEST(std::any_cast<std::string>(first[0]) == "#joke");
-            BOOST_TEST(std::any_cast<std::string>(first[1]) == "bbbb");
-        } else
-            BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "aaa");
+			BOOST_TEST(std::any_cast<std::string>(first[0]) == "#joke");
+			BOOST_TEST(std::any_cast<std::string>(first[1]) == "bbbb");
+		} else
+			BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "aaa");
 
-        said[msg] += 1;
-        server_->clear();
-    };
+		said[msg] += 1;
+		server_->clear();
+	};
 
-    call();
-    call();
+	call();
+	call();
 
-    BOOST_TEST(said.size() == 2U);
-    BOOST_TEST(said["aaa"] == 1U);
-    BOOST_TEST(said["bbbb"] == 1U);
+	BOOST_TEST(said.size() == 2U);
+	BOOST_TEST(said["aaa"] == 1U);
+	BOOST_TEST(said["bbbb"] == 1U);
 }
 
 BOOST_AUTO_TEST_CASE(toobig)
 {
-    // xxx and yyy are both 3-lines which we disallow. only a must be said.
-    load({
-        { "file", CMAKE_CURRENT_SOURCE_DIR "/error-toobig.json" },
-        { "max-list-lines", "2" }
-    });
+	// xxx and yyy are both 3-lines which we disallow. only a must be said.
+	load({
+		{ "file", CMAKE_CURRENT_SOURCE_DIR "/error-toobig.json" },
+		{ "max-list-lines", "2" }
+	});
 
-    std::unordered_map<std::string, int> said{
-        { "a", 0 }
-    };
+	std::unordered_map<std::string, int> said{
+		{ "a", 0 }
+	};
 
-    const auto call = [&] () {
-        plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
+	const auto call = [&] () {
+		plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
 
-        const auto cmd = server_->find("message").back();
+		const auto cmd = server_->find("message").back();
 
-        BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
-        BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "a");
+		BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
+		BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "a");
 
-        said[std::any_cast<std::string>(cmd[1])] += 1;
-        server_->clear();
-    };
+		said[std::any_cast<std::string>(cmd[1])] += 1;
+		server_->clear();
+	};
 
-    call();
-    call();
-    call();
+	call();
+	call();
+	call();
 
-    BOOST_TEST(said.size() == 1U);
-    BOOST_TEST(said["a"] == 3U);
+	BOOST_TEST(said.size() == 1U);
+	BOOST_TEST(said["a"] == 3U);
 }
 
 BOOST_AUTO_TEST_CASE(invalid)
 {
-    // Only a is the valid joke in this file.
-    load({
-        { "file", CMAKE_CURRENT_SOURCE_DIR "/error-invalid.json" },
-    });
+	// Only a is the valid joke in this file.
+	load({{ "file", CMAKE_CURRENT_SOURCE_DIR "/error-invalid.json" }});
 
-    std::unordered_map<std::string, int> said{
-        { "a", 0 }
-    };
+	std::unordered_map<std::string, int> said{
+		{ "a", 0 }
+	};
 
-    const auto call = [&] () {
-        plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
+	const auto call = [&] () {
+		plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
 
-        const auto cmd = server_->find("message").back();
+		const auto cmd = server_->find("message").back();
 
-        BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
-        BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "a");
+		BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
+		BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "a");
 
-        server_->clear();
-        said[std::any_cast<std::string>(cmd[1])] += 1;
-    };
+		server_->clear();
+		said[std::any_cast<std::string>(cmd[1])] += 1;
+	};
 
-    call();
-    call();
-    call();
+	call();
+	call();
+	call();
 
-    BOOST_TEST(said.size() == 1U);
-    BOOST_TEST(said["a"] == 3U);
+	BOOST_TEST(said.size() == 1U);
+	BOOST_TEST(said["a"] == 3U);
 }
 
 BOOST_AUTO_TEST_SUITE(errors)
 
 BOOST_AUTO_TEST_CASE(not_found)
 {
-    load({{"file", "doesnotexist.json"}});
+	load({{"file", "doesnotexist.json"}});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_CASE(not_array)
 {
-    load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error-not-array.json"}});
+	load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error-not-array.json"}});
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#joke", "" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_CASE(empty)
 {
-    load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error-empty.json"}});
+	load({{"file", CMAKE_CURRENT_SOURCE_DIR "/error-empty.json"}});
 
-    plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#joke", ""});
+	plugin_->handle_command(irccd_, {server_, "jean!jean@localhost", "#joke", ""});
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#joke");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "error=test:#joke:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/logger/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/logger/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME plugin-logger
-    SOURCES main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/logger/logger.js"
+	NAME plugin-logger
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/logger/logger.js"
 )
--- a/tests/src/plugins/logger/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/logger/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,123 +33,123 @@
 
 class logger_test : public js_plugin_fixture {
 protected:
-    std::string last() const
-    {
-        std::ifstream file(CMAKE_CURRENT_BINARY_DIR "/log.txt");
+	std::string last() const
+	{
+		std::ifstream file(CMAKE_CURRENT_BINARY_DIR "/log.txt");
 
-        return std::string(std::istreambuf_iterator<char>(file.rdbuf()), {});
-    }
+		return std::string(std::istreambuf_iterator<char>(file.rdbuf()), {});
+	}
 
 public:
-    logger_test()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        remove(CMAKE_CURRENT_BINARY_DIR "/log.txt");
+	logger_test()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		remove(CMAKE_CURRENT_BINARY_DIR "/log.txt");
 
-        plugin_->set_formats({
-            { "join", "join=#{server}:#{channel}:#{origin}:#{nickname}" },
-            { "kick", "kick=#{server}:#{channel}:#{origin}:#{nickname}:#{target}:#{reason}" },
-            { "me", "me=#{server}:#{channel}:#{origin}:#{nickname}:#{message}" },
-            { "message", "message=#{server}:#{channel}:#{origin}:#{nickname}:#{message}" },
-            { "mode", "mode=#{server}:#{origin}:#{channel}:#{mode}:#{limit}:#{user}:#{mask}" },
-            { "notice", "notice=#{server}:#{origin}:#{channel}:#{message}" },
-            { "part", "part=#{server}:#{channel}:#{origin}:#{nickname}:#{reason}" },
-            { "query", "query=#{server}:#{origin}:#{nickname}:#{message}" },
-            { "topic", "topic=#{server}:#{channel}:#{origin}:#{nickname}:#{topic}" },
-        });
-    }
+		plugin_->set_formats({
+			{ "join", "join=#{server}:#{channel}:#{origin}:#{nickname}" },
+			{ "kick", "kick=#{server}:#{channel}:#{origin}:#{nickname}:#{target}:#{reason}" },
+			{ "me", "me=#{server}:#{channel}:#{origin}:#{nickname}:#{message}" },
+			{ "message", "message=#{server}:#{channel}:#{origin}:#{nickname}:#{message}" },
+			{ "mode", "mode=#{server}:#{origin}:#{channel}:#{mode}:#{limit}:#{user}:#{mask}" },
+			{ "notice", "notice=#{server}:#{origin}:#{channel}:#{message}" },
+			{ "part", "part=#{server}:#{channel}:#{origin}:#{nickname}:#{reason}" },
+			{ "query", "query=#{server}:#{origin}:#{nickname}:#{message}" },
+			{ "topic", "topic=#{server}:#{channel}:#{origin}:#{nickname}:#{topic}" },
+		});
+	}
 
-    void load(plugin::map config = {})
-    {
-        if (config.count("path") == 0)
-            config.emplace("path", CMAKE_CURRENT_BINARY_DIR "/log.txt");
+	void load(plugin::map config = {})
+	{
+		if (config.count("path") == 0)
+			config.emplace("path", CMAKE_CURRENT_BINARY_DIR "/log.txt");
 
-        plugin_->set_options(config);
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->set_options(config);
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(logger_test_suite, logger_test)
 
 BOOST_AUTO_TEST_CASE(format_join)
 {
-    load();
+	load();
 
-    plugin_->handle_join(irccd_, {server_, "jean!jean@localhost", "#staff"});
+	plugin_->handle_join(irccd_, {server_, "jean!jean@localhost", "#staff"});
 
-    BOOST_REQUIRE_EQUAL("join=test:#staff:jean!jean@localhost:jean\n", last());
+	BOOST_REQUIRE_EQUAL("join=test:#staff:jean!jean@localhost:jean\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_kick)
 {
-    load();
+	load();
 
-    plugin_->handle_kick(irccd_, {server_, "jean!jean@localhost", "#staff", "badboy", "please do not flood"});
+	plugin_->handle_kick(irccd_, {server_, "jean!jean@localhost", "#staff", "badboy", "please do not flood"});
 
-    BOOST_REQUIRE_EQUAL("kick=test:#staff:jean!jean@localhost:jean:badboy:please do not flood\n", last());
+	BOOST_REQUIRE_EQUAL("kick=test:#staff:jean!jean@localhost:jean:badboy:please do not flood\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_me)
 {
-    load();
+	load();
 
-    plugin_->handle_me(irccd_, {server_, "jean!jean@localhost", "#staff", "is drinking water"});
+	plugin_->handle_me(irccd_, {server_, "jean!jean@localhost", "#staff", "is drinking water"});
 
-    BOOST_REQUIRE_EQUAL("me=test:#staff:jean!jean@localhost:jean:is drinking water\n", last());
+	BOOST_REQUIRE_EQUAL("me=test:#staff:jean!jean@localhost:jean:is drinking water\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_message)
 {
-    load();
+	load();
 
-    plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#staff", "hello guys"});
+	plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#staff", "hello guys"});
 
-    BOOST_REQUIRE_EQUAL("message=test:#staff:jean!jean@localhost:jean:hello guys\n", last());
+	BOOST_REQUIRE_EQUAL("message=test:#staff:jean!jean@localhost:jean:hello guys\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_mode)
 {
-    load();
+	load();
 
-    plugin_->handle_mode(irccd_, {server_, "jean!jean@localhost", "chris", "+i", "l", "u", "m"});
+	plugin_->handle_mode(irccd_, {server_, "jean!jean@localhost", "chris", "+i", "l", "u", "m"});
 
-    BOOST_REQUIRE_EQUAL("mode=test:jean!jean@localhost:chris:+i:l:u:m\n", last());
+	BOOST_REQUIRE_EQUAL("mode=test:jean!jean@localhost:chris:+i:l:u:m\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_notice)
 {
-    load();
+	load();
 
-    plugin_->handle_notice(irccd_, {server_, "jean!jean@localhost", "chris", "tu veux voir mon chat ?"});
+	plugin_->handle_notice(irccd_, {server_, "jean!jean@localhost", "chris", "tu veux voir mon chat ?"});
 
-    BOOST_REQUIRE_EQUAL("notice=test:jean!jean@localhost:chris:tu veux voir mon chat ?\n", last());
+	BOOST_REQUIRE_EQUAL("notice=test:jean!jean@localhost:chris:tu veux voir mon chat ?\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_part)
 {
-    load();
+	load();
 
-    plugin_->handle_part(irccd_, {server_, "jean!jean@localhost", "#staff", "too noisy here"});
+	plugin_->handle_part(irccd_, {server_, "jean!jean@localhost", "#staff", "too noisy here"});
 
-    BOOST_REQUIRE_EQUAL("part=test:#staff:jean!jean@localhost:jean:too noisy here\n", last());
+	BOOST_REQUIRE_EQUAL("part=test:#staff:jean!jean@localhost:jean:too noisy here\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(format_topic)
 {
-    load();
+	load();
 
-    plugin_->handle_topic(irccd_, {server_, "jean!jean@localhost", "#staff", "oh yeah yeaaaaaaaah"});
+	plugin_->handle_topic(irccd_, {server_, "jean!jean@localhost", "#staff", "oh yeah yeaaaaaaaah"});
 
-    BOOST_REQUIRE_EQUAL("topic=test:#staff:jean!jean@localhost:jean:oh yeah yeaaaaaaaah\n", last());
+	BOOST_REQUIRE_EQUAL("topic=test:#staff:jean!jean@localhost:jean:oh yeah yeaaaaaaaah\n", last());
 }
 
 BOOST_AUTO_TEST_CASE(fix_642)
 {
-    load();
+	load();
 
-    plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#STAFF", "hello guys"});
+	plugin_->handle_message(irccd_, {server_, "jean!jean@localhost", "#STAFF", "hello guys"});
 
-    BOOST_REQUIRE_EQUAL("message=test:#staff:jean!jean@localhost:jean:hello guys\n", last());
+	BOOST_REQUIRE_EQUAL("message=test:#staff:jean!jean@localhost:jean:hello guys\n", last());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/plugin/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/plugin/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,8 +17,8 @@
 #
 
 irccd_define_test(
-    NAME plugin-plugin
-    SOURCES main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/plugin/plugin.js"
+	NAME plugin-plugin
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/plugin/plugin.js"
 )
--- a/tests/src/plugins/plugin/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/plugin/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -37,106 +37,106 @@
 
 class fake_plugin : public plugin {
 public:
-    using plugin::plugin;
+	using plugin::plugin;
 
-    auto get_name() const noexcept -> std::string_view override
-    {
-        return "fake";
-    }
+	auto get_name() const noexcept -> std::string_view override
+	{
+		return "fake";
+	}
 
-    auto get_author() const noexcept -> std::string_view override
-    {
-        return "jean";
-    }
+	auto get_author() const noexcept -> std::string_view override
+	{
+		return "jean";
+	}
 
-    auto get_version() const noexcept -> std::string_view override
-    {
-        return "0.0.0.0.0.1";
-    }
+	auto get_version() const noexcept -> std::string_view override
+	{
+		return "0.0.0.0.0.1";
+	}
 
-    auto get_license() const noexcept -> std::string_view override
-    {
-        return "BEER";
-    }
+	auto get_license() const noexcept -> std::string_view override
+	{
+		return "BEER";
+	}
 
-    auto get_summary() const noexcept -> std::string_view override
-    {
-        return "Fake White Beer 2000";
-    }
+	auto get_summary() const noexcept -> std::string_view override
+	{
+		return "Fake White Beer 2000";
+	}
 };
 
 class test_fixture : public js_plugin_fixture {
 public:
-    test_fixture()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        irccd_.plugins().add(std::make_shared<fake_plugin>("fake"));
+	test_fixture()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		irccd_.plugins().add(std::make_shared<fake_plugin>("fake"));
 
-        plugin_->set_formats({
-            { "usage", "usage=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" },
-            { "info", "info=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{author}:#{license}:#{name}:#{summary}:#{version}" },
-            { "not-found", "not-found=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{name}" },
-            { "too-long", "too-long=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" }
-        });
-        plugin_->handle_load(irccd_);
-    }
+		plugin_->set_formats({
+			{ "usage", "usage=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" },
+			{ "info", "info=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{author}:#{license}:#{name}:#{summary}:#{version}" },
+			{ "not-found", "not-found=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}:#{name}" },
+			{ "too-long", "too-long=#{plugin}:#{command}:#{server}:#{channel}:#{origin}:#{nickname}" }
+		});
+		plugin_->handle_load(irccd_);
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(test_fixture_suite, test_fixture)
 
 BOOST_AUTO_TEST_CASE(format_usage)
 {
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "" });
 
-    auto cmd = server_->find("message").front();
+	auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "fail" });
-    cmd = server_->find("message").front();
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "fail" });
+	cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info" });
-    cmd = server_->find("message").front();
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info" });
+	cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "usage=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_CASE(format_info)
 {
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info fake" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info fake" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "info=plugin:!plugin:test:#staff:jean!jean@localhost:jean:jean:BEER:fake:Fake White Beer 2000:0.0.0.0.0.1");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "info=plugin:!plugin:test:#staff:jean!jean@localhost:jean:jean:BEER:fake:Fake White Beer 2000:0.0.0.0.0.1");
 }
 
 BOOST_AUTO_TEST_CASE(format_not_found)
 {
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info doesnotexistsihope" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "info doesnotexistsihope" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "not-found=plugin:!plugin:test:#staff:jean!jean@localhost:jean:doesnotexistsihope");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "not-found=plugin:!plugin:test:#staff:jean!jean@localhost:jean:doesnotexistsihope");
 }
 
 BOOST_AUTO_TEST_CASE(format_too_long)
 {
-    for (int i = 0; i < 100; ++i)
-        irccd_.plugins().add(std::make_shared<fake_plugin>(str(format("plugin-n-%1%") % i)));
+	for (int i = 0; i < 100; ++i)
+		irccd_.plugins().add(std::make_shared<fake_plugin>(str(format("plugin-n-%1%") % i)));
 
-    plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "list" });
+	plugin_->handle_command(irccd_, { server_, "jean!jean@localhost", "#staff", "list" });
 
-    const auto cmd = server_->find("message").front();
+	const auto cmd = server_->find("message").front();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "too-long=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#staff");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "too-long=plugin:!plugin:test:#staff:jean!jean@localhost:jean");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/src/plugins/tictactoe/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/tictactoe/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -17,9 +17,9 @@
 #
 
 irccd_define_test(
-    NAME plugin-tictactoe
-    SOURCES main.cpp
-    LIBRARIES libirccd
-    FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/tictactoe/tictactoe.js"
+	NAME plugin-tictactoe
+	SOURCES main.cpp
+	LIBRARIES libirccd
+	FLAGS PLUGIN_PATH="${CMAKE_SOURCE_DIR}/plugins/tictactoe/tictactoe.js"
 )
 
--- a/tests/src/plugins/tictactoe/main.cpp	Wed Oct 24 13:24:03 2018 +0200
+++ b/tests/src/plugins/tictactoe/main.cpp	Fri Oct 26 13:01:00 2018 +0200
@@ -33,227 +33,227 @@
 
 class test_fixture : public js_plugin_fixture {
 public:
-    test_fixture()
-        : js_plugin_fixture(PLUGIN_PATH)
-    {
-        plugin_->set_formats({
-            { "draw",       "draw=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}"                },
-            { "invalid",    "invalid=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}"   },
-            { "running",    "running=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}"   },
-            { "turn",       "turn=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}"                },
-            { "used",       "used=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}"      },
-            { "win",        "win=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}"                 }
-        });
-    }
+	test_fixture()
+		: js_plugin_fixture(PLUGIN_PATH)
+	{
+		plugin_->set_formats({
+			{ "draw", "draw=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" },
+			{ "invalid", "invalid=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" },
+			{ "running", "running=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" },
+			{ "turn", "turn=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" },
+			{ "used", "used=#{channel}:#{command}:#{nickname}:#{origin}:#{plugin}:#{server}" },
+			{ "win", "win=#{channel}:#{command}:#{nickname}:#{plugin}:#{server}" }
+		});
+	}
 
-    auto next_players() const -> std::pair<std::string, std::string>
-    {
-        const auto functions = server_->find("message");
+	auto next_players() const -> std::pair<std::string, std::string>
+	{
+		const auto functions = server_->find("message");
 
-        if (functions.size() == 0U)
-            throw std::runtime_error("no message");
+		if (functions.size() == 0U)
+			throw std::runtime_error("no message");
 
-        const auto cmd = functions.back();
-        const auto list = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
+		const auto cmd = functions.back();
+		const auto list = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
 
-        BOOST_TEST(list.size() == 5U);
-        BOOST_TEST(list[0] == "turn=#tictactoe");
-        BOOST_TEST(list[1] == "!tictactoe");
-        BOOST_TEST(list[3] == "tictactoe");
-        BOOST_TEST(list[4] == "test");
+		BOOST_TEST(list.size() == 5U);
+		BOOST_TEST(list[0] == "turn=#tictactoe");
+		BOOST_TEST(list[1] == "!tictactoe");
+		BOOST_TEST(list[3] == "tictactoe");
+		BOOST_TEST(list[4] == "test");
 
-        return list[2] == "a" ? std::make_pair("a", "b") : std::make_pair("b", "a");
-    }
+		return list[2] == "a" ? std::make_pair("a", "b") : std::make_pair("b", "a");
+	}
 
-    auto start()
-    {
-        plugin_->handle_command(irccd_, { server_, "a!a@localhost", "#tictactoe", "b" });
-        plugin_->handle_names(irccd_, { server_, "#tictactoe", { "a", "b" }});
+	auto start()
+	{
+		plugin_->handle_command(irccd_, { server_, "a!a@localhost", "#tictactoe", "b" });
+		plugin_->handle_names(irccd_, { server_, "#tictactoe", { "a", "b" }});
 
-        return next_players();
-    }
+		return next_players();
+	}
 
-    /**
-     * Helper to place several tokens on the board and automatically toggling
-     * players.
-     *
-     * This will start the game from "a" with target opponent "b".
-     *
-     */
-    void run(const std::initializer_list<std::string>& points)
-    {
-        auto players = start();
+	/**
+	 * Helper to place several tokens on the board and automatically toggling
+	 * players.
+	 *
+	 * This will start the game from "a" with target opponent "b".
+	 *
+	 */
+	void run(const std::initializer_list<std::string>& points)
+	{
+		auto players = start();
 
-        for (const auto& p : points) {
-            server_->clear();
-            plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", p });
-            players = next_players();
-        }
-    }
+		for (const auto& p : points) {
+			server_->clear();
+			plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", p });
+			players = next_players();
+		}
+	}
 };
 
 BOOST_FIXTURE_TEST_SUITE(test_fixture_suite, test_fixture)
 
 BOOST_AUTO_TEST_CASE(win)
 {
-    run({ "a 1", "b1", "a 2", "b2" });
+	run({ "a 1", "b1", "a 2", "b2" });
 
-    const auto players = next_players();
+	const auto players = next_players();
 
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 3" });
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 3" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
 
-    const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
+	const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
 
-    BOOST_TEST(parts.size() == 5U);
-    BOOST_TEST(parts[0] == "win=#tictactoe");
-    BOOST_TEST(parts[1] == "!tictactoe");
-    BOOST_TEST(parts[2] == players.first);
-    BOOST_TEST(parts[3] == "tictactoe");
-    BOOST_TEST(parts[4] == "test");
+	BOOST_TEST(parts.size() == 5U);
+	BOOST_TEST(parts[0] == "win=#tictactoe");
+	BOOST_TEST(parts[1] == "!tictactoe");
+	BOOST_TEST(parts[2] == players.first);
+	BOOST_TEST(parts[3] == "tictactoe");
+	BOOST_TEST(parts[4] == "test");
 }
 
 BOOST_AUTO_TEST_CASE(draw)
 {
-    /*
-     *   a b c
-     * 1 o x o
-     * 2 o x x
-     * 3 x o x
-     */
-    run({ "b 2", "c 1", "c 3", "b 3", "c 2", "a 2", "a 3", "a 1" });
+	/*
+	 *   a b c
+	 * 1 o x o
+	 * 2 o x x
+	 * 3 x o x
+	 */
+	run({ "b 2", "c 1", "c 3", "b 3", "c 2", "a 2", "a 3", "a 1" });
 
-    const auto players = next_players();
+	const auto players = next_players();
 
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "b 1" });
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "b 1" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
 
-    const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
+	const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
 
-    BOOST_TEST(parts.size() == 5U);
-    BOOST_TEST(parts[0] == "draw=#tictactoe");
-    BOOST_TEST(parts[1] == "!tictactoe");
-    BOOST_TEST(parts[2] == players.first);
-    BOOST_TEST(parts[3] == "tictactoe");
-    BOOST_TEST(parts[4] == "test");
+	BOOST_TEST(parts.size() == 5U);
+	BOOST_TEST(parts[0] == "draw=#tictactoe");
+	BOOST_TEST(parts[1] == "!tictactoe");
+	BOOST_TEST(parts[2] == players.first);
+	BOOST_TEST(parts[3] == "tictactoe");
+	BOOST_TEST(parts[4] == "test");
 }
 
 BOOST_AUTO_TEST_CASE(used)
 {
-    auto players = start();
+	auto players = start();
 
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
-    plugin_->handle_message(irccd_, { server_, players.second, "#tictactoe", "a 1" });
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
+	plugin_->handle_message(irccd_, { server_, players.second, "#tictactoe", "a 1" });
 
-    const auto cmd = server_->find("message").back();
+	const auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
 
-    const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
+	const auto parts = string_util::split(std::any_cast<std::string>(cmd[1]), ":");
 
-    BOOST_TEST(parts[0] == "used=#tictactoe");
-    BOOST_TEST(parts[1] == "!tictactoe");
-    BOOST_TEST(parts[2] == players.second);
-    BOOST_TEST(parts[3] == players.second);
-    BOOST_TEST(parts[4] == "tictactoe");
-    BOOST_TEST(parts[5] == "test");
+	BOOST_TEST(parts[0] == "used=#tictactoe");
+	BOOST_TEST(parts[1] == "!tictactoe");
+	BOOST_TEST(parts[2] == players.second);
+	BOOST_TEST(parts[3] == players.second);
+	BOOST_TEST(parts[4] == "tictactoe");
+	BOOST_TEST(parts[5] == "test");
 }
 
 BOOST_AUTO_TEST_CASE(invalid)
 {
-    // empty name (no names)
-    plugin_->handle_command(irccd_, { server_, "jean", "#tictactoe", "" });
+	// empty name (no names)
+	plugin_->handle_command(irccd_, { server_, "jean", "#tictactoe", "" });
 
-    auto cmd = server_->find("message").back();
+	auto cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test");
 
-    // bot name (no names)
-    plugin_->handle_command(irccd_, { server_, "jean", "#tictactoe", "irccd" });
-    cmd = server_->find("message").back();
+	// bot name (no names)
+	plugin_->handle_command(irccd_, { server_, "jean", "#tictactoe", "irccd" });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:jean:jean:tictactoe:test");
 
-    // target is origin (no names)
-    plugin_->handle_command(irccd_, { server_, server_->get_nickname(), "#tictactoe", server_->get_nickname() });
-    cmd = server_->find("message").back();
+	// target is origin (no names)
+	plugin_->handle_command(irccd_, { server_, server_->get_nickname(), "#tictactoe", server_->get_nickname() });
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test");
 
-    // not existing (names)
-    plugin_->handle_command(irccd_, { server_, server_->get_nickname(), "#tictactoe", server_->get_nickname() });
-    plugin_->handle_names(irccd_, { server_, "#tictactoe", { "a", "b", "c" }});
-    cmd = server_->find("message").back();
+	// not existing (names)
+	plugin_->handle_command(irccd_, { server_, server_->get_nickname(), "#tictactoe", server_->get_nickname() });
+	plugin_->handle_names(irccd_, { server_, "#tictactoe", { "a", "b", "c" }});
+	cmd = server_->find("message").back();
 
-    BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
-    BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test");
+	BOOST_TEST(std::any_cast<std::string>(cmd[0]) == "#tictactoe");
+	BOOST_TEST(std::any_cast<std::string>(cmd[1]) == "invalid=#tictactoe:!tictactoe:irccd:irccd:tictactoe:test");
 }
 
 BOOST_AUTO_TEST_CASE(random)
 {
-    /*
-     * Ensure that the first player is not always the originator, start the game
-     * for at most 1'000'000 times to avoid forever loop.
-     */
-    unsigned count = 0;
-    bool a = false;
-    bool b = false;
+	/*
+	 * Ensure that the first player is not always the originator, start the game
+	 * for at most 1'000'000 times to avoid forever loop.
+	 */
+	unsigned count = 0;
+	bool a = false;
+	bool b = false;
 
-    // Last player turn is the winner.
-    while (!a && !b && count++ < 1000000U) {
-        run({ "a 1", "b 1", "a 2", "b 2" });
+	// Last player turn is the winner.
+	while (!a && !b && count++ < 1000000U) {
+		run({ "a 1", "b 1", "a 2", "b 2" });
 
-        const auto players = next_players();
+		const auto players = next_players();
 
-        if (players.first == "a")
-            a = true;
-        else
-            b = true;
+		if (players.first == "a")
+			a = true;
+		else
+			b = true;
 
-        plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 3" });
-    }
+		plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 3" });
+	}
 }
 
 BOOST_AUTO_TEST_CASE(disconnect)
 {
-    const auto players = start();
+	const auto players = start();
 
-    plugin_->handle_disconnect(irccd_, { server_ });
-    server_->clear();
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
+	plugin_->handle_disconnect(irccd_, { server_ });
+	server_->clear();
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
 
-    BOOST_TEST(server_->empty());
+	BOOST_TEST(server_->empty());
 }
 
 BOOST_AUTO_TEST_CASE(kick)
 {
-    const auto players = start();
+	const auto players = start();
 
-    server_->clear();
-    plugin_->handle_kick(irccd_, { server_, "kefka", "#tictactoe", players.first, "" });
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
+	server_->clear();
+	plugin_->handle_kick(irccd_, { server_, "kefka", "#tictactoe", players.first, "" });
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
 
-    BOOST_TEST(server_->empty());
+	BOOST_TEST(server_->empty());
 }
 
 BOOST_AUTO_TEST_CASE(part)
 {
-    const auto players = start();
+	const auto players = start();
 
-    server_->clear();
-    plugin_->handle_part(irccd_, { server_, players.first, "#tictactoe", "" });
-    plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
+	server_->clear();
+	plugin_->handle_part(irccd_, { server_, players.first, "#tictactoe", "" });
+	plugin_->handle_message(irccd_, { server_, players.first, "#tictactoe", "a 1" });
 
-    BOOST_TEST(server_->empty());
+	BOOST_TEST(server_->empty());
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/win32/CMakeLists.txt	Wed Oct 24 13:24:03 2018 +0200
+++ b/win32/CMakeLists.txt	Fri Oct 26 13:01:00 2018 +0200
@@ -30,15 +30,15 @@
 #
 
 if (MINGW)
-    if (IRCCD_64BITS)
-        set(LIBGCC_DLL libgcc_s_seh-1.dll)
-    else ()
-        set(LIBGCC_DLL libgcc_s_sjlj-1.dll)
-    endif ()
+	if (IRCCD_64BITS)
+		set(LIBGCC_DLL libgcc_s_seh-1.dll)
+	else ()
+		set(LIBGCC_DLL libgcc_s_sjlj-1.dll)
+	endif ()
 
-    set(LIBWINPTHREAD_DLL libwinpthread-1.dll)
-    set(LIBSTDCPP_DLL libstdc++-6.dll)
-    list(APPEND DLLS LIBGCC_DLL LIBWINPTHREAD_DLL LIBSTDCPP_DLL)
+	set(LIBWINPTHREAD_DLL libwinpthread-1.dll)
+	set(LIBSTDCPP_DLL libstdc++-6.dll)
+	list(APPEND DLLS LIBGCC_DLL LIBWINPTHREAD_DLL LIBSTDCPP_DLL)
 endif ()
 
 #
@@ -47,9 +47,9 @@
 #
 
 if (IRCCD_HAVE_SSL)
-    set(SSL_EAY_DLL libeay32.dll)
-    set(SSL_LIB_DLL ssleay32.dll)
-    list(APPEND DLLS SSL_EAY_DLL SSL_LIB_DLL)
+	set(SSL_EAY_DLL libeay32.dll)
+	set(SSL_LIB_DLL ssleay32.dll)
+	list(APPEND DLLS SSL_EAY_DLL SSL_LIB_DLL)
 endif ()
 
 #
@@ -65,28 +65,28 @@
 #
 
 foreach (name ${DLLS})
-    find_program(
-        IRCCD_WITH_${name}
-        NAMES ${${name}}
-        DOC "Path to DLL"
-    )
+	find_program(
+		IRCCD_WITH_${name}
+		NAMES ${${name}}
+		DOC "Path to DLL"
+	)
 
-    if (EXISTS ${IRCCD_WITH_${name}})
-        file(
-            COPY ${IRCCD_WITH_${name}}
-            DESTINATION ${IRCCD_FAKEROOTDIR}/${IRCCD_WITH_BINDIR}
-        )
-        install(
-            PROGRAMS ${IRCCD_WITH_${name}}
-            COMPONENT libirccd
-            DESTINATION bin
-        )
-        list(APPEND IRCCD_DLLS IRCCD_WITH_${name})
-    else ()
-        set(IRCCD_PACKAGE Off PARENT_SCOPE)
-        set(IRCCD_PACKAGE_MSG "No (some .dll were not found)" PARENT_SCOPE)
-        list(APPEND IRCCD_DLLS_NOT_FOUND IRCCD_WITH_${name})
-    endif ()
+	if (EXISTS ${IRCCD_WITH_${name}})
+		file(
+			COPY ${IRCCD_WITH_${name}}
+			DESTINATION ${IRCCD_FAKEROOTDIR}/${IRCCD_WITH_BINDIR}
+		)
+		install(
+			PROGRAMS ${IRCCD_WITH_${name}}
+			COMPONENT libirccd
+			DESTINATION bin
+		)
+		list(APPEND IRCCD_DLLS IRCCD_WITH_${name})
+	else ()
+		set(IRCCD_PACKAGE Off PARENT_SCOPE)
+		set(IRCCD_PACKAGE_MSG "No (some .dll were not found)" PARENT_SCOPE)
+		list(APPEND IRCCD_DLLS_NOT_FOUND IRCCD_WITH_${name})
+	endif ()
 endforeach ()
 
 set(IRCCD_DLLS ${IRCCD_DLLS} PARENT_SCOPE)