From 63eb02970fc19c2ba182be4c30d5dcd79e63f438 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 12 Jan 2022 16:51:02 +0100 Subject: [PATCH 001/223] Add a Menu::Insert method working with free functions as handler --- CHANGELOG.md | 1 + examples/complete.cpp | 6 +++++ include/cli/cli.h | 28 +++++++++++++++-------- include/cli/detail/genericasioremotecli.h | 6 ++--- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ee1fee..d1fd6f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Add a non-blocking exec method to schedulers (issue [#127](https://github.com/daniele77/cli/issues/127)) + - Add a Menu::Insert method working with free functions as handler ## [2.0.0] - 2021-08-25 diff --git a/examples/complete.cpp b/examples/complete.cpp index 3bd04dd..8aa4657 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -61,6 +61,8 @@ using namespace cli; using namespace std; +static void foo(std::ostream& out, int x) { out << x << std::endl; } + int main() { try @@ -71,6 +73,10 @@ int main() // setup cli auto rootMenu = make_unique("cli"); + rootMenu->Insert( + "free_function", + foo, + "Call a free function that echoes the parameter passed" ); rootMenu->Insert( "hello", [](std::ostream& out){ out << "Hello, world\n"; }, diff --git a/include/cli/cli.h b/include/cli/cli.h index 95b3aa4..95ab940 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -422,6 +422,9 @@ namespace cli Command(_name), parent(nullptr), description(std::move(desc)), cmds(std::make_shared()) {} + template + CmdHandler Insert(const std::string& cmdName, R (*f)(std::ostream&, Args...), const std::string& help, const std::vector& parDesc={}); + template CmdHandler Insert(const std::string& cmdName, F f, const std::string& help = "", const std::vector& parDesc={}) { @@ -564,27 +567,27 @@ namespace cli // ******************************************************************** - template + template struct Select; - template - struct Select + template + struct Select { - template + template static void Exec(const F& f, InputIt first, InputIt last) { assert( first != last ); assert( std::distance(first, last) == 1+sizeof...(Args) ); const P p = detail::from_string::type>(*first); auto g = [&](auto ... pars){ f(p, pars...); }; - Select::Exec(g, std::next(first), last); + Select::Exec(g, std::next(first), last); } }; - template - struct Select + template <> + struct Select<> { - template + template static void Exec(const F& f, InputIt first, InputIt last) { // silence the unused warning in release mode when assert is disabled @@ -646,7 +649,7 @@ namespace cli try { auto g = [&](auto ... pars){ func( session.OutStream(), pars... ); }; - Select::Exec(g, std::next(cmdLine.begin()), cmdLine.end()); + Select::Exec(g, std::next(cmdLine.begin()), cmdLine.end()); } catch (std::bad_cast&) { @@ -823,6 +826,13 @@ namespace cli // Menu implementation + template + CmdHandler Menu::Insert(const std::string& cmdName, R (*f)(std::ostream&, Args...), const std::string& help, const std::vector& parDesc) + { + using F = R (*)(std::ostream&, Args...); + return Insert(std::make_unique>(cmdName, f, help, parDesc)); + } + template CmdHandler Menu::Insert(const std::string& cmdName, const std::string& help, const std::vector& parDesc, F& f, R (F::*)(std::ostream& out, Args...) const ) { diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 5d6488c..a006a1d 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -77,13 +77,13 @@ class TelnetSession : public Session // https://www.ibm.com/support/knowledgecenter/SSLTBW_1.13.0/com.ibm.zos.r13.hald001/telcmds.htm - std::string iacDoLineMode{ "\x0FF\x0FD\x022", 3 }; + static const std::string iacDoLineMode{ "\x0FF\x0FD\x022", 3 }; this -> OutStream() << iacDoLineMode << std::flush; - std::string iacSbLineMode0IacSe{ "\x0FF\x0FA\x022\x001\x000\x0FF\x0F0", 7 }; + static const std::string iacSbLineMode0IacSe{ "\x0FF\x0FA\x022\x001\x000\x0FF\x0F0", 7 }; this -> OutStream() << iacSbLineMode0IacSe << std::flush; - std::string iacWillEcho{ "\x0FF\x0FB\x001", 3 }; + static const std::string iacWillEcho{ "\x0FF\x0FB\x001", 3 }; this -> OutStream() << iacWillEcho << std::flush; /* constexpr char IAC = '\x0FF'; // 255 From bb916eb4b206f5e1af9f2105bc1e749454020f51 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 30 Mar 2022 19:55:37 +0200 Subject: [PATCH 002/223] Remove nocolor command at start in example --- examples/complete.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/complete.cpp b/examples/complete.cpp index 8aa4657..9d1c3d4 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -171,6 +171,7 @@ int main() nocolorCmd.Disable(); }, "Disable colors in the cli" ); + nocolorCmd.Disable(); // start w/o colors, so we disable this command rootMenu->Insert( "removecmds", [&](std::ostream&) From 9d398548f60a1b1e77c8211f3bd5856d8843fbd1 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 30 Mar 2022 19:57:30 +0200 Subject: [PATCH 003/223] Add section "Menus and commands" in readme file --- README.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/README.md b/README.md index 2018aa2..53894da 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,97 @@ ioc.run(); ... ``` +## Adding menus and commands + +You must provide at least a root menu for your cli: + +``` +// create a menu (this is the root menu of our cli) +auto rootMenu = make_unique("myprompt"); + +... // fills rootMenu with commands + +// create the cli with the root menu +Cli cli(std::move(rootMenu)); + +``` + +You can add menus to existing menus, to get a hierarchy: + +``` +auto rootMenu = make_unique("myprompt"); + +auto menuA = make_unique("a_prompt"); +rootMenu->Insert( std::move(menuA) ); + +auto menuAA = make_unique("aa_prompt"); +menuA->Insert( std::move(menuAA) ); + +auto menuAB = make_unique("ab_prompt"); +menuA->Insert( std::move(menuAB) ); + +auto menuAC = make_unique("ac_prompt"); +menuA->Insert( std::move(menuAC) ); + +auto menuACA = make_unique("aca_prompt"); +menuAC->Insert( std::move(menuACA) ); + +auto menuB = make_unique("b_prompt"); +rootMenu->Insert( std::move(menuB) ); + +auto menuBA = make_unique("ba_prompt"); +menuB->Insert( std::move(menuBA) ); + +auto menuBB = make_unique("bb_prompt"); +menuB->Insert( std::move(menuBB) ); +``` + +This results in this tree: + +``` +myprompt + | + +--- a_prompt + | | + | +--- aa_prompt + | | + | +--- ab_prompt + | | + | +--- ac_prompt + | | + | +--- aca_prompt + | + +--- b_prompt + | + +--- ba_prompt + | + +--- bb_prompt + +``` + +Finally, you can add commands to menus, using the `Menu::Insert` method. +The library supports adding commands handler via: +- free functions +- `std::function` +- lambdas + +``` + +static void foo(std::ostream& out, int x) { out << x << std::endl; } + +std::function fun(foo); + +... + +myMenu->Insert("free_function", foo); + +myMenu->Insert("std_function", fun); + +myMenu->Insert("lambda", [](std::ostream& out, int x){ out << x << std::endl; } ); + +``` + + ## License Distributed under the Boost Software License, Version 1.0. From 3db8ab70a8daba7329cea43db7ea7a5a413d4c53 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 30 Mar 2022 20:18:08 +0200 Subject: [PATCH 004/223] Cli::cout() returns a class derived from std::ostream --- include/cli/cli.h | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 95ab940..418082e 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -81,29 +81,27 @@ namespace cli { // inner class to provide a global output stream - class OutStream + class OutStream : public std::basic_ostream, public std::streambuf { public: - template - OutStream& operator << (const T& msg) + OutStream() { - for (auto out: ostreams) - *out << msg; - return *this; + this->init(this); } - // this is the type of std::cout - using CoutType = std::basic_ostream >; - // this is the function signature of std::endl - using StandardEndLine = CoutType &(*)(CoutType &); - - // takes << std::endl - OutStream& operator << (StandardEndLine manip) + // std::streambuf overrides + std::streamsize xsputn(const char* s, std::streamsize n) override { - for (auto out: ostreams) - manip(*out); - return *this; + for (auto os: ostreams) + os->rdbuf()->sputn(s, n); + return n; } + int overflow(int c) override + { + for (auto os: ostreams) + *os << static_cast(c); + return c; + } private: friend class Cli; From 25c31d8ab11a73a94c2b1bb5a5605aaca5babae6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 30 Mar 2022 23:33:19 +0200 Subject: [PATCH 005/223] Fix address sanitizer issue with GenericAsioScheduler dtor --- CHANGELOG.md | 2 ++ include/cli/detail/genericasioscheduler.h | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1fd6f5..5b0063b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - Add a non-blocking exec method to schedulers (issue [#127](https://github.com/daniele77/cli/issues/127)) - Add a Menu::Insert method working with free functions as handler + - Cli::cout() returns a class derived from std::ostream + - Fix address sanitizer issue with GenericAsioScheduler dtor ## [2.0.0] - 2021-08-25 diff --git a/include/cli/detail/genericasioscheduler.h b/include/cli/detail/genericasioscheduler.h index 1cc2687..6252fbf 100644 --- a/include/cli/detail/genericasioscheduler.h +++ b/include/cli/detail/genericasioscheduler.h @@ -55,7 +55,14 @@ class GenericAsioScheduler : public Scheduler explicit GenericAsioScheduler(ContextType& _context) : context{&_context}, executor{*context} {} - ~GenericAsioScheduler() override { if (owned) delete context; } + ~GenericAsioScheduler() override + { + if (owned) + { + work.reset(); // work uses context, so it must be deleted before context + delete context; + } + } // non copyable GenericAsioScheduler(const GenericAsioScheduler&) = delete; From ae5eb7ed9733142c9691009513cf2f92d1775d1d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 31 Mar 2022 19:09:24 +0200 Subject: [PATCH 006/223] Fix teardown problem with linux (close issue #132) --- CHANGELOG.md | 1 + include/cli/detail/linuxkeyboard.h | 134 +++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b0063b..536e159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add a Menu::Insert method working with free functions as handler - Cli::cout() returns a class derived from std::ostream - Fix address sanitizer issue with GenericAsioScheduler dtor + - Fix teardown problem with linux (issue [#132](https://github.com/daniele77/cli/issues/132)) ## [2.0.0] - 2021-08-25 diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index ec9c568..37e10ba 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "inputdevice.h" @@ -46,37 +47,118 @@ namespace cli namespace detail { +class InputSource +{ +public: + + InputSource() + { + ToManualMode(); + int pipes[2]; + if (pipe(pipes) == 0) + { + shutdownPipe = pipes[1]; // we store the write end + readPipe = pipes[0]; // ... and the read end + } + } + ~InputSource() + { + ToStandardMode(); + } + + int Get() + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + FD_SET(readPipe, &rfds); + + while (select(readPipe + 1, &rfds, nullptr, nullptr, nullptr) == 0); + + if (FD_ISSET(readPipe, &rfds)) // stop called + { + close(readPipe); + throw std::runtime_error("InputSource stop"); + } + + if (FD_ISSET(STDIN_FILENO, &rfds)) // char from stdinput + { + return std::getchar(); + } + + // cannot reach this point + return -1; + } + + void Stop() + { + [[maybe_unused]] auto result = write(shutdownPipe, " ", 1); + result = close(shutdownPipe); + shutdownPipe = -1; + } + +private: + void ToManualMode() + { + constexpr tcflag_t ICANON_FLAG = ICANON; + constexpr tcflag_t ECHO_FLAG = ECHO; + + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~( ICANON_FLAG | ECHO_FLAG ); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + } + + void ToStandardMode() + { + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + } + + termios oldt; + termios newt; + int shutdownPipe; + int readPipe; +}; + +// + + class LinuxKeyboard : public InputDevice { public: explicit LinuxKeyboard(Scheduler& _scheduler) : - InputDevice(_scheduler) + InputDevice(_scheduler), + servant( [this]() noexcept { Read(); } ) { - ToManualMode(); - servant = std::make_unique( [this](){ Read(); } ); - servant->detach(); } ~LinuxKeyboard() override { - run = false; - ToStandardMode(); + is.Stop(); + servant.join(); } private: - void Read() + void Read() noexcept { - while ( run ) + try { - auto k = Get(); - Notify(k); + while (true) + { + auto k = Get(); + Notify(k); + } } + catch(const std::exception&) + { + // nothing to do: just exit + } } std::pair Get() { - int ch = std::getchar(); - switch( ch ) + int ch = is.Get(); + switch(ch) { case EOF: case 4: // EOT @@ -85,14 +167,14 @@ class LinuxKeyboard : public InputDevice case 127: return std::make_pair(KeyType::backspace,' '); break; case 10: return std::make_pair(KeyType::ret,' '); break; case 27: // symbol - ch = std::getchar(); + ch = is.Get(); if ( ch == 91 ) // arrow keys { - ch = std::getchar(); + ch = is.Get(); switch( ch ) { case 51: - ch = std::getchar(); + ch = is.Get(); if ( ch == 126 ) return std::make_pair(KeyType::canc,' '); else return std::make_pair(KeyType::ignored,' '); break; @@ -115,26 +197,8 @@ class LinuxKeyboard : public InputDevice return std::make_pair(KeyType::ignored,' '); } - void ToManualMode() - { - constexpr tcflag_t ICANON_FLAG = ICANON; - constexpr tcflag_t ECHO_FLAG = ECHO; - - tcgetattr( STDIN_FILENO, &oldt ); - newt = oldt; - newt.c_lflag &= ~( ICANON_FLAG | ECHO_FLAG ); - tcsetattr( STDIN_FILENO, TCSANOW, &newt ); - } - - void ToStandardMode() - { - tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); - } - - termios oldt; - termios newt; - std::atomic run{ true }; - std::unique_ptr servant; + InputSource is; + std::thread servant; }; } // namespace detail From ef2f89552f957a1542c4a68824486f360627c5e6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:49:01 +0200 Subject: [PATCH 007/223] Remove deprecated Cli method and impreve readme --- README.md | 32 +++++++++++++++++++++++++++++--- include/cli/cli.h | 14 -------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 53894da..d1167f7 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,9 @@ or, if you want to specify the installation path: ## Compilation of the examples You can find some examples in the directory "examples". -Each .cpp file corresponds to an executable. You can compile each example by including -cli (and optionally asio/boost header files) +Each .cpp file corresponds to an executable. +Each example can be compiled by including cli +(and optionally asio/boost header files) and linking pthread on linux (and optionally boost system). To compile the examples using cmake, use: @@ -92,7 +93,7 @@ In the same directory you can also find: * Windows nmake files (makefile.noasio.win, makefile.boostasio.win, makefile.standaloneasio.win) * a Visual Studio solution -You can specify boost/asio library path in the following ways: +If needed, you can specify asio library path in the following ways: ### GNU Make @@ -147,6 +148,31 @@ of the library in this way: ## CLI usage +### Commands and shortcuts + +At the start of your application, cli is presenting a prompt with the +name you provided in the `Cli` constructor. +This means you're in the root menu. + +To enter in a submenu, just type the submenu name: +you should see the prompt change to reflect the name of the current submenu. + +To go back to the parent menu, you must enter the name of the parent menu. + +In any menu, you can enter: +- `exit`: to exit the cli +- `help`: to print the list of the commands available with a description +- a submenu name: to enter the submenu +- the parent menu name: to return to the the parent menu +- a command in the current menu: to exec the command +- a command in a submenu (using the full path): to exec the command + +You can also use: +- up and down arrow keys: to navigate the history of commands +- tab key: to autocomplete the command / menu + +### Parameter parsing + The cli interpreter can manage correctly sentences using quote (') and double quote ("). Any character (spaces too) comprises between quotes or double quotes are considered as a single parameter of a command. The characters ' and " can be used inside a command parameter by escaping them with a backslash. diff --git a/include/cli/cli.h b/include/cli/cli.h index 418082e..0c68773 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -128,20 +128,6 @@ namespace cli Cli(Cli&&) = default; Cli& operator = (Cli&&) = default; - /// \deprecated Use the @c Cli::Cli(std::unique_ptr,std::unique_ptr) - /// overload version and the method @c Cli::ExitAction instead - [[deprecated("Use the other overload of Cli constructor and the method Cli::ExitAction instead")]] - explicit Cli( - std::unique_ptr&& _rootMenu, - std::function< void(std::ostream&)> _exitAction, - std::unique_ptr&& historyStorage = std::make_unique() - ) : - globalHistoryStorage(std::move(historyStorage)), - rootMenu(std::move(_rootMenu)), - exitAction(std::move(_exitAction)) - { - } - /** * @brief Construct a new Cli object having a given root menu that contains the first level commands available. * From 40a0475f425ded52187ebeaa8d0b95098d473dbd Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 12:34:08 +0200 Subject: [PATCH 008/223] Fix linuxkeyboard when special keys are pressed --- include/cli/detail/linuxkeyboard.h | 61 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 37e10ba..0b1ad71 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -32,12 +32,12 @@ #include #include -#include #include #include #include #include +#include #include "inputdevice.h" @@ -53,7 +53,6 @@ class InputSource InputSource() { - ToManualMode(); int pipes[2]; if (pipe(pipes) == 0) { @@ -61,12 +60,8 @@ class InputSource readPipe = pipes[0]; // ... and the read end } } - ~InputSource() - { - ToStandardMode(); - } - int Get() + void WaitKbHit() { fd_set rfds; FD_ZERO(&rfds); @@ -83,11 +78,11 @@ class InputSource if (FD_ISSET(STDIN_FILENO, &rfds)) // char from stdinput { - return std::getchar(); + return; } // cannot reach this point - return -1; + assert(false); } void Stop() @@ -98,24 +93,6 @@ class InputSource } private: - void ToManualMode() - { - constexpr tcflag_t ICANON_FLAG = ICANON; - constexpr tcflag_t ECHO_FLAG = ECHO; - - tcgetattr(STDIN_FILENO, &oldt); - newt = oldt; - newt.c_lflag &= ~( ICANON_FLAG | ECHO_FLAG ); - tcsetattr(STDIN_FILENO, TCSANOW, &newt); - } - - void ToStandardMode() - { - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); - } - - termios oldt; - termios newt; int shutdownPipe; int readPipe; }; @@ -130,9 +107,11 @@ class LinuxKeyboard : public InputDevice InputDevice(_scheduler), servant( [this]() noexcept { Read(); } ) { + ToManualMode(); } ~LinuxKeyboard() override { + ToStandardMode(); is.Stop(); servant.join(); } @@ -157,7 +136,9 @@ class LinuxKeyboard : public InputDevice std::pair Get() { - int ch = is.Get(); + is.WaitKbHit(); + + int ch = std::getchar(); switch(ch) { case EOF: @@ -167,14 +148,14 @@ class LinuxKeyboard : public InputDevice case 127: return std::make_pair(KeyType::backspace,' '); break; case 10: return std::make_pair(KeyType::ret,' '); break; case 27: // symbol - ch = is.Get(); + ch = std::getchar(); if ( ch == 91 ) // arrow keys { - ch = is.Get(); + ch = std::getchar(); switch( ch ) { case 51: - ch = is.Get(); + ch = std::getchar(); if ( ch == 126 ) return std::make_pair(KeyType::canc,' '); else return std::make_pair(KeyType::ignored,' '); break; @@ -197,6 +178,24 @@ class LinuxKeyboard : public InputDevice return std::make_pair(KeyType::ignored,' '); } + void ToManualMode() + { + constexpr tcflag_t ICANON_FLAG = ICANON; + constexpr tcflag_t ECHO_FLAG = ECHO; + + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~( ICANON_FLAG | ECHO_FLAG ); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + } + + void ToStandardMode() + { + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + } + + termios oldt; + termios newt; InputSource is; std::thread servant; }; From 719bbb15fa35769ad6c7d77bee1f406053a85385 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 15:32:33 +0200 Subject: [PATCH 009/223] Fix compilation bug in windows --- include/cli/cli.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 418082e..ad58f5f 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -84,9 +84,8 @@ namespace cli class OutStream : public std::basic_ostream, public std::streambuf { public: - OutStream() + OutStream() : std::basic_ostream(this) { - this->init(this); } // std::streambuf overrides @@ -304,7 +303,7 @@ namespace cli CliSession(CliSession&&) = delete; CliSession& operator = (CliSession&&) = delete; - void Feed( const std::string& cmd ); + void Feed(const std::string& cmd); void Prompt(); From c2917aed1b9b17c77ca4621ed83e48da3e66f2eb Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 15:36:52 +0200 Subject: [PATCH 010/223] Silence warning issue --- include/cli/detail/linuxkeyboard.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 0b1ad71..d92e176 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -87,8 +87,9 @@ class InputSource void Stop() { - [[maybe_unused]] auto result = write(shutdownPipe, " ", 1); - result = close(shutdownPipe); + auto unused = write(shutdownPipe, " ", 1); + unused = close(shutdownPipe); + static_cast(unused); // silence unused warn shutdownPipe = -1; } From 28fcaa8d5da5fff925995aee7d3c6225b9672a43 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 15:46:33 +0200 Subject: [PATCH 011/223] The prompt is no more shown after exit --- CHANGELOG.md | 1 + include/cli/cli.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 536e159..30f3060 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Cli::cout() returns a class derived from std::ostream - Fix address sanitizer issue with GenericAsioScheduler dtor - Fix teardown problem with linux (issue [#132](https://github.com/daniele77/cli/issues/132)) + - The prompt is no more shown after exit ## [2.0.0] - 2021-08-25 diff --git a/include/cli/cli.h b/include/cli/cli.h index ad58f5f..f51a45f 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -320,6 +320,8 @@ namespace cli auto cmds = history.GetCommands(); cli.StoreCommands(cmds); + + exit = true; // prevent the prompt to be shown } void ExitAction(const std::function& action) @@ -349,6 +351,7 @@ namespace cli std::ostream& out; std::function< void(std::ostream&)> exitAction = []( std::ostream& ){}; detail::History history; + bool exit{ false }; // to prevent the prompt after exit command }; // ******************************************************************** @@ -791,6 +794,7 @@ namespace cli inline void CliSession::Prompt() { + if (exit) return; out << beforePrompt << current->Prompt() << afterPrompt From da1c2847a2bfa42c363e93f9919844826b26f44f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 1 Apr 2022 16:33:40 +0200 Subject: [PATCH 012/223] Fix teardown problem with windows --- CHANGELOG.md | 1 + include/cli/clilocalsession.h | 2 +- include/cli/detail/winkeyboard.h | 84 +++++++++++++++++++++++++++----- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f3060..4f8f46d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Cli::cout() returns a class derived from std::ostream - Fix address sanitizer issue with GenericAsioScheduler dtor - Fix teardown problem with linux (issue [#132](https://github.com/daniele77/cli/issues/132)) + - Fix teardown problem with windows - The prompt is no more shown after exit ## [2.0.0] - 2021-08-25 diff --git a/include/cli/clilocalsession.h b/include/cli/clilocalsession.h index 241a8b8..b9dc82e 100644 --- a/include/cli/clilocalsession.h +++ b/include/cli/clilocalsession.h @@ -31,9 +31,9 @@ #define CLI_CLILOCALSESSION_H #include // std::ostream -#include "detail/keyboard.h" #include "detail/inputhandler.h" #include "cli.h" // CliSession +#include "detail/keyboard.h" namespace cli { diff --git a/include/cli/detail/winkeyboard.h b/include/cli/detail/winkeyboard.h index cea4d2c..18a3ead 100644 --- a/include/cli/detail/winkeyboard.h +++ b/include/cli/detail/winkeyboard.h @@ -34,41 +34,101 @@ #include #include #include -#include #include +#include #include "inputdevice.h" +#include + namespace cli { namespace detail { +class InputSource +{ +public: + + InputSource() + { + events[0] = CreateEvent(nullptr, FALSE, FALSE, nullptr); // Obtain a Windows handle to use to stop + events[1] = GetStdHandle(STD_INPUT_HANDLE); // Get a Windows handle to the keyboard input + } + + void WaitKbHit() + { + // Wait for either the timer to expire or a key press event + DWORD dwResult = WaitForMultipleObjects(2, events, false, INFINITE); + + if (dwResult == WAIT_FAILED) + { + // TODO + assert(false); + } + else + { + if (dwResult == WAIT_OBJECT_0) // WAIT_OBJECT_0 corresponds to the stop event + { + throw std::runtime_error("InputSource stop"); + } + else + { + return; + } + } + + // we can't reach this point + assert(false); + } + + void Stop() + { + SetEvent(events[0]); + } + +private: + HANDLE events[2]; +}; + +// + class WinKeyboard : public InputDevice { public: - explicit WinKeyboard(Scheduler& _scheduler) : InputDevice(_scheduler) + explicit WinKeyboard(Scheduler& _scheduler) : + InputDevice(_scheduler), + servant([this]() noexcept { Read(); }) { - servant = std::make_unique( [this](){ Read(); } ); - servant->detach(); } - ~WinKeyboard() + ~WinKeyboard() override { - run = false; + is.Stop(); + servant.join(); } private: - void Read() + + void Read() noexcept { - while (run) + try + { + while (true) + { + auto k = Get(); + Notify(k); + } + } + catch (const std::exception&) { - auto k = Get(); - Notify(k); + // nothing to do: just exit } } std::pair Get() { + is.WaitKbHit(); + int c = _getch(); switch (c) { @@ -109,8 +169,8 @@ class WinKeyboard : public InputDevice return std::make_pair(KeyType::ignored, ' '); } - std::atomic run{true}; - std::unique_ptr servant; + InputSource is; + std::thread servant; }; } // namespace detail From 9ce4c7280707c0d76de102a217aed97d63c01586 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 14 Apr 2022 23:58:19 +0200 Subject: [PATCH 013/223] Telnet server now works on MobaXTerm --- CHANGELOG.md | 1 + include/cli/detail/genericasioremotecli.h | 86 ++++++++++------------- 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f8f46d..72f13e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix teardown problem with linux (issue [#132](https://github.com/daniele77/cli/issues/132)) - Fix teardown problem with windows - The prompt is no more shown after exit + - Telnet server now works on MobaXTerm ## [2.0.0] - 2021-08-25 diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index a006a1d..f35348b 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -85,6 +85,7 @@ class TelnetSession : public Session static const std::string iacWillEcho{ "\x0FF\x0FB\x001", 3 }; this -> OutStream() << iacWillEcho << std::flush; + /* constexpr char IAC = '\x0FF'; // 255 constexpr char DO = '\x0FD'; // 253 @@ -200,7 +201,14 @@ class TelnetSession : public Session // or confirmation that you are no // longer expecting the other party // to perform, the indicated option. - IAC = '\x0FF' // Data Byte 255. + IAC = '\x0FF', // Data Byte 255. + + ECHO = '\x001', + SUPPRESS_GO_AHEAD = '\x003', + TERMINAL_TYPE = '\x018', + NEGOTIATE_ABOUT_WIN_SIZE = '\x01F', + TERMINAL_SPEED = '\x020', + NEW_ENV_OPTION = '\x027' }; @@ -217,15 +225,10 @@ class TelnetSession : public Session if (escape) { if (c == IAC) - { Data(c); - escape = false; - } else - { Command(c); - escape = false; - } + escape = false; } else { @@ -244,22 +247,22 @@ class TelnetSession : public Session Output(c); break; case State::sub: - Sub(c); + RxSub(c); break; case State::wait_will: - Will(c); + RxWill(c); state = State::data; break; case State::wait_wont: - Wont(c); + RxWont(c); state = State::data; break; case State::wait_do: - Do(c); + RxDo(c); state = State::data; break; case State::wait_dont: - Dont(c); + RxDont(c); state = State::data; break; } @@ -333,15 +336,21 @@ class TelnetSession : public Session } } - void Will(char c) + void RxWill(char c) { #ifdef CLI_TELNET_TRACE std::cout << "will " << static_cast(c) << std::endl; - #else - (void)c; #endif + switch(c) + { + case SUPPRESS_GO_AHEAD: Send(WILL, SUPPRESS_GO_AHEAD); break; + case TERMINAL_TYPE: Send(DO, TERMINAL_TYPE); break; + case NEGOTIATE_ABOUT_WIN_SIZE: Send(DO, NEGOTIATE_ABOUT_WIN_SIZE); break; + case TERMINAL_SPEED: Send(DONT, TERMINAL_SPEED); break; + case NEW_ENV_OPTION: Send(DONT, NEW_ENV_OPTION); break; + }; } - void Wont(char c) + void RxWont(char c) { #ifdef CLI_TELNET_TRACE std::cout << "wont " << static_cast(c) << std::endl; @@ -349,15 +358,15 @@ class TelnetSession : public Session (void)c; #endif } - void Do(char c) + void RxDo(char c) { #ifdef CLI_TELNET_TRACE std::cout << "do " << static_cast(c) << std::endl; - #else - (void)c; #endif + if (c == ECHO) // do echo + Send(DO, ECHO); } - void Dont(char c) + void RxDont(char c) { #ifdef CLI_TELNET_TRACE std::cout << "dont " << static_cast(c) << std::endl; @@ -365,7 +374,7 @@ class TelnetSession : public Session (void)c; #endif } - void Sub(char c) + void RxSub(char c) { #ifdef CLI_TELNET_TRACE std::cout << "sub: " << static_cast(c) << std::endl; @@ -373,6 +382,13 @@ class TelnetSession : public Session (void)c; #endif } + void Send(char action, char op) + { + std::string answer("\x0FF\x000\x000", 3); + answer[1] = action; + answer[2] = op; + this -> OutStream() << answer << std::flush; + } protected: virtual void Output(char c) { @@ -394,36 +410,8 @@ class TelnetSession : public Session { if (std::isprint(c)) std::cout << c << std::endl; else std::cout << "0x" << std::hex << static_cast(c) << std::dec << std::endl; -/* - switch ( c ) - { - case 0: break; - case '\n': - case '\r': - { - // trim trailing spaces - std::size_t endpos = buffer.find_last_not_of(" \t\r\n"); - if( std::string::npos != endpos ) buffer = buffer.substr( 0, endpos+1 ); - if ( cliSession.Feed( buffer ) ) cliSession.Prompt(); - else Disconnect(); - - buffer.clear(); - break; - } - default: - Echo( c ); - buffer += c; - } -*/ - } -/* - void Echo( char c ) - { - this -> OutStream() << c << std::flush; } -*/ std::string buffer; - //bool waitAck = false; }; template From fa826b0f9567985502ddf1a1f4e997d787013c32 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 15 Apr 2022 00:08:30 +0200 Subject: [PATCH 014/223] Fix compilation issue with gcc --- include/cli/detail/genericasioremotecli.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index f35348b..7bb931d 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -203,7 +203,7 @@ class TelnetSession : public Session // to perform, the indicated option. IAC = '\x0FF', // Data Byte 255. - ECHO = '\x001', + _ECHO = '\x001', SUPPRESS_GO_AHEAD = '\x003', TERMINAL_TYPE = '\x018', NEGOTIATE_ABOUT_WIN_SIZE = '\x01F', @@ -343,11 +343,11 @@ class TelnetSession : public Session #endif switch(c) { - case SUPPRESS_GO_AHEAD: Send(WILL, SUPPRESS_GO_AHEAD); break; - case TERMINAL_TYPE: Send(DO, TERMINAL_TYPE); break; - case NEGOTIATE_ABOUT_WIN_SIZE: Send(DO, NEGOTIATE_ABOUT_WIN_SIZE); break; - case TERMINAL_SPEED: Send(DONT, TERMINAL_SPEED); break; - case NEW_ENV_OPTION: Send(DONT, NEW_ENV_OPTION); break; + case SUPPRESS_GO_AHEAD: SendIacCmd(WILL, SUPPRESS_GO_AHEAD); break; + case TERMINAL_TYPE: SendIacCmd(DO, TERMINAL_TYPE); break; + case NEGOTIATE_ABOUT_WIN_SIZE: SendIacCmd(DO, NEGOTIATE_ABOUT_WIN_SIZE); break; + case TERMINAL_SPEED: SendIacCmd(DONT, TERMINAL_SPEED); break; + case NEW_ENV_OPTION: SendIacCmd(DONT, NEW_ENV_OPTION); break; }; } void RxWont(char c) @@ -363,8 +363,8 @@ class TelnetSession : public Session #ifdef CLI_TELNET_TRACE std::cout << "do " << static_cast(c) << std::endl; #endif - if (c == ECHO) // do echo - Send(DO, ECHO); + if (c == _ECHO) // do echo + SendIacCmd(DO, _ECHO); } void RxDont(char c) { @@ -382,7 +382,7 @@ class TelnetSession : public Session (void)c; #endif } - void Send(char action, char op) + void SendIacCmd(char action, char op) { std::string answer("\x0FF\x000\x000", 3); answer[1] = action; From 59a94a83d1ebe7711029deb21d15368b0939833b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 19 Apr 2022 11:08:53 +0200 Subject: [PATCH 015/223] Manages new telnet options --- include/cli/detail/genericasioremotecli.h | 33 +++++++++++++++++------ 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 7bb931d..59459a2 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -167,6 +167,12 @@ class TelnetSession : public Session } #else + /* + See + https://www.iana.org/assignments/telnet-options/telnet-options.xhtml + for a list of telnet options + */ + enum { SE = '\x0F0', // End of subnegotiation parameters. @@ -211,7 +217,6 @@ class TelnetSession : public Session NEW_ENV_OPTION = '\x027' }; - void OnDataReceived(const std::string& _data) override { for (char c: _data) @@ -343,11 +348,14 @@ class TelnetSession : public Session #endif switch(c) { - case SUPPRESS_GO_AHEAD: SendIacCmd(WILL, SUPPRESS_GO_AHEAD); break; - case TERMINAL_TYPE: SendIacCmd(DO, TERMINAL_TYPE); break; - case NEGOTIATE_ABOUT_WIN_SIZE: SendIacCmd(DO, NEGOTIATE_ABOUT_WIN_SIZE); break; - case TERMINAL_SPEED: SendIacCmd(DONT, TERMINAL_SPEED); break; - case NEW_ENV_OPTION: SendIacCmd(DONT, NEW_ENV_OPTION); break; + case SUPPRESS_GO_AHEAD: + SendIacCmd(WILL, SUPPRESS_GO_AHEAD); + break; + case NEGOTIATE_ABOUT_WIN_SIZE: + SendIacCmd(DO, NEGOTIATE_ABOUT_WIN_SIZE); + break; + default: + SendIacCmd(DONT, c); }; } void RxWont(char c) @@ -363,8 +371,17 @@ class TelnetSession : public Session #ifdef CLI_TELNET_TRACE std::cout << "do " << static_cast(c) << std::endl; #endif - if (c == _ECHO) // do echo - SendIacCmd(DO, _ECHO); + switch (c) + { + case _ECHO: + SendIacCmd(DO, _ECHO); + break; + case SUPPRESS_GO_AHEAD: + SendIacCmd(WILL, SUPPRESS_GO_AHEAD); + break; + default: + SendIacCmd(WONT, c); + }; } void RxDont(char c) { From da698ced7591d0176ec21002b3e180bb4c1f33ec Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 19 Apr 2022 11:39:33 +0200 Subject: [PATCH 016/223] Add NOMINMAX definition to prevent windows header from defining min and max macros --- include/cli/detail/winkeyboard.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/cli/detail/winkeyboard.h b/include/cli/detail/winkeyboard.h index 18a3ead..0ed159d 100644 --- a/include/cli/detail/winkeyboard.h +++ b/include/cli/detail/winkeyboard.h @@ -39,6 +39,9 @@ #include "inputdevice.h" +#if !defined(NOMINMAX) +#define NOMINMAX 1 // prevent windows from defining min and max macros +#endif // !defined(NOMINMAX) #include namespace cli From df185bc827a2008a53d87d5c54f49a20923dc868 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:08:21 +0200 Subject: [PATCH 017/223] Bump version --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- README.md | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72f13e5..8babb7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## [2.0.1] - 2022-04-19 - Add a non-blocking exec method to schedulers (issue [#127](https://github.com/daniele77/cli/issues/127)) - Add a Menu::Insert method working with free functions as handler diff --git a/CMakeLists.txt b/CMakeLists.txt index 777943d..284a68a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ cmake_minimum_required(VERSION 3.8) -project(cli VERSION 2.0.0 +project(cli VERSION 2.0.1 # DESCRIPTION "A library for interactive command line interfaces in modern C++" LANGUAGES CXX) diff --git a/README.md b/README.md index d1167f7..116156a 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,34 @@ myMenu->Insert("lambda", [](std::ostream& out, int x){ out << x << std::endl; } ``` +There is no limit to the number of parameters that a command handler can take +(however, they can only be basic types or `std::string`s): + +``` +myMenu->Insert( + "mycmd", + [](std::ostream& out, int a, double b, const std::string& c, bool d, long e) + { + ... + } ); + +``` + +If you need it, you can have a command handlers taking an arbitrary +number of string parameters: + +``` +myMenu->Insert( + "mycmd", + [](std::ostream& out, const std::vector& pars) + { + ... + } ); + +``` + +Please note that in this case your command handler must take *only one* +parameter of type `std::vector`. ## License From 898af701465aff96030af643e04a84bd918ae297 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 2 May 2022 22:52:52 +0200 Subject: [PATCH 018/223] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8babb7c..6b74cf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # Changelog +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [2.0.1] - 2022-04-19 From 0a4d86089e6d92c1156708189d8aca18c743b63d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 27 Jun 2022 11:02:02 +0200 Subject: [PATCH 019/223] Specifies signed for char parameters --- include/cli/detail/genericasioremotecli.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 59459a2..6c5d07c 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -219,13 +219,13 @@ class TelnetSession : public Session void OnDataReceived(const std::string& _data) override { - for (char c: _data) + for (auto c: _data) Consume(c); } private: - void Consume(char c) + void Consume(signed char c) { if (escape) { @@ -244,7 +244,7 @@ class TelnetSession : public Session } } - void Data(char c) + void Data(signed char c) { switch(state) { @@ -407,7 +407,7 @@ class TelnetSession : public Session this -> OutStream() << answer << std::flush; } protected: - virtual void Output(char c) + virtual void Output(signed char c) { #ifdef CLI_TELNET_TRACE std::cout << "data: " << static_cast(c) << std::endl; @@ -466,7 +466,7 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes Prompt(); } - void Output(char c) override + void Output(signed char c) override // NB: C++ does not specify wether char is signed or unsigned { switch(step) { From 63e2f2c04528b92780599a4dc2da54bc5fb82011 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 27 Jun 2022 11:08:04 +0200 Subject: [PATCH 020/223] Closes #149 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b74cf4..0ac0a43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + + - Specify signed for char parameters (issue [#149](https://github.com/daniele77/cli/issues/149)) + ## [2.0.1] - 2022-04-19 - Add a non-blocking exec method to schedulers (issue [#127](https://github.com/daniele77/cli/issues/127)) From b2bcd1eaba6dff03b73ac8ad8b10aa632a80f47c Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:37:03 +0200 Subject: [PATCH 021/223] CliSession can call OutStream::UnRegister() when it's dead (Close #153) --- CHANGELOG.md | 1 + include/cli/cli.h | 93 ++++++++++++++++++++++++----------------------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac0a43..6afcb0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased - Specify signed for char parameters (issue [#149](https://github.com/daniele77/cli/issues/149)) + - CliSession can call OutStream::UnRegister() when it's already destroyed (issue [#153](https://github.com/daniele77/cli/issues/153)) ## [2.0.1] - 2022-04-19 diff --git a/include/cli/cli.h b/include/cli/cli.h index df28848..0a6361f 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -72,51 +72,49 @@ namespace cli // ******************************************************************** - // forward declarations - class Menu; - class CliSession; - - - class Cli + // this class provides a global output stream + class OutStream : public std::basic_ostream, public std::streambuf { + public: + OutStream() : std::basic_ostream(this) + { + } - // inner class to provide a global output stream - class OutStream : public std::basic_ostream, public std::streambuf + // std::streambuf overrides + std::streamsize xsputn(const char* s, std::streamsize n) override { - public: - OutStream() : std::basic_ostream(this) - { - } + for (auto os: ostreams) + os->rdbuf()->sputn(s, n); + return n; + } + int overflow(int c) override + { + for (auto os: ostreams) + *os << static_cast(c); + return c; + } - // std::streambuf overrides - std::streamsize xsputn(const char* s, std::streamsize n) override - { - for (auto os: ostreams) - os->rdbuf()->sputn(s, n); - return n; - } - int overflow(int c) override - { - for (auto os: ostreams) - *os << static_cast(c); - return c; - } + void Register(std::ostream& o) + { + ostreams.push_back(&o); + } + void UnRegister(std::ostream& o) + { + ostreams.erase(std::remove(ostreams.begin(), ostreams.end(), &o), ostreams.end()); + } - private: - friend class Cli; + private: - void Register(std::ostream& o) - { - ostreams.push_back(&o); - } - void UnRegister(std::ostream& o) - { - ostreams.erase(std::remove(ostreams.begin(), ostreams.end(), &o), ostreams.end()); - } + std::vector ostreams; + }; + + // forward declarations + class Menu; + class CliSession; + + class Cli + { - std::vector ostreams; - }; - // end inner class public: ~Cli() = default; @@ -172,13 +170,18 @@ namespace cli */ static OutStream& cout() { - static OutStream s; - return s; + return *CoutPtr(); } private: friend class CliSession; + static std::shared_ptr CoutPtr() + { + static std::shared_ptr s = std::make_shared(); + return s; + } + Menu* RootMenu() { return rootMenu.get(); } void ExitAction( std::ostream& out ) @@ -195,10 +198,6 @@ namespace cli out << e.what() << '\n'; } - static void Register(std::ostream& o) { cout().Register(o); } - - static void UnRegister(std::ostream& o) { cout().UnRegister(o); } - void StoreCommands(const std::vector& cmds) { globalHistoryStorage->Store(cmds); @@ -280,7 +279,7 @@ namespace cli { public: CliSession(Cli& _cli, std::ostream& _out, std::size_t historySize = 100); - virtual ~CliSession() noexcept { Cli::UnRegister(out); } + virtual ~CliSession() noexcept { coutPtr->UnRegister(out); } // disable value semantics CliSession(const CliSession&) = delete; @@ -332,6 +331,7 @@ namespace cli private: Cli& cli; + std::shared_ptr coutPtr; Menu* current; std::unique_ptr globalScopeMenu; std::ostream& out; @@ -719,6 +719,7 @@ namespace cli inline CliSession::CliSession(Cli& _cli, std::ostream& _out, std::size_t historySize) : cli(_cli), + coutPtr(Cli::CoutPtr()), current(cli.RootMenu()), globalScopeMenu(std::make_unique< Menu >()), out(_out), @@ -726,7 +727,7 @@ namespace cli { history.LoadCommands(cli.GetCommands()); - Cli::Register(out); + coutPtr->Register(out); globalScopeMenu->Insert( "help", [this](std::ostream&){ Help(); }, From 05e0ed84ee71ea61b3698d2984048e46e9398509 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 18 Aug 2022 12:50:45 +0200 Subject: [PATCH 022/223] Bump version --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6afcb0d..99ef916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [2.0.1] - 2022-04-19 - Specify signed for char parameters (issue [#149](https://github.com/daniele77/cli/issues/149)) - CliSession can call OutStream::UnRegister() when it's already destroyed (issue [#153](https://github.com/daniele77/cli/issues/153)) diff --git a/CMakeLists.txt b/CMakeLists.txt index 284a68a..6d8a19a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ cmake_minimum_required(VERSION 3.8) -project(cli VERSION 2.0.1 +project(cli VERSION 2.0.2 # DESCRIPTION "A library for interactive command line interfaces in modern C++" LANGUAGES CXX) From 9e86142d8f4b5408296eb28411dfcf2abb21eace Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:24:11 +0200 Subject: [PATCH 023/223] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99ef916..2ecdc7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.0.1] - 2022-04-19 +## [2.0.2] - 2022-08-18 - Specify signed for char parameters (issue [#149](https://github.com/daniele77/cli/issues/149)) - CliSession can call OutStream::UnRegister() when it's already destroyed (issue [#153](https://github.com/daniele77/cli/issues/153)) From b2e4f3e7a3602d25367b56d00fecb02b46782e7d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 7 Sep 2022 13:06:02 +0200 Subject: [PATCH 024/223] Examples of user-defined parameter type --- README.md | 36 ++++++++++++++++-- examples/asyncsession.cpp | 4 +- examples/boostasio_nonowner_iocontext.cpp | 4 +- examples/complete.cpp | 37 ++++++++++++++++++- examples/pluginmanager.cpp | 4 +- .../standaloneasio_nonowner_iocontext.cpp | 4 +- include/cli/detail/genericasioremotecli.h | 2 +- 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 116156a..b23be59 100644 --- a/README.md +++ b/README.md @@ -369,8 +369,8 @@ myMenu->Insert("lambda", [](std::ostream& out, int x){ out << x << std::endl; } ``` -There is no limit to the number of parameters that a command handler can take -(however, they can only be basic types or `std::string`s): +There is no limit to the number of parameters that a command handler can take. +They can be basic types and `std::string`s ``` myMenu->Insert( @@ -380,10 +380,40 @@ myMenu->Insert( ... } ); +myMenu->Insert( + "complex", + [](std::ostream& out, std::complex c) + { + ... + } ); +``` + +or they can be custom types overloading the `std::istream << operator`: + +``` +struct Foo +{ + friend istream & operator >> (istream &in, Foo& p); + int value; +}; + +istream & operator >> (istream& in, Foo& p) +{ + in >> p.value; + return in; +} + +myMenu->Insert( + "foo", + [](std::ostream& out, Foo f) + { + ... + } ); + ``` If you need it, you can have a command handlers taking an arbitrary -number of string parameters: +number of `std::string` parameters: ``` myMenu->Insert( diff --git a/examples/asyncsession.cpp b/examples/asyncsession.cpp index f082c49..6b0a4aa 100644 --- a/examples/asyncsession.cpp +++ b/examples/asyncsession.cpp @@ -125,11 +125,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << endl; + cerr << "Exception caugth in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main." << endl; + cerr << "Unknown exception caugth in main.\n"; } return -1; } diff --git a/examples/boostasio_nonowner_iocontext.cpp b/examples/boostasio_nonowner_iocontext.cpp index 0d57466..f0bfead 100644 --- a/examples/boostasio_nonowner_iocontext.cpp +++ b/examples/boostasio_nonowner_iocontext.cpp @@ -135,11 +135,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << endl; + cerr << "Exception caugth in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main." << endl; + cerr << "Unknown exception caugth in main.\n"; } return -1; } diff --git a/examples/complete.cpp b/examples/complete.cpp index 9d1c3d4..1cb650e 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -58,11 +58,35 @@ #include #include // std::copy +#include + using namespace cli; using namespace std; +// a free function to be used as handler static void foo(std::ostream& out, int x) { out << x << std::endl; } +// a custom struct to be used as a user-defined parameter type +struct Bar +{ + string to_string() const { return std::to_string(value); } + friend istream & operator >> (istream &in, Bar& p); + int value; +}; + +istream & operator >> (istream& in, Bar& p) +{ + in >> p.value; + return in; +} + +// needed only for generic help, you can omit this +namespace cli { template <> struct TypeDesc { static const char* Name() { return ""; } }; } + +// needed only for generic help, you can omit this +namespace cli { template <> struct TypeDesc> { static const char* Name() { return ""; } }; } + + int main() { try @@ -73,6 +97,7 @@ int main() // setup cli auto rootMenu = make_unique("cli"); + rootMenu->Insert( "free_function", foo, @@ -151,6 +176,14 @@ int main() out << "\n"; }, "Alphabetically sort a list of words" ); + rootMenu->Insert( + "bar", + [](std::ostream& out, Bar x){ out << "You entered bar: " << x.to_string() << "\n"; }, + "Custom type" ); + rootMenu->Insert( + "complex", + [](std::ostream& out, std::complex x){ out << "You entered complex : " << x << "\n"; }, + "Print a complex number" ); colorCmd = rootMenu->Insert( "color", [&](std::ostream& out) @@ -242,11 +275,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << endl; + cerr << "Exception caugth in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main." << endl; + cerr << "Unknown exception caugth in main.\n"; } return -1; } diff --git a/examples/pluginmanager.cpp b/examples/pluginmanager.cpp index 7e5ff31..3dc37e3 100644 --- a/examples/pluginmanager.cpp +++ b/examples/pluginmanager.cpp @@ -334,11 +334,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << endl; + cerr << "Exception caugth in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main." << endl; + cerr << "Unknown exception caugth in main.\n"; } return -1; } diff --git a/examples/standaloneasio_nonowner_iocontext.cpp b/examples/standaloneasio_nonowner_iocontext.cpp index 5a51fb6..88ce0ef 100644 --- a/examples/standaloneasio_nonowner_iocontext.cpp +++ b/examples/standaloneasio_nonowner_iocontext.cpp @@ -127,11 +127,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << endl; + cerr << "Exception caugth in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main." << endl; + cerr << "Unknown exception caugth in main.\n"; } return -1; } diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 6c5d07c..b66f23c 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -303,7 +303,7 @@ class TelnetSession : public Session if (state == State::sub) state = State::data; else - std::cout << "ERROR: received SE when not in sub state" << std::endl; + std::cerr << "ERROR: received SE when not in sub state\n"; break; case DataMark: // ? case Break: // ? From 10c570db45d2209e5c6801a6a1eb8ac6cc941f7a Mon Sep 17 00:00:00 2001 From: Evan McBroom <15305789+EvanMcBroom@users.noreply.github.com> Date: Tue, 20 Sep 2022 12:13:43 -0400 Subject: [PATCH 025/223] Added check for CMAKE_SKIP_INSTALL_RULES (#160) --- CMakeLists.txt | 64 ++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d8a19a..6477670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,34 +116,36 @@ if (CLI_BuildTests) endif() # Install -install(DIRECTORY include/cli DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - -include(CMakePackageConfigHelpers) -configure_package_config_file( - "cliConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli" -) - -# Generate pkg-config .pc file -set(PKGCONFIG_INSTALL_DIR - ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig - CACHE PATH "Installation directory for pkg-config (cli.pc) file" -) -configure_file( - "cli.pc.in" - "cli.pc" - @ONLY -) - -install(TARGETS cli EXPORT cliTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) -install(EXPORT cliTargets FILE cliTargets.cmake NAMESPACE cli:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cli) - -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli" -) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cli.pc" - DESTINATION ${PKGCONFIG_INSTALL_DIR} -) +if(NOT CMAKE_SKIP_INSTALL_RULES) + install(DIRECTORY include/cli DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + include(CMakePackageConfigHelpers) + configure_package_config_file( + "cliConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli" + ) + + # Generate pkg-config .pc file + set(PKGCONFIG_INSTALL_DIR + ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig + CACHE PATH "Installation directory for pkg-config (cli.pc) file" + ) + configure_file( + "cli.pc.in" + "cli.pc" + @ONLY + ) + + install(TARGETS cli EXPORT cliTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(EXPORT cliTargets FILE cliTargets.cmake NAMESPACE cli:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cli) + + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli" + ) + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/cli.pc" + DESTINATION ${PKGCONFIG_INSTALL_DIR} + ) +endif() \ No newline at end of file From e8739a7906cd68d25e876afe066b507c8c147b5a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 20 Sep 2022 18:45:38 +0200 Subject: [PATCH 026/223] Update README.md --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index b23be59..1816766 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,21 @@ or, if you want to specify the installation path: mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX:PATH= make install + +Alternatively, you can use CMake's `FetchContent` module to include CLI library in your project directly. +Add something like this in your `CMakeLists.txt` file: + + include(FetchContent) + FetchContent_Declare( + cli + GIT_REPOSITORY https://github.com/daniele77/cli.git + GIT_TAG v2.0.2 + ) + FetchContent_MakeAvailable(cli) + + add_executable(main-project) + target_link_libraries(main-project PRIVATE cli::cli) + ## Compilation of the examples From 7270d6e2e0d03d56d9a6fe9c0cf1ff489a1a8166 Mon Sep 17 00:00:00 2001 From: Subrata Paul <36674883+paulsubrata55@users.noreply.github.com> Date: Thu, 22 Sep 2022 19:56:16 +0530 Subject: [PATCH 027/223] Added ascii value 8 for backspace (#124) Co-authored-by: Subrata Paul Close #122 --- include/cli/detail/linuxkeyboard.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index d92e176..2878ac6 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -146,7 +146,9 @@ class LinuxKeyboard : public InputDevice case 4: // EOT return std::make_pair(KeyType::eof,' '); break; - case 127: return std::make_pair(KeyType::backspace,' '); break; + case 127: + case 8: + return std::make_pair(KeyType::backspace,' '); break; case 10: return std::make_pair(KeyType::ret,' '); break; case 27: // symbol ch = std::getchar(); From c659fd327f02f097474d4304cbd458dc318fb4e9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 2 Nov 2022 09:44:32 +0100 Subject: [PATCH 028/223] Nest namespace rang (Close #167) --- CHANGELOG.md | 4 ++++ README.md | 2 +- include/cli/colorprofile.h | 8 ++++---- include/cli/detail/rang.h | 5 +++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ecdc7e..b2cb143 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + + - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) + ## [2.0.2] - 2022-08-18 - Specify signed for char parameters (issue [#149](https://github.com/daniele77/cli/issues/149)) diff --git a/README.md b/README.md index b23be59..62f574c 100644 --- a/README.md +++ b/README.md @@ -239,7 +239,7 @@ LoopScheduler scheduler; CliLocalTerminalSession localSession(cli, scheduler); ... // in another thread you can do: -scheduler.Post([](){ cout << "This will be executed in the scheduler thread" << endl; }); +scheduler.Post([](){ cout << "This will be executed in the scheduler thread\n"; }); ... // start the scheduler main loop // it will exit from this method only when scheduler.Stop() is called diff --git a/include/cli/colorprofile.h b/include/cli/colorprofile.h index 0d9714b..518ce57 100644 --- a/include/cli/colorprofile.h +++ b/include/cli/colorprofile.h @@ -47,25 +47,25 @@ enum AfterInput { afterInput }; inline std::ostream& operator<<(std::ostream& os, BeforePrompt) { - if ( Color() ) { os << rang::control::forceColor << rang::fg::green << rang::style::bold; } + if ( Color() ) { os << detail::rang::control::forceColor << detail::rang::fg::green << detail::rang::style::bold; } return os; } inline std::ostream& operator<<(std::ostream& os, AfterPrompt) { - os << rang::style::reset; + os << detail::rang::style::reset; return os; } inline std::ostream& operator<<(std::ostream& os, BeforeInput) { - if ( Color() ) { os << rang::control::forceColor << rang::fgB::gray; } + if ( Color() ) { os << detail::rang::control::forceColor << detail::rang::fgB::gray; } return os; } inline std::ostream& operator<<(std::ostream& os, AfterInput) { - os << rang::style::reset; + os << detail::rang::style::reset; return os; } diff --git a/include/cli/detail/rang.h b/include/cli/detail/rang.h index 708f443..79b5ae6 100644 --- a/include/cli/detail/rang.h +++ b/include/cli/detail/rang.h @@ -30,6 +30,8 @@ #include #include +namespace cli { +namespace detail { namespace rang { enum class style { @@ -289,7 +291,10 @@ inline rang_implementation::enableControl operator<<( } return os; } + } // namespace rang +} // namespace detail +} // namespace cli #undef OS_LINUX #undef OS_WIN From 63b33e7ce65bfbfc42f590cbb4a8aec8c9aed997 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 2 Nov 2022 09:54:38 +0100 Subject: [PATCH 029/223] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2cb143..d41b251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) + - Add ascii value 8 for backspace [#124](https://github.com/daniele77/cli/issues/124)) + - Add check for CMAKE_SKIP_INSTALL_RULES [#160](https://github.com/daniele77/cli/issues/160)) ## [2.0.2] - 2022-08-18 From 8ccd7bdcbd7824d56830e2bbbdb9636647dc0632 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 2 Nov 2022 09:56:20 +0100 Subject: [PATCH 030/223] Update CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d41b251..50cb451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) - - Add ascii value 8 for backspace [#124](https://github.com/daniele77/cli/issues/124)) - - Add check for CMAKE_SKIP_INSTALL_RULES [#160](https://github.com/daniele77/cli/issues/160)) + - Add ascii value 8 for backspace (issue [#124](https://github.com/daniele77/cli/issues/124)) + - Add check for CMAKE_SKIP_INSTALL_RULES (issue [#160](https://github.com/daniele77/cli/issues/160)) ## [2.0.2] - 2022-08-18 From b9e47f755298aa770372b29a75197d0fe0513e47 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:37:41 +0100 Subject: [PATCH 031/223] Create codeql.yml --- .github/workflows/codeql.yml | 76 ++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..e5ac9f9 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,76 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '20 0 * * 6' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'cpp' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" From 401d0b1cab04b1c1ff73225f724651f3796ffb22 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:51:04 +0100 Subject: [PATCH 032/223] Update codeql.yml --- .github/workflows/codeql.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e5ac9f9..e648e5c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -57,8 +57,8 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + #- name: Autobuild + # uses: github/codeql-action/autobuild@v2 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -66,9 +66,12 @@ jobs: # If the Autobuild fails above, remove it and uncomment the following three lines. # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + - run: | + echo "Run, Build Application using script" + mkdir build + cd build + cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON + make all - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 From f722c78322213a071a346a9f668f758d2e34f848 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 13 Jan 2023 11:14:32 +0100 Subject: [PATCH 033/223] Update codeql.yml --- .github/workflows/codeql.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e648e5c..850082d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -67,7 +67,6 @@ jobs: # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - run: | - echo "Run, Build Application using script" mkdir build cd build cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON From 0e5845ff917277f60690a9a2e808e5c0303e2258 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 13 Jan 2023 11:37:30 +0100 Subject: [PATCH 034/223] Update codeql.yml --- .github/workflows/codeql.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 850082d..9d3fdea 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -66,11 +66,12 @@ jobs: # If the Autobuild fails above, remove it and uncomment the following three lines. # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - run: | - mkdir build - cd build - cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON - make all + - name: Build + run: | + mkdir build + cd build + cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON + make all - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 From 3e6fecf4e5df9000a6bc720c2a0a536fc323d8e0 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 13 Jan 2023 11:42:29 +0100 Subject: [PATCH 035/223] Update codeql.yml --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9d3fdea..f44004b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -70,7 +70,7 @@ jobs: run: | mkdir build cd build - cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON + cmake .. -DCLI_BuildTests=OFF -DCLI_BuildExamples=ON make all - name: Perform CodeQL Analysis From e508a701650005015208790ec208b55931153de2 Mon Sep 17 00:00:00 2001 From: Dup4 Date: Wed, 18 Jan 2023 00:53:42 +0800 Subject: [PATCH 036/223] feat: support EnterAction (#180) --- include/cli/cli.h | 31 +++++++++++++++++++++++ include/cli/clifilesession.h | 2 ++ include/cli/clilocalsession.h | 1 + include/cli/detail/genericasioremotecli.h | 8 ++++++ test/test_cli.cpp | 23 +++++++++++++++++ 5 files changed, 65 insertions(+) diff --git a/include/cli/cli.h b/include/cli/cli.h index 0a6361f..0788139 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -140,10 +140,18 @@ namespace cli Cli(std::unique_ptr _rootMenu, std::unique_ptr historyStorage = std::make_unique()) : globalHistoryStorage(std::move(historyStorage)), rootMenu(std::move(_rootMenu)), + enterAction{}, exitAction{} { } + /** + * @brief Add a global enter action that is called every time a session (local or remote) is established. + * + * @param action the function to be called when a session exits, taking a @c std::ostream& parameter to write on that session console. + */ + void EnterAction(const std::function< void(std::ostream&)>& action) { enterAction = action; } + /** * @brief Add a global exit action that is called every time a session (local or remote) gets the "exit" command. * @@ -184,6 +192,13 @@ namespace cli Menu* RootMenu() { return rootMenu.get(); } + void EnterAction(std::ostream& out) + { + if (enterAction) { + enterAction(out); + } + } + void ExitAction( std::ostream& out ) { if ( exitAction ) @@ -211,6 +226,7 @@ namespace cli private: std::unique_ptr globalHistoryStorage; std::unique_ptr rootMenu; // just to keep it alive + std::function enterAction; std::function exitAction; std::function exceptionHandler; }; @@ -298,6 +314,15 @@ namespace cli void Help() const; + void Enter() + { + cli.EnterAction(out); + + if (enterAction) { + enterAction(out); + } + } + void Exit() { exitAction(out); @@ -309,6 +334,11 @@ namespace cli exit = true; // prevent the prompt to be shown } + void EnterAction(const std::function& action) + { + enterAction = action; + } + void ExitAction(const std::function& action) { exitAction = action; @@ -335,6 +365,7 @@ namespace cli Menu* current; std::unique_ptr globalScopeMenu; std::ostream& out; + std::function< void(std::ostream&)> enterAction = []( std::ostream& ){}; std::function< void(std::ostream&)> exitAction = []( std::ostream& ){}; detail::History history; bool exit{ false }; // to prevent the prompt after exit command diff --git a/include/cli/clifilesession.h b/include/cli/clifilesession.h index 2416487..f0f08c5 100644 --- a/include/cli/clifilesession.h +++ b/include/cli/clifilesession.h @@ -58,6 +58,8 @@ class CliFileSession : public CliSession } void Start() { + Enter(); + while(!exit) { Prompt(); diff --git a/include/cli/clilocalsession.h b/include/cli/clilocalsession.h index b9dc82e..5528350 100644 --- a/include/cli/clilocalsession.h +++ b/include/cli/clilocalsession.h @@ -64,6 +64,7 @@ class CliLocalTerminalSession : public CliSession kb(scheduler), ih(*this, kb) { + Enter(); Prompt(); } diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index b66f23c..576520a 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -463,6 +463,7 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes void OnConnect() override { TelnetSession::OnConnect(); + Enter(); Prompt(); } @@ -559,6 +560,12 @@ class CliGenericTelnetServer : public Server cli(_cli), historySize(_historySize) {} + + void EnterAction(std::function< void(std::ostream&)> action) + { + enterAction = action; + } + void ExitAction( std::function< void(std::ostream&)> action ) { exitAction = action; @@ -570,6 +577,7 @@ class CliGenericTelnetServer : public Server private: Scheduler& scheduler; Cli& cli; + std::function< void(std::ostream&)> enterAction; std::function< void(std::ostream&)> exitAction; std::size_t historySize; }; diff --git a/test/test_cli.cpp b/test/test_cli.cpp index ae395a6..b622a38 100644 --- a/test/test_cli.cpp +++ b/test/test_cli.cpp @@ -370,6 +370,29 @@ BOOST_AUTO_TEST_CASE(Submenus) BOOST_CHECK_EQUAL(ExtractContent(oss), "foo"); } +BOOST_AUTO_TEST_CASE(EnterActions) +{ + auto rootMenu = make_unique("cli"); + rootMenu->Insert("int_cmd", + [](ostream &out, int par) { out << par << "\n"; }, + "int_cmd help", {"int_par"}); + rootMenu->Insert( + "string_cmd", + [](ostream &out, const string &par) { out << par << "\n"; }, + "string_cmd help", {"string_par"}); + + Cli cli(std::move(rootMenu)); + bool enterActionDone = false; + + cli.EnterAction( + [&enterActionDone](std::ostream &) { enterActionDone = true; }); + + stringstream oss; + + UserInput(cli, oss, "exit"); + BOOST_CHECK(enterActionDone); +} + BOOST_AUTO_TEST_CASE(ExitActions) { auto rootMenu = make_unique("cli"); From 31ff1b91094743457ca47fe1256441acf735b169 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 17 Jan 2023 18:14:55 +0100 Subject: [PATCH 037/223] Update README and CHANGELOG --- CHANGELOG.md | 1 + README.md | 26 ++++++++++++++++++++------ include/cli/cli.h | 12 +++++------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50cb451..f354c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) - Add ascii value 8 for backspace (issue [#124](https://github.com/daniele77/cli/issues/124)) - Add check for CMAKE_SKIP_INSTALL_RULES (issue [#160](https://github.com/daniele77/cli/issues/160)) + - Add enter action (issue [#177](https://github.com/daniele77/cli/issues/177) - PR [#180](https://github.com/daniele77/cli/pull/177)) ## [2.0.2] - 2022-08-18 diff --git a/README.md b/README.md index 3185a2d..a6a4fbe 100644 --- a/README.md +++ b/README.md @@ -298,7 +298,7 @@ ioc.run(); You must provide at least a root menu for your cli: -``` +```C++ // create a menu (this is the root menu of our cli) auto rootMenu = make_unique("myprompt"); @@ -311,7 +311,7 @@ Cli cli(std::move(rootMenu)); You can add menus to existing menus, to get a hierarchy: -``` +```C++ auto rootMenu = make_unique("myprompt"); auto menuA = make_unique("a_prompt"); @@ -368,7 +368,7 @@ The library supports adding commands handler via: - `std::function` - lambdas -``` +```C++ static void foo(std::ostream& out, int x) { out << x << std::endl; } @@ -387,7 +387,7 @@ myMenu->Insert("lambda", [](std::ostream& out, int x){ out << x << std::endl; } There is no limit to the number of parameters that a command handler can take. They can be basic types and `std::string`s -``` +```C++ myMenu->Insert( "mycmd", [](std::ostream& out, int a, double b, const std::string& c, bool d, long e) @@ -405,7 +405,7 @@ myMenu->Insert( or they can be custom types overloading the `std::istream << operator`: -``` +```C++ struct Foo { friend istream & operator >> (istream &in, Foo& p); @@ -430,7 +430,7 @@ myMenu->Insert( If you need it, you can have a command handlers taking an arbitrary number of `std::string` parameters: -``` +```C++ myMenu->Insert( "mycmd", [](std::ostream& out, const std::vector& pars) @@ -443,6 +443,20 @@ myMenu->Insert( Please note that in this case your command handler must take *only one* parameter of type `std::vector`. +## Enter and exit actions + +You can add an enter action and/or an exit action (for example to print a welcome/goodbye message +every time a user opens/closes a session, even a remote one): + +```C++ +Cli cli(std::move(rootMenu)); +cli.EnterAction( + [&enterActionDone](std::ostream& out) { out << "Welcome\n"; }); +cli.ExitAction( + [&enterActionDone](std::ostream& out) { out << "Goodbye\n"; }); +``` + + ## License Distributed under the Boost Software License, Version 1.0. diff --git a/include/cli/cli.h b/include/cli/cli.h index 0788139..0b56fb0 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -194,15 +194,14 @@ namespace cli void EnterAction(std::ostream& out) { - if (enterAction) { + if (enterAction) enterAction(out); - } } - void ExitAction( std::ostream& out ) + void ExitAction(std::ostream& out) { - if ( exitAction ) - exitAction( out ); + if (exitAction) + exitAction(out); } void StdExceptionHandler(std::ostream& out, const std::string& cmd, const std::exception& e) @@ -318,9 +317,8 @@ namespace cli { cli.EnterAction(out); - if (enterAction) { + if (enterAction) enterAction(out); - } } void Exit() From 484bd3b65dbffbebb5862b031731d809f7193e9d Mon Sep 17 00:00:00 2001 From: Ilya Lukin <62634576+illukin@users.noreply.github.com> Date: Wed, 8 Feb 2023 18:18:50 +0700 Subject: [PATCH 038/223] Fixed some typos (#184) --- CHANGELOG.md | 2 +- README.md | 4 ++-- examples/asyncsession.cpp | 4 ++-- include/cli/cli.h | 2 +- include/cli/detail/terminal.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f354c69..225133b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [1.2.1] - 2020-08-27 - - With Boost >= 1.74 use TS exectuor by default (issue [#79](https://github.com/daniele77/cli/issues/79)) + - With Boost >= 1.74 use TS executor by default (issue [#79](https://github.com/daniele77/cli/issues/79)) - Standard and custom exception handler for cli commands (issue [#74](https://github.com/daniele77/cli/issues/74)) ## [1.2.0] - 2020-06-27 diff --git a/README.md b/README.md index a6a4fbe..b7f6c36 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ In any menu, you can enter: - `exit`: to exit the cli - `help`: to print the list of the commands available with a description - a submenu name: to enter the submenu -- the parent menu name: to return to the the parent menu +- the parent menu name: to return to the parent menu - a command in the current menu: to exec the command - a command in a submenu (using the full path): to exec the command @@ -235,7 +235,7 @@ because they internally use `boost::asio` and `asio`. You should use one of them also if your application uses `asio` in some way. After setting up your application, you must call `Scheduler::Run()` -to enter the scheduler loop. Each comamnd handler of the library +to enter the scheduler loop. Each command handler of the library will execute in the thread that called `Scheduler::Run()`. You can exit the scheduler loop by calling `Scheduler::Stop()` diff --git a/examples/asyncsession.cpp b/examples/asyncsession.cpp index 6b0a4aa..181065f 100644 --- a/examples/asyncsession.cpp +++ b/examples/asyncsession.cpp @@ -125,11 +125,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << '\n'; + cerr << "Exception caught in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main.\n"; + cerr << "Unknown exception caught in main.\n"; } return -1; } diff --git a/include/cli/cli.h b/include/cli/cli.h index 0b56fb0..5d4fd2d 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -129,7 +129,7 @@ namespace cli * @brief Construct a new Cli object having a given root menu that contains the first level commands available. * * @param _rootMenu is the @c Menu containing the first level commands available to the user. - * @param historyStorage is the policy for the storage of the cli commands history. You must pass an istance of + * @param historyStorage is the policy for the storage of the cli commands history. You must pass an instance of * a class derived from @c HistoryStorage. The library provides these policies: * - @c VolatileHistoryStorage * - @c FileHistoryStorage it's a persistent history. I.e., the command history is preserved after your application diff --git a/include/cli/detail/terminal.h b/include/cli/detail/terminal.h index 6db62f5..e9a4f6d 100644 --- a/include/cli/detail/terminal.h +++ b/include/cli/detail/terminal.h @@ -62,7 +62,7 @@ class Terminal << std::string(position, '\b') << newLine << afterInput << std::flush; - // if newLine is shorter then currentLine, we have + // if newLine is shorter than currentLine, we have // to clear the rest of the string if (newLine.size() < currentLine.size()) { From 59b51121e10245587e90a7858e2ad8b29c8c929b Mon Sep 17 00:00:00 2001 From: YunchengLiu <40971483+YunchengLiu@users.noreply.github.com> Date: Wed, 15 Feb 2023 00:30:23 +0800 Subject: [PATCH 039/223] add docs on handling Unicode input and output (#187) --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index b7f6c36..9e2e306 100644 --- a/README.md +++ b/README.md @@ -455,7 +455,38 @@ cli.EnterAction( cli.ExitAction( [&enterActionDone](std::ostream& out) { out << "Goodbye\n"; }); ``` +## Unicode +`cli` uses the input and output stream objects provided by the standard library (such as `std::cin` and `std::cout`) by default, so currently `cli` does not have effective support for unicode input and output. + +If you want to handle unicode input and output, you need to provide custom i/o unicode aware stream objects derived from `std::istream` or `std::ostream`. + +For example, you can use [boost::nowide](https://github.com/boostorg/nowide) as an alternative to implement UTF-8 aware programming in a out-of-box and cross-platform way: + +```c++ +#include // for boost::nowide::cin and boost::nowide::cout +// other headers... + +cli::Cli app{/*init code*/}; + +// FileSession session{app}; // default + +// now, all parameters is in a UTF-8 encoded std::string +// pass boost::nowide::cin and boost::nowide::cout as parameters(FileSession requires std::istream and std::ostream) +FileSession session{app, boost::nowide::cin, boost::nowide::cout}; + +/*....*/ + +// you can call this command funtion and get UTF-8 encoded input data (p), just use it. +// boost::noide helps us avoid the trouble +// caused by inconsistent default code page and encoding of the console under different platforms. +void a_command_function(std::ostream& os, std::string const& p) { + /* implements */ +} + +``` + +Of course, you can also pass stream objects with other capabilities to achieve more customized input and output functions. ## License From 94cc7b08f2b8211f9b7e9bb8245aa3ce2e1f9764 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 15 Feb 2023 10:49:27 +0100 Subject: [PATCH 040/223] Fix missing echo after paste with linux (close issue #185) --- CHANGELOG.md | 1 + include/cli/detail/linuxkeyboard.h | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f354c69..d7b1608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add ascii value 8 for backspace (issue [#124](https://github.com/daniele77/cli/issues/124)) - Add check for CMAKE_SKIP_INSTALL_RULES (issue [#160](https://github.com/daniele77/cli/issues/160)) - Add enter action (issue [#177](https://github.com/daniele77/cli/issues/177) - PR [#180](https://github.com/daniele77/cli/pull/177)) + - Fix missing echo after paste of command (issue [#185](https://github.com/daniele77/cli/issues/185) ## [2.0.2] - 2022-08-18 diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 2878ac6..72ec901 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -88,9 +88,9 @@ class InputSource void Stop() { auto unused = write(shutdownPipe, " ", 1); - unused = close(shutdownPipe); + unused = close(shutdownPipe); static_cast(unused); // silence unused warn - shutdownPipe = -1; + shutdownPipe = -1; } private: @@ -132,14 +132,22 @@ class LinuxKeyboard : public InputDevice catch(const std::exception&) { // nothing to do: just exit - } + } + } + + char GetChar() + { + char buffer = 0; + auto unused = read(0, &buffer, 1); + static_cast(unused); // silence unused warn + return buffer; } std::pair Get() { is.WaitKbHit(); - int ch = std::getchar(); + auto ch = GetChar(); switch(ch) { case EOF: @@ -151,14 +159,14 @@ class LinuxKeyboard : public InputDevice return std::make_pair(KeyType::backspace,' '); break; case 10: return std::make_pair(KeyType::ret,' '); break; case 27: // symbol - ch = std::getchar(); + ch = GetChar(); if ( ch == 91 ) // arrow keys { - ch = std::getchar(); + ch = GetChar(); switch( ch ) { case 51: - ch = std::getchar(); + ch = GetChar(); if ( ch == 126 ) return std::make_pair(KeyType::canc,' '); else return std::make_pair(KeyType::ignored,' '); break; From cd9caa5192873d3d8a7e3832f92ed4f497233805 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 20 Feb 2023 11:43:27 +0100 Subject: [PATCH 041/223] Fix asio::io_context::work has no member named reset in old asio lib (Close #188) --- CHANGELOG.md | 1 + include/cli/detail/genericasioscheduler.h | 2 +- include/cli/detail/newboostasiolib.h | 5 +++++ include/cli/detail/newstandaloneasiolib.h | 6 ++++++ include/cli/detail/oldboostasiolib.h | 4 ++++ include/cli/detail/oldstandaloneasiolib.h | 4 ++++ 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 260a260..de8b91b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add check for CMAKE_SKIP_INSTALL_RULES (issue [#160](https://github.com/daniele77/cli/issues/160)) - Add enter action (issue [#177](https://github.com/daniele77/cli/issues/177) - PR [#180](https://github.com/daniele77/cli/pull/177)) - Fix missing echo after paste of command (issue [#185](https://github.com/daniele77/cli/issues/185) + - Fix asio::io_context::work has no member named reset in old asio lib (issue [#188](https://github.com/daniele77/cli/issues/188) ## [2.0.2] - 2022-08-18 diff --git a/include/cli/detail/genericasioscheduler.h b/include/cli/detail/genericasioscheduler.h index 6252fbf..7fb2979 100644 --- a/include/cli/detail/genericasioscheduler.h +++ b/include/cli/detail/genericasioscheduler.h @@ -71,7 +71,7 @@ class GenericAsioScheduler : public Scheduler void Stop() { if (work) - work->reset(); + ASIOLIB::Reset(*work); context->stop(); } diff --git a/include/cli/detail/newboostasiolib.h b/include/cli/detail/newboostasiolib.h index 1d1f3ee..2d7b4e6 100644 --- a/include/cli/detail/newboostasiolib.h +++ b/include/cli/detail/newboostasiolib.h @@ -75,6 +75,11 @@ class NewBoostAsioLib return boost::asio::make_work_guard(context); } + static void Reset(WorkGuard& wg) + { + wg.reset(); + } + }; } // namespace detail diff --git a/include/cli/detail/newstandaloneasiolib.h b/include/cli/detail/newstandaloneasiolib.h index 92f3d23..54d5aa7 100644 --- a/include/cli/detail/newstandaloneasiolib.h +++ b/include/cli/detail/newstandaloneasiolib.h @@ -74,6 +74,12 @@ class NewStandaloneAsioLib { return asio::make_work_guard(context); } + + static void Reset(WorkGuard& wg) + { + wg.reset(); + } + }; } // namespace detail diff --git a/include/cli/detail/oldboostasiolib.h b/include/cli/detail/oldboostasiolib.h index af5c704..a24173d 100644 --- a/include/cli/detail/oldboostasiolib.h +++ b/include/cli/detail/oldboostasiolib.h @@ -69,6 +69,10 @@ class OldBoostAsioLib return work; } + static void Reset(WorkGuard& /*wg*/) + { + } + }; } // namespace detail diff --git a/include/cli/detail/oldstandaloneasiolib.h b/include/cli/detail/oldstandaloneasiolib.h index a764fb3..6c582e6 100644 --- a/include/cli/detail/oldstandaloneasiolib.h +++ b/include/cli/detail/oldstandaloneasiolib.h @@ -72,6 +72,10 @@ class OldStandaloneAsioLib return work; } + static void Reset(WorkGuard& /*wg*/) + { + } + }; } // namespace detail From c771805fe040c963c9fbf500fbf49118600a8266 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 7 Apr 2023 13:24:29 +0200 Subject: [PATCH 042/223] Add in examples that menus do have description in help (#96) --- CHANGELOG.md | 5 +++-- examples/complete.cpp | 4 ++-- examples/pluginmanager.cpp | 4 ++-- include/cli/cli.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index de8b91b..1584b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add ascii value 8 for backspace (issue [#124](https://github.com/daniele77/cli/issues/124)) - Add check for CMAKE_SKIP_INSTALL_RULES (issue [#160](https://github.com/daniele77/cli/issues/160)) - Add enter action (issue [#177](https://github.com/daniele77/cli/issues/177) - PR [#180](https://github.com/daniele77/cli/pull/177)) - - Fix missing echo after paste of command (issue [#185](https://github.com/daniele77/cli/issues/185) - - Fix asio::io_context::work has no member named reset in old asio lib (issue [#188](https://github.com/daniele77/cli/issues/188) + - Fix missing echo after paste of command (issue [#185](https://github.com/daniele77/cli/issues/185)) + - Fix asio::io_context::work has no member named reset in old asio lib (issue [#188](https://github.com/daniele77/cli/issues/188)) + - Shown in the `complete` and `pluginmanager` examples that the issue #96 was already fixed (issue [#96](https://github.com/daniele77/cli/issues/96)) ## [2.0.2] - 2022-08-18 diff --git a/examples/complete.cpp b/examples/complete.cpp index 1cb650e..d7cd0bd 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -214,7 +214,7 @@ int main() } ); - auto subMenu = make_unique("sub"); + auto subMenu = make_unique("sub", "Enter a submenu"); subMenu->Insert( "hello", [](std::ostream& out){ out << "Hello, submenu world\n"; }, @@ -224,7 +224,7 @@ int main() [](std::ostream& out){ out << "This is a sample!\n"; }, "Print a demo string" ); - auto subSubMenu = make_unique("subsub"); + auto subSubMenu = make_unique("subsub", "Enter a submenu of second level"); subSubMenu->Insert( "hello", [](std::ostream& out){ out << "Hello, subsubmenu world\n"; }, diff --git a/examples/pluginmanager.cpp b/examples/pluginmanager.cpp index 3dc37e3..8336d7d 100644 --- a/examples/pluginmanager.cpp +++ b/examples/pluginmanager.cpp @@ -164,7 +164,7 @@ class Arithmetic : public RegisteredPlugin public: explicit Arithmetic(Menu* menu) { - auto subMenu = make_unique(Name()); + auto subMenu = make_unique(Name(), "Enter the " + Name() + " plugin menu"); subMenu->Insert( "add", {"first_term", "second_term"}, [](std::ostream& out, int x, int y) @@ -208,7 +208,7 @@ class Strings : public RegisteredPlugin public: explicit Strings(Menu* menu) { - auto subMenu = make_unique(Name()); + auto subMenu = make_unique(Name(), "Enter the " + Name() + " plugin menu"); subMenu->Insert( "reverse", {"string_to_revert"}, [](std::ostream& out, const string& arg) diff --git a/include/cli/cli.h b/include/cli/cli.h index 5d4fd2d..c835b33 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -433,7 +433,7 @@ namespace cli Menu() : Command({}), parent(nullptr), description(), cmds(std::make_shared()) {} - explicit Menu(const std::string& _name, std::string desc = "(menu)") : + explicit Menu(const std::string& _name, std::string desc = "(menu)") : Command(_name), parent(nullptr), description(std::move(desc)), cmds(std::make_shared()) {} From 900c74eca6c750bf514755c23814c0f5d42a5a4b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:02:13 +0200 Subject: [PATCH 043/223] Allow custom prompt for menu (close #101) --- CHANGELOG.md | 1 + examples/complete.cpp | 6 +++++- include/cli/cli.h | 11 ++++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1584b10..8809ced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix missing echo after paste of command (issue [#185](https://github.com/daniele77/cli/issues/185)) - Fix asio::io_context::work has no member named reset in old asio lib (issue [#188](https://github.com/daniele77/cli/issues/188)) - Shown in the `complete` and `pluginmanager` examples that the issue #96 was already fixed (issue [#96](https://github.com/daniele77/cli/issues/96)) + - Allow custom prompt for menu (issue [#101](https://github.com/daniele77/cli/issues/101)) ## [2.0.2] - 2022-08-18 diff --git a/examples/complete.cpp b/examples/complete.cpp index d7cd0bd..7b5e84a 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -214,7 +214,11 @@ int main() } ); - auto subMenu = make_unique("sub", "Enter a submenu"); + // a submenu + // first parameter is the command to enter the submenu + // second parameter (optional) is the description of the menu in the help + // third parameter (optional) is the prompt of the menu (default is the name of the command) + auto subMenu = make_unique("sub", "Enter a submenu", "submenu"); subMenu->Insert( "hello", [](std::ostream& out){ out << "Hello, submenu world\n"; }, diff --git a/include/cli/cli.h b/include/cli/cli.h index c835b33..073aabb 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -433,8 +433,12 @@ namespace cli Menu() : Command({}), parent(nullptr), description(), cmds(std::make_shared()) {} - explicit Menu(const std::string& _name, std::string desc = "(menu)") : - Command(_name), parent(nullptr), description(std::move(desc)), cmds(std::make_shared()) + explicit Menu(const std::string& _name, std::string desc = "(menu)", const std::string& _prompt="") : + Command(_name), + parent(nullptr), + description(std::move(desc)), + prompt(_prompt.empty() ? _name : _prompt), + cmds(std::make_shared()) {} template @@ -505,7 +509,7 @@ namespace cli std::string Prompt() const { - return Name(); + return prompt; } void MainHelp(std::ostream& out) @@ -574,6 +578,7 @@ namespace cli Menu* parent{ nullptr }; const std::string description; + const std::string prompt; // using shared_ptr instead of unique_ptr to get a weak_ptr // for the CmdHandler::Descriptor using Cmds = std::vector>; From a0ed10097e0140c62de2d4dbaffc97f16c4619e6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 7 Apr 2023 16:36:52 +0200 Subject: [PATCH 044/223] Minor layout changes --- examples/complete.cpp | 4 ++-- include/cli/cli.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/complete.cpp b/examples/complete.cpp index 7b5e84a..0472340 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -211,8 +211,8 @@ int main() { colorCmd.Remove(); nocolorCmd.Remove(); - } - ); + }, + "Remove both color and nocolor commands from the menu" ); // a submenu // first parameter is the command to enter the submenu diff --git a/include/cli/cli.h b/include/cli/cli.h index 073aabb..d6f987a 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -115,7 +115,6 @@ namespace cli class Cli { - public: ~Cli() = default; // disable value semantics From be1292d67906edca099b91db321648c165a48331 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 27 Jun 2023 18:18:48 +0200 Subject: [PATCH 045/223] Add noexcept to lambas --- include/cli/cli.h | 4 ++-- include/cli/clifilesession.h | 2 +- test/scheduler_test_templates.h | 4 ++-- test/test_boostasioscheduler.cpp | 2 +- test/test_cli.cpp | 6 +++--- test/test_standaloneasioscheduler.cpp | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 073aabb..d317ff2 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -363,8 +363,8 @@ namespace cli Menu* current; std::unique_ptr globalScopeMenu; std::ostream& out; - std::function< void(std::ostream&)> enterAction = []( std::ostream& ){}; - std::function< void(std::ostream&)> exitAction = []( std::ostream& ){}; + std::function< void(std::ostream&)> enterAction = []( std::ostream& ) noexcept {}; + std::function< void(std::ostream&)> exitAction = []( std::ostream& ) noexcept {}; detail::History history; bool exit{ false }; // to prevent the prompt after exit command }; diff --git a/include/cli/clifilesession.h b/include/cli/clifilesession.h index f0f08c5..68177e5 100644 --- a/include/cli/clifilesession.h +++ b/include/cli/clifilesession.h @@ -50,7 +50,7 @@ class CliFileSession : public CliSession if (!_in.good()) throw std::invalid_argument("istream invalid"); if (!_out.good()) throw std::invalid_argument("ostream invalid"); ExitAction( - [this](std::ostream&) + [this](std::ostream&) noexcept { exit = true; } diff --git a/test/scheduler_test_templates.h b/test/scheduler_test_templates.h index 0c7d4d0..9792f36 100644 --- a/test/scheduler_test_templates.h +++ b/test/scheduler_test_templates.h @@ -38,7 +38,7 @@ void SchedulingTest() { S scheduler; bool done = false; - scheduler.Post( [&done](){ done = true; } ); + scheduler.Post( [&done]() noexcept { done = true; } ); scheduler.ExecOne(); BOOST_CHECK(done); } @@ -56,7 +56,7 @@ void SameThreadTest() { postThreadId = this_thread::get_id(); scheduler.Post( - [&runThreadId]() + [&runThreadId]() noexcept { runThreadId = this_thread::get_id(); } diff --git a/test/test_boostasioscheduler.cpp b/test/test_boostasioscheduler.cpp index dc90491..b3c478b 100644 --- a/test/test_boostasioscheduler.cpp +++ b/test/test_boostasioscheduler.cpp @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(BoostAsioNonOwner) detail::BoostAsioLib::ContextType ioc; BoostAsioScheduler scheduler(ioc); bool done = false; - scheduler.Post( [&done](){ done = true; } ); + scheduler.Post( [&done]() noexcept { done = true; } ); ioc.run_one(); BOOST_CHECK(done); } diff --git a/test/test_cli.cpp b/test/test_cli.cpp index b622a38..7f16829 100644 --- a/test/test_cli.cpp +++ b/test/test_cli.cpp @@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(EnterActions) bool enterActionDone = false; cli.EnterAction( - [&enterActionDone](std::ostream &) { enterActionDone = true; }); + [&enterActionDone](std::ostream &) noexcept { enterActionDone = true; }); stringstream oss; @@ -401,7 +401,7 @@ BOOST_AUTO_TEST_CASE(ExitActions) Cli cli(move(rootMenu)); bool exitActionDone = false; - cli.ExitAction([&](std::ostream&){ exitActionDone=true; }); + cli.ExitAction([&](std::ostream&) noexcept { exitActionDone=true; }); stringstream oss; @@ -425,7 +425,7 @@ BOOST_AUTO_TEST_CASE(Exceptions) // std exception type, custom handler bool excActionDone = false; - cli.StdExceptionHandler( [&](std::ostream&, const std::string&, const std::exception&){ excActionDone = true; } ); + cli.StdExceptionHandler( [&](std::ostream&, const std::string&, const std::exception&) noexcept { excActionDone = true; } ); BOOST_CHECK_NO_THROW( UserInput(cli, oss, "stdexception") ); BOOST_CHECK(excActionDone); diff --git a/test/test_standaloneasioscheduler.cpp b/test/test_standaloneasioscheduler.cpp index 8bdf68c..d8198e3 100644 --- a/test/test_standaloneasioscheduler.cpp +++ b/test/test_standaloneasioscheduler.cpp @@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(StandaloneAsioNonOwner) detail::StandaloneAsioLib::ContextType ioc; StandaloneAsioScheduler scheduler(ioc); bool done = false; - scheduler.Post( [&done](){ done = true; } ); + scheduler.Post( [&done]() noexcept { done = true; } ); ioc.run_one(); BOOST_CHECK(done); } From 429ecc84a5f9de04b13aa64d0c66b02df20a1f2a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 27 Jun 2023 18:43:42 +0200 Subject: [PATCH 046/223] Fix crash when closing telnet server --- include/cli/detail/server.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/include/cli/detail/server.h b/include/cli/detail/server.h index 7d6eb41..8013057 100644 --- a/include/cli/detail/server.h +++ b/include/cli/detail/server.h @@ -125,14 +125,12 @@ class Server Server& operator = ( const Server& ) = delete; Server(typename ASIOLIB::ContextType& ios, unsigned short port) : - acceptor(ios, asiolib::ip::tcp::endpoint(asiolib::ip::tcp::v4(), port)), - socket(ios) + acceptor(ios, asiolib::ip::tcp::endpoint(asiolib::ip::tcp::v4(), port)) { Accept(); } Server(typename ASIOLIB::ContextType& ios, std::string address, unsigned short port) : - acceptor(ios, asiolib::ip::tcp::endpoint(ASIOLIB::IpAddressFromString(address), port)), - socket(ios) + acceptor(ios, asiolib::ip::tcp::endpoint(ASIOLIB::IpAddressFromString(address), port)) { Accept(); } @@ -142,16 +140,16 @@ class Server private: void Accept() { - acceptor.async_accept(socket, [this](asiolibec::error_code ec) + acceptor.async_accept([this](asiolibec::error_code ec, asiolib::ip::tcp::socket socket) { if (!ec) CreateSession(std::move(socket))->Start(); Accept(); }); } asiolib::ip::tcp::acceptor acceptor; - asiolib::ip::tcp::socket socket; }; + } // namespace detail } // namespace cli From 1b94e8a89f31e1d685f738801fe28ca115ccabd2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:48:03 +0200 Subject: [PATCH 047/223] Bump version --- .gitignore | 1 + CHANGELOG.md | 2 +- CMakeLists.txt | 9 ++++++--- README.md | 2 +- doc/doxy/Doxyfile | 2 +- .../boostasio_nonowner_iocontext.vcxproj | 8 ++++---- examples/complete_vsprj/complete.vcxproj | 8 ++++---- examples/filesession_vsprj/filesession.vcxproj | 8 ++++---- examples/pluginmanager_vsprj/pluginmanager.vcxproj | 8 ++++---- .../simplelocalsession_vsprj/simplelocalsession.vcxproj | 8 ++++---- .../standaloneasio_nonowner_iocontext.vcxproj | 8 ++++---- 11 files changed, 34 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index ef6e87a..db31d3c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # Cmake Files CMakeLists.txt.user CMakeCache.txt +CMakeSettings.json CMakeFiles CMakeScripts Testing diff --git a/CHANGELOG.md b/CHANGELOG.md index 8809ced..ca11632 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [2.1.0] - 2023-06-29 - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) - Add ascii value 8 for backspace (issue [#124](https://github.com/daniele77/cli/issues/124)) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6477670..750e7a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,9 +29,12 @@ cmake_minimum_required(VERSION 3.8) -project(cli VERSION 2.0.2 - # DESCRIPTION "A library for interactive command line interfaces in modern C++" - LANGUAGES CXX) +project( + cli + VERSION 2.1.0 + # DESCRIPTION "A library for interactive command line interfaces in modern C++" + LANGUAGES CXX +) include(GNUInstallDirs) diff --git a/README.md b/README.md index 9e2e306..4de34da 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Add something like this in your `CMakeLists.txt` file: FetchContent_Declare( cli GIT_REPOSITORY https://github.com/daniele77/cli.git - GIT_TAG v2.0.2 + GIT_TAG v2.1.0 ) FetchContent_MakeAvailable(cli) diff --git a/doc/doxy/Doxyfile b/doc/doxy/Doxyfile index 0b2a0ae..d487e53 100644 --- a/doc/doxy/Doxyfile +++ b/doc/doxy/Doxyfile @@ -29,7 +29,7 @@ #--------------------------------------------------------------------------- PROJECT_NAME = "Interactive CLI" -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 #--------------------------------------------------------------------------- FULL_PATH_NAMES = NO #--------------------------------------------------------------------------- diff --git a/examples/boostasio_nonowner_iocontext_vsprj/boostasio_nonowner_iocontext.vcxproj b/examples/boostasio_nonowner_iocontext_vsprj/boostasio_nonowner_iocontext.vcxproj index 6b3aa1b..e5ceeff 100644 --- a/examples/boostasio_nonowner_iocontext_vsprj/boostasio_nonowner_iocontext.vcxproj +++ b/examples/boostasio_nonowner_iocontext_vsprj/boostasio_nonowner_iocontext.vcxproj @@ -32,26 +32,26 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode diff --git a/examples/complete_vsprj/complete.vcxproj b/examples/complete_vsprj/complete.vcxproj index 7009a87..a1c2ebd 100644 --- a/examples/complete_vsprj/complete.vcxproj +++ b/examples/complete_vsprj/complete.vcxproj @@ -28,26 +28,26 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte diff --git a/examples/filesession_vsprj/filesession.vcxproj b/examples/filesession_vsprj/filesession.vcxproj index bd54902..77e11d8 100644 --- a/examples/filesession_vsprj/filesession.vcxproj +++ b/examples/filesession_vsprj/filesession.vcxproj @@ -28,26 +28,26 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte diff --git a/examples/pluginmanager_vsprj/pluginmanager.vcxproj b/examples/pluginmanager_vsprj/pluginmanager.vcxproj index f226999..d645983 100644 --- a/examples/pluginmanager_vsprj/pluginmanager.vcxproj +++ b/examples/pluginmanager_vsprj/pluginmanager.vcxproj @@ -28,26 +28,26 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte diff --git a/examples/simplelocalsession_vsprj/simplelocalsession.vcxproj b/examples/simplelocalsession_vsprj/simplelocalsession.vcxproj index aa5651c..1586dfc 100644 --- a/examples/simplelocalsession_vsprj/simplelocalsession.vcxproj +++ b/examples/simplelocalsession_vsprj/simplelocalsession.vcxproj @@ -28,26 +28,26 @@ Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte Application true - v142 + v143 MultiByte Application false - v142 + v143 true MultiByte diff --git a/examples/standaloneasio_nonowner_iocontext_vsprj/standaloneasio_nonowner_iocontext.vcxproj b/examples/standaloneasio_nonowner_iocontext_vsprj/standaloneasio_nonowner_iocontext.vcxproj index 4c58c4e..2695e29 100644 --- a/examples/standaloneasio_nonowner_iocontext_vsprj/standaloneasio_nonowner_iocontext.vcxproj +++ b/examples/standaloneasio_nonowner_iocontext_vsprj/standaloneasio_nonowner_iocontext.vcxproj @@ -32,26 +32,26 @@ Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode Application true - v142 + v143 Unicode Application false - v142 + v143 true Unicode From ef7cacf8cdf72568267e020f90758a7bce7fbf79 Mon Sep 17 00:00:00 2001 From: Marco Maia Date: Tue, 22 Aug 2023 11:07:08 -0300 Subject: [PATCH 048/223] Fix proper operator overloading in README (#208) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4de34da..3f117d7 100644 --- a/README.md +++ b/README.md @@ -403,7 +403,7 @@ myMenu->Insert( } ); ``` -or they can be custom types overloading the `std::istream << operator`: +Or they can be custom types by overloading the `std::istream::operator>>`: ```C++ struct Foo From 29217588d33528ac9bf975435afff9e8dfdb226e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 2 Feb 2024 19:23:32 +0100 Subject: [PATCH 049/223] close #220 (issue with remote session on ARM platforms) --- include/cli/detail/genericasioremotecli.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 576520a..2328831 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -219,13 +219,13 @@ class TelnetSession : public Session void OnDataReceived(const std::string& _data) override { - for (auto c: _data) + for (char c: _data) Consume(c); } private: - void Consume(signed char c) + void Consume(char c) { if (escape) { @@ -244,7 +244,7 @@ class TelnetSession : public Session } } - void Data(signed char c) + void Data(char c) { switch(state) { @@ -407,7 +407,7 @@ class TelnetSession : public Session this -> OutStream() << answer << std::flush; } protected: - virtual void Output(signed char c) + virtual void Output(char c) { #ifdef CLI_TELNET_TRACE std::cout << "data: " << static_cast(c) << std::endl; @@ -467,14 +467,14 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes Prompt(); } - void Output(signed char c) override // NB: C++ does not specify wether char is signed or unsigned + void Output(char c) override // NB: C++ does not specify wether char is signed or unsigned { switch(step) { case Step::_1: switch( c ) { - case EOF: + case static_cast(EOF): case 4: // EOT Notify(std::make_pair(KeyType::eof,' ')); break; case 8: // Backspace From a80cac8ae6129ad167c79584f57de3736e50dd19 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 2 Feb 2024 19:49:16 +0100 Subject: [PATCH 050/223] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca11632..84dfaad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + + - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) + ## [2.1.0] - 2023-06-29 - Nest namespace rang (issue [#167](https://github.com/daniele77/cli/issues/167)) From 260d569a9d367cc41c3d4edd4cf552935ef40910 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 9 Feb 2024 23:18:33 +0100 Subject: [PATCH 051/223] close #223 (custom handler for wrong commands) --- CHANGELOG.md | 1 + README.md | 37 +++++++++++++++++++++++++++++++++++++ examples/complete.cpp | 13 +++++++++++-- include/cli/cli.h | 29 +++++++++++++++++++++++++---- 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84dfaad..e0b1326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) + - Custom handler for wrong commands (issue [#223](https://github.com/daniele77/cli/issues/223)) ## [2.1.0] - 2023-06-29 diff --git a/README.md b/README.md index 3f117d7..b6aa6c0 100644 --- a/README.md +++ b/README.md @@ -455,6 +455,43 @@ cli.EnterAction( cli.ExitAction( [&enterActionDone](std::ostream& out) { out << "Goodbye\n"; }); ``` + +## Custom Handler for Unknown Commands + +You can modify the default behavior of the library for cases where +the user enters an unknown command or its parameters do not match: + +```C++ +Cli cli(std::move(rootMenu)); +cli.WrongCommandHandler( + [](std::ostream& out, const std::string& cmd) + { + out << "Unknown command or incorrect parameters: " + << cmd + << ".\n"; + } +); +``` + +## Standard Exception Custom Handler + +You can handle cases where an exception is thrown inside a command handler +by registering a specific handler: + +```C++ +Cli cli(std::move(rootMenu)); +cli.StdExceptionHandler( + [](std::ostream& out, const std::string& cmd, const std::exception& e) + { + out << "Exception caught in CLI handler: " + << e.what() + << " while handling command: " + << cmd + << ".\n"; + } +); +``` + ## Unicode `cli` uses the input and output stream objects provided by the standard library (such as `std::cin` and `std::cout`) by default, so currently `cli` does not have effective support for unicode input and output. diff --git a/examples/complete.cpp b/examples/complete.cpp index 0472340..0fcd4ca 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -248,9 +248,18 @@ int main() cli.StdExceptionHandler( [](std::ostream& out, const std::string& cmd, const std::exception& e) { - out << "Exception caught in cli handler: " + out << "Exception caught in CLI handler: " << e.what() - << " handling command: " + << " while handling command: " + << cmd + << ".\n"; + } + ); + // custom handler for unknown commands + cli.WrongCommandHandler( + [](std::ostream& out, const std::string& cmd) + { + out << "Unknown command or incorrect parameters: " << cmd << ".\n"; } diff --git a/include/cli/cli.h b/include/cli/cli.h index 8d61911..8ed132e 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -162,14 +162,26 @@ namespace cli * @brief Add an handler that will be called when a @c std::exception (or derived) is thrown inside a command handler. * If an exception handler is not set, the exception will be logget on the session output stream. * - * @param handler the function to be called when an exception is thrown, taking a @c std::ostream& parameter to write on that session console - * and the exception thrown. + * @param handler the function to be called when an exception is thrown, taking a @c std::ostream& parameter to write on that session console, + * the command entered and the exception thrown. */ void StdExceptionHandler(const std::function< void(std::ostream&, const std::string& cmd, const std::exception&) >& handler) { exceptionHandler = handler; } + /** + * @brief Add an handler that will be called when the user enter a wrong command (not existing command or having wrong parameters). + * If an handler is not set, the library will print the message "wrong command" on the console. + * + * @param handler the function to be called when the user enter a wrong command, taking a @c std::ostream& parameter to write on that session console + * and the command entered. + */ + void WrongCommandHandler(const std::function< void(std::ostream&, const std::string& cmd) >& handler) + { + wrongCmdHandler = handler; + } + /** * @brief Get a global out stream object that can be used to print on every session currently connected (local and remote) * @@ -211,6 +223,14 @@ namespace cli out << e.what() << '\n'; } + void WrongCommandHandler(std::ostream& out, const std::string& cmd) + { + if (wrongCmdHandler) + wrongCmdHandler(out, cmd); + else + out << "wrong command: " << cmd << '\n'; + } + void StoreCommands(const std::vector& cmds) { globalHistoryStorage->Store(cmds); @@ -227,6 +247,7 @@ namespace cli std::function enterAction; std::function exitAction; std::function exceptionHandler; + std::function wrongCmdHandler; }; // ******************************************************************** @@ -797,8 +818,8 @@ namespace cli // root menu recursive cmds check if (!found) found = current->ScanCmds(strs, *this); - if (!found) // error msg if not found - out << "wrong command: " << cmd << '\n'; + if (!found) // wrong command handler if not found + cli.WrongCommandHandler(out, cmd); } catch(const std::exception& e) { From ac7d23c577b942b315995110cda8e4557e31f4b6 Mon Sep 17 00:00:00 2001 From: Rob Baily Date: Mon, 19 Feb 2024 13:57:53 -0500 Subject: [PATCH 052/223] close #113 Document Conan packaging support (#225) * close #113 Document Conan packaging support * README update * Spelling corrections --- README.md | 1 + examples/boostasio_nonowner_iocontext.cpp | 4 ++-- examples/complete.cpp | 4 ++-- examples/pluginmanager.cpp | 4 ++-- examples/standaloneasio_nonowner_iocontext.cpp | 4 ++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index b6aa6c0..1cbdf87 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ To migrate your application to new `cli` version, see the section * From [GitHub](https://github.com/daniele77/cli/releases) * Using [Vcpkg](https://github.com/Microsoft/vcpkg) +* Using [Conan](https://conan.io/center/recipes/cli) ## Dependencies diff --git a/examples/boostasio_nonowner_iocontext.cpp b/examples/boostasio_nonowner_iocontext.cpp index f0bfead..b3a214a 100644 --- a/examples/boostasio_nonowner_iocontext.cpp +++ b/examples/boostasio_nonowner_iocontext.cpp @@ -135,11 +135,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << '\n'; + cerr << "Exception caught in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main.\n"; + cerr << "Unknown exception caught in main.\n"; } return -1; } diff --git a/examples/complete.cpp b/examples/complete.cpp index 0fcd4ca..4f31199 100644 --- a/examples/complete.cpp +++ b/examples/complete.cpp @@ -288,11 +288,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << '\n'; + cerr << "Exception caught in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main.\n"; + cerr << "Unknown exception caught in main.\n"; } return -1; } diff --git a/examples/pluginmanager.cpp b/examples/pluginmanager.cpp index 8336d7d..9e0371a 100644 --- a/examples/pluginmanager.cpp +++ b/examples/pluginmanager.cpp @@ -334,11 +334,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << '\n'; + cerr << "Exception caught in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main.\n"; + cerr << "Unknown exception caught in main.\n"; } return -1; } diff --git a/examples/standaloneasio_nonowner_iocontext.cpp b/examples/standaloneasio_nonowner_iocontext.cpp index 88ce0ef..ae37c02 100644 --- a/examples/standaloneasio_nonowner_iocontext.cpp +++ b/examples/standaloneasio_nonowner_iocontext.cpp @@ -127,11 +127,11 @@ int main() } catch (const std::exception& e) { - cerr << "Exception caugth in main: " << e.what() << '\n'; + cerr << "Exception caught in main: " << e.what() << '\n'; } catch (...) { - cerr << "Unknown exception caugth in main.\n"; + cerr << "Unknown exception caught in main.\n"; } return -1; } From 32ef9921fd928d94c061c12020ffb4c5e893e719 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:01:51 +0100 Subject: [PATCH 053/223] Now .. brings to the parent --- include/cli/cli.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/cli/cli.h b/include/cli/cli.h index 8ed132e..06c8626 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -499,6 +499,7 @@ namespace cli { if (!IsEnabled()) return false; + assert(!cmdLine.empty()); if (cmdLine[0] == Name()) { if (cmdLine.size() == 1) @@ -517,6 +518,14 @@ namespace cli return false; } + bool Exec(CliSession& session) + { + if (!IsEnabled()) + return false; + session.Current(this); + return true; + } + bool ScanCmds(const std::vector& cmdLine, CliSession& session) { if (!IsEnabled()) @@ -524,6 +533,9 @@ namespace cli for (auto& cmd: *cmds) if (cmd->Exec(cmdLine, session)) return true; + assert(!cmdLine.empty()); + if (parent && cmdLine[0] == "..") + return parent->Exec(session); return (parent && parent->Exec(cmdLine, session)); } From 4828c725a5dcf9ea66efc5245b2f9ec6780ed1ed Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:31:39 +0100 Subject: [PATCH 054/223] close #234 (Parent menus does not chain) --- CHANGELOG.md | 1 + include/cli/cli.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0b1326..d6525df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) - Custom handler for wrong commands (issue [#223](https://github.com/daniele77/cli/issues/223)) + - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) ## [2.1.0] - 2023-06-29 diff --git a/include/cli/cli.h b/include/cli/cli.h index 8ed132e..5772227 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -512,6 +512,7 @@ namespace cli std::vector subCmdLine(cmdLine.begin()+1, cmdLine.end()); for (auto& cmd: *cmds) if (cmd->Exec( subCmdLine, session )) return true; + return (parent && parent->Exec(subCmdLine, session)); } } return false; @@ -580,6 +581,12 @@ namespace cli for (const auto& c: cs) result.push_back(Name() + ' ' + c); // concat submenu with command } + if (parent != nullptr) + { + auto cc = parent->GetCompletionRecursive(rest); + for (const auto& c: cc) + result.push_back(Name() + ' ' + c); // concat submenu with command + } return result; } return Command::GetCompletionRecursive(line); From 54c433379aecd8043e9ba498b74688496c29e356 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:39:17 +0100 Subject: [PATCH 055/223] Rename variable --- include/cli/cli.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 5772227..6ea44b6 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -583,8 +583,8 @@ namespace cli } if (parent != nullptr) { - auto cc = parent->GetCompletionRecursive(rest); - for (const auto& c: cc) + auto cs = parent->GetCompletionRecursive(rest); + for (const auto& c: cs) result.push_back(Name() + ' ' + c); // concat submenu with command } return result; From 9373d0b378fce1c005222294075ffe178c3fc4c7 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 27 Mar 2024 19:49:57 +0100 Subject: [PATCH 056/223] Fix tests --- test/test_menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_menu.cpp b/test/test_menu.cpp index a5bf488..0bfbcad 100644 --- a/test/test_menu.cpp +++ b/test/test_menu.cpp @@ -89,7 +89,7 @@ BOOST_AUTO_TEST_CASE(Basics) BOOST_CHECK_EQUAL_COLLECTIONS(completions.begin(), completions.end(), expected.begin(), expected.end()); completions = menu.GetCompletions("submenu"); - expected = {"submenu subsubmenu", "submenu foo"}; + expected = {"submenu subsubmenu", "submenu foo", "submenu menu"}; BOOST_CHECK_EQUAL_COLLECTIONS(completions.begin(), completions.end(), expected.begin(), expected.end()); /* @@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(Basics) BOOST_CHECK_EQUAL_COLLECTIONS(completions.begin(), completions.end(), expected.begin(), expected.end()); completions = menu.GetCompletionRecursive("menu submenu"); - expected = {"menu submenu subsubmenu", "menu submenu foo"}; + expected = {"menu submenu subsubmenu", "menu submenu foo", "menu submenu menu"}; BOOST_CHECK_EQUAL_COLLECTIONS(completions.begin(), completions.end(), expected.begin(), expected.end()); } From 090e922093c868c6fdf06b2db57c7822a91f752d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Apr 2024 09:51:56 +0200 Subject: [PATCH 057/223] .. command enters the parent menu --- include/cli/cli.h | 81 +++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index f052a0c..7d14861 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -497,34 +497,12 @@ namespace cli bool Exec(const std::vector& cmdLine, CliSession& session) override { - if (!IsEnabled()) - return false; - assert(!cmdLine.empty()); - if (cmdLine[0] == Name()) - { - if (cmdLine.size() == 1) - { - session.Current(this); - return true; - } - else - { - // check also for subcommands - std::vector subCmdLine(cmdLine.begin()+1, cmdLine.end()); - for (auto& cmd: *cmds) - if (cmd->Exec( subCmdLine, session )) return true; - return (parent && parent->Exec(subCmdLine, session)); - } - } - return false; + return HandleCommand({Name()}, cmdLine, session); } - bool Exec(CliSession& session) + bool ExecParent(const std::vector& cmdLine, CliSession& session) { - if (!IsEnabled()) - return false; - session.Current(this); - return true; + return HandleCommand({Name(), ".."}, cmdLine, session); } bool ScanCmds(const std::vector& cmdLine, CliSession& session) @@ -535,9 +513,7 @@ namespace cli if (cmd->Exec(cmdLine, session)) return true; assert(!cmdLine.empty()); - if (parent && cmdLine[0] == "..") - return parent->Exec(session); - return (parent && parent->Exec(cmdLine, session)); + return (parent && parent->ExecParent(cmdLine, session)); } std::string Prompt() const @@ -606,6 +582,55 @@ namespace cli private: + /** + * Handles a command from the user input. + * + * This function checks if the first element of the `cmdLine` vector matches any of the + * valid commands listed in `cmdNames`. If it does, it performs the following actions: + * - If the `cmdLine` is of length 1 (only the command itself), it sets the current + * session to this object (`session.Current(this)`) and returns true. + * - If the `cmdLine` is longer (includes subcommands), it iterates through registered + * subcommands (`*cmds`) and calls their `Exec` function with the subcommand arguments + * (`subCmdLine`) and the session (`session`). If any subcommand successfully handles + * the command, it returns true. + * - If no subcommand handles the command and a parent object (`parent`) is set, it + * calls the parent's `ExecParent` function with the subcommand arguments and the + * session. + * + * The function returns false if the command is not found, not enabled, or no subcommand or + * parent can handle it. + * + * @param cmdNames - List of valid command names. + * @param cmdLine - User input divided into tokens (command and arguments). + * @param session - Reference to the current CliSession object. + * @return true if the command is handled successfully, false otherwise. + */ + bool HandleCommand(const std::vector& cmdNames, const std::vector& cmdLine, CliSession& session) + { + if (!IsEnabled()) + return false; + + assert(!cmdLine.empty()); + + if (std::find(cmdNames.begin(), cmdNames.end(), cmdLine[0]) != cmdNames.end()) + { + if (cmdLine.size() == 1) + { + session.Current(this); + return true; + } + else + { + // check also for subcommands + std::vector subCmdLine(cmdLine.begin()+1, cmdLine.end()); + for (auto& cmd: *cmds) + if (cmd->Exec( subCmdLine, session )) return true; + return (parent && parent->ExecParent(subCmdLine, session)); + } + } + return false; + } + template CmdHandler Insert(const std::string& name, const std::string& help, const std::vector& parDesc, F& f, R (F::*)(std::ostream& out, Args...) const); From 3d7091e3173935e3f6b7f5ff3dd91196f0227ce5 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:37:04 +0200 Subject: [PATCH 058/223] close #233 (parent menu shortcut) --- CHANGELOG.md | 1 + README.md | 42 ++++++++++----------- include/cli/cli.h | 96 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 95 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6525df..a7f1bdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) - Custom handler for wrong commands (issue [#223](https://github.com/daniele77/cli/issues/223)) - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) + - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) ## [2.1.0] - 2023-06-29 diff --git a/README.md b/README.md index 1cbdf87..1644102 100644 --- a/README.md +++ b/README.md @@ -164,36 +164,36 @@ of the library in this way: ## CLI usage -### Commands and shortcuts - -At the start of your application, cli is presenting a prompt with the +At the start of your application, the CLI presents a prompt with the name you provided in the `Cli` constructor. -This means you're in the root menu. +This indicates you're in the root menu. + +### Navigation + +- **Enter a submenu:** Type the submenu name to enter it. + The prompt will change to reflect the current submenu. +- **Go back to parent menu:** Type the name of the parent menu or `..` to return. +- **Navigate history:** Use up and down arrow keys to navigate through previously entered commands. +- **Exit:** Type `exit` to terminate the CLI application. -To enter in a submenu, just type the submenu name: -you should see the prompt change to reflect the name of the current submenu. +### Commands in any menu -To go back to the parent menu, you must enter the name of the parent menu. +- `help`: Prints a list of available commands with descriptions. +- **Command execution:** + - **Current menu:** Enter the name of a command available in the current menu to execute it. + - **Submenu (full path):** Specify the complete path (separated by spaces) to a command within a submenu to execute it. -In any menu, you can enter: -- `exit`: to exit the cli -- `help`: to print the list of the commands available with a description -- a submenu name: to enter the submenu -- the parent menu name: to return to the parent menu -- a command in the current menu: to exec the command -- a command in a submenu (using the full path): to exec the command +### Autocompletion -You can also use: -- up and down arrow keys: to navigate the history of commands -- tab key: to autocomplete the command / menu +Use the Tab key to get suggestions for completing command or menu names as you type. ### Parameter parsing -The cli interpreter can manage correctly sentences using quote (') and double quote ("). -Any character (spaces too) comprises between quotes or double quotes are considered as a single parameter of a command. -The characters ' and " can be used inside a command parameter by escaping them with a backslash. +The CLI interpreter can handle sentences using single quotes (`'`) and double quotes (`"`). +Any character (including spaces) enclosed within quotes is considered a single parameter for a command. +You can use quotes within parameters by escaping them with a backslash (`\`). -Some example: +**Examples:** cli> echo "this is a single parameter" this is a single parameter diff --git a/include/cli/cli.h b/include/cli/cli.h index 7d14861..1a85faf 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -502,7 +502,7 @@ namespace cli bool ExecParent(const std::vector& cmdLine, CliSession& session) { - return HandleCommand({Name(), ".."}, cmdLine, session); + return HandleCommand({Name(), ParentShortcut()}, cmdLine, session); } bool ScanCmds(const std::vector& cmdLine, CliSession& session) @@ -545,43 +545,88 @@ namespace cli auto result = cli::GetCompletions(cmds, currentLine); if (parent != nullptr) { - auto c = parent->GetCompletionRecursive(currentLine); + auto c = parent->GetCompletionWithParent(currentLine); result.insert(result.end(), std::make_move_iterator(c.begin()), std::make_move_iterator(c.end())); } return result; } - // returns: - // - the completion of this menu command - // - the recursive completions of the subcommands + /** + * Retrieves completion suggestions for the user input recursively. + * + * This function checks if the user input starts with the current command's name. If it + * does, it extracts the remaining part of the input and retrieves suggestions: + * - From subcommands using their `GetCompletionRecursive` function. + * - From the parent command (if available) using its `GetCompletionRecursiveFull` function. + * - (Optional) You can customize the behavior for empty lines to provide top-level commands. + * + * If the input doesn't start with the command name, it delegates to the base class's + * `Command::GetCompletionRecursive` function for handling generic commands. + * + * @param line The user's input string (potentially incomplete command). + * @return A vector containing suggested completions for the user input. + */ std::vector GetCompletionRecursive(const std::string& line) const override { if (line.rfind(Name(), 0) == 0) // line starts_with Name() { - auto rest = line; - rest.erase(0, Name().size()); - // trim_left(rest); - rest.erase(rest.begin(), std::find_if(rest.begin(), rest.end(), [](int ch) { return !std::isspace(ch); })); - std::vector result; - for (const auto& cmd: *cmds) - { - auto cs = cmd->GetCompletionRecursive(rest); - for (const auto& c: cs) - result.push_back(Name() + ' ' + c); // concat submenu with command - } - if (parent != nullptr) - { - auto cs = parent->GetCompletionRecursive(rest); - for (const auto& c: cs) - result.push_back(Name() + ' ' + c); // concat submenu with command - } - return result; + return GetCompletionRecursiveHelper(line, Name()); } + return Command::GetCompletionRecursive(line); } private: + /** + * Retrieves completion suggestions for the user input recursively, including the parent command. + * + * This function is similar to `GetCompletionRecursive` but explicitly includes + * completions from the parent command (if available) using its `GetCompletionRecursiveFull` function. + * This allows navigation within the command hierarchy using "..". + * + * The rest of the functionality remains the same as `GetCompletionRecursive`. + * + * @param line The user's input string (potentially incomplete command). + * @return A vector containing suggested completions for the user input. + */ + std::vector GetCompletionWithParent(const std::string& line) const + { + if (line.rfind(Name(), 0) == 0) // line starts_with Name() + { + return GetCompletionRecursiveHelper(line, Name()); + } + + if (line.rfind(ParentShortcut(), 0) == 0) // line starts_with .. + { + return GetCompletionRecursiveHelper(line, ParentShortcut()); + } + + return Command::GetCompletionRecursive(line); + } + + std::vector GetCompletionRecursiveHelper(const std::string& line, const std::string& prefix) const + { + auto rest = line; + rest.erase(0, prefix.size()); + // trim_left(rest); + rest.erase(rest.begin(), std::find_if(rest.begin(), rest.end(), [](int ch) { return !std::isspace(ch); })); + std::vector result; + for (const auto& cmd: *cmds) + { + auto cs = cmd->GetCompletionRecursive(rest); + for (const auto& c: cs) + result.push_back(prefix + ' ' + c); // concat submenu with command + } + if (parent != nullptr) + { + auto cs = parent->GetCompletionWithParent(rest); + for (const auto& c: cs) + result.push_back(prefix + ' ' + c); // concat submenu with command + } + return result; + } + /** * Handles a command from the user input. * @@ -631,6 +676,11 @@ namespace cli return false; } + static std::string ParentShortcut() + { + return ".."; + } + template CmdHandler Insert(const std::string& name, const std::string& help, const std::vector& parDesc, F& f, R (F::*)(std::ostream& out, Args...) const); From ee14ce04ca2cfd4ea735e80530816f9eda1ae520 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:45:54 +0200 Subject: [PATCH 059/223] close #236 (Integer overflow warning detected by clang++) --- CHANGELOG.md | 1 + include/cli/detail/fromstring.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f1bdf..8418fe0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Custom handler for wrong commands (issue [#223](https://github.com/daniele77/cli/issues/223)) - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) + - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) ## [2.1.0] - 2023-06-29 diff --git a/include/cli/detail/fromstring.h b/include/cli/detail/fromstring.h index e66fd85..0bfbced 100644 --- a/include/cli/detail/fromstring.h +++ b/include/cli/detail/fromstring.h @@ -131,7 +131,8 @@ inline T signed_from_string(std::string s) { s = s.substr(1); const U val = unsigned_digits_from_string(s); - if ( val > static_cast( - std::numeric_limits::min() ) ) + const auto min = std::numeric_limits::min(); // this to avoid overflow warnings + if ( val > static_cast( - min ) ) throw bad_conversion(); return (- static_cast(val)); } From af87753d86e5b2e16e5aebd07da7cd839a7fc4d3 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 3 Apr 2024 18:59:40 +0200 Subject: [PATCH 060/223] close #236 (Integer overflow warning detected by clang++) --- examples/pluginmanager.cpp | 6 +++--- include/cli/detail/fromstring.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/pluginmanager.cpp b/examples/pluginmanager.cpp index 9e0371a..b7f6b11 100644 --- a/examples/pluginmanager.cpp +++ b/examples/pluginmanager.cpp @@ -98,7 +98,7 @@ class PluginContainer { auto p = PluginRegistry::Instance().Create(plugin, menu); if (p) - plugins.push_back(move(p)); + plugins.push_back(std::move(p)); } void Unload(const string& plugin) { @@ -187,7 +187,7 @@ class Arithmetic : public RegisteredPlugin }, "Print the result of a subtraction" ); - menuHandler = menu->Insert(move(subMenu)); + menuHandler = menu->Insert(std::move(subMenu)); } ~Arithmetic() override { @@ -237,7 +237,7 @@ class Strings : public RegisteredPlugin out << "\n"; }, "Alphabetically sort a list of words" ); - menuHandler = menu->Insert(move(subMenu)); + menuHandler = menu->Insert(std::move(subMenu)); } ~Strings() override { diff --git a/include/cli/detail/fromstring.h b/include/cli/detail/fromstring.h index 0bfbced..606b3e2 100644 --- a/include/cli/detail/fromstring.h +++ b/include/cli/detail/fromstring.h @@ -131,7 +131,7 @@ inline T signed_from_string(std::string s) { s = s.substr(1); const U val = unsigned_digits_from_string(s); - const auto min = std::numeric_limits::min(); // this to avoid overflow warnings + auto min = std::numeric_limits::min(); // this to avoid overflow warnings. Please NOTE: const auto produces warning! if ( val > static_cast( - min ) ) throw bad_conversion(); return (- static_cast(val)); From 17dafd8c50d828a3334586dd558a12270ba6bdc0 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:07:47 +0200 Subject: [PATCH 061/223] close #239 (enable keyboard handling in command handlers on linux) --- CHANGELOG.md | 1 + include/cli/detail/inputdevice.h | 2 ++ include/cli/detail/inputhandler.h | 8 ++++++-- include/cli/detail/linuxkeyboard.h | 26 ++++++++++++++++++++++++-- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8418fe0..566faa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) + - Enable Keyboard Handling in Command Handlers on Linux Platform (issue [#239](https://github.com/daniele77/cli/issues/239)) ## [2.1.0] - 2023-06-29 diff --git a/include/cli/detail/inputdevice.h b/include/cli/detail/inputdevice.h index 5655ed8..bb536e3 100644 --- a/include/cli/detail/inputdevice.h +++ b/include/cli/detail/inputdevice.h @@ -48,6 +48,8 @@ class InputDevice explicit InputDevice(Scheduler& _scheduler) : scheduler(_scheduler) {} virtual ~InputDevice() = default; + virtual void ActivateInput() {} + virtual void DeactivateInput() {} template void Register(H&& h) { handler = std::forward(h); } diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/inputhandler.h index ac9170e..5f0310e 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/inputhandler.h @@ -45,9 +45,10 @@ namespace detail class InputHandler { public: - InputHandler(CliSession& _session, InputDevice& kb) : + InputHandler(CliSession& _session, InputDevice& _kb) : session(_session), - terminal(session.OutStream()) + terminal(session.OutStream()), + kb(_kb) { kb.Register( [this](auto key){ this->Keypressed(key); } ); } @@ -75,8 +76,10 @@ class InputHandler } case Symbol::command: { + kb.DeactivateInput(); session.Feed(s.second); session.Prompt(); + kb.ActivateInput(); break; } case Symbol::down: @@ -124,6 +127,7 @@ class InputHandler CliSession& session; Terminal terminal; + InputDevice& kb; }; } // namespace detail diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 72ec901..d58e396 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -32,13 +32,14 @@ #include #include +#include #include #include #include #include #include - +#include #include "inputdevice.h" @@ -106,9 +107,10 @@ class LinuxKeyboard : public InputDevice public: explicit LinuxKeyboard(Scheduler& _scheduler) : InputDevice(_scheduler), + enabled(false), servant( [this]() noexcept { Read(); } ) { - ToManualMode(); + ActivateInput(); } ~LinuxKeyboard() override { @@ -116,6 +118,19 @@ class LinuxKeyboard : public InputDevice is.Stop(); servant.join(); } + void ActivateInput() override + { + ToManualMode(); + std::lock_guard lock(mtx); + enabled = true; + cv.notify_one(); + } + void DeactivateInput() override + { + ToStandardMode(); + std::lock_guard lock(mtx); + enabled = false; + } private: @@ -125,6 +140,10 @@ class LinuxKeyboard : public InputDevice { while (true) { + { + std::unique_lock lock(mtx); + cv.wait(lock, [this]{ return enabled; }); // release mtx, suspend thread execution until enabled becomes true + } auto k = Get(); Notify(k); } @@ -205,10 +224,13 @@ class LinuxKeyboard : public InputDevice tcsetattr(STDIN_FILENO, TCSANOW, &oldt); } + bool enabled; termios oldt; termios newt; InputSource is; std::thread servant; + std::mutex mtx; + std::condition_variable cv; }; } // namespace detail From 60a1f787c65cfe6625132d9584bb6c0bb0008e62 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:08:35 +0200 Subject: [PATCH 062/223] Update README.md --- README.md | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1644102..1bac29b 100644 --- a/README.md +++ b/README.md @@ -314,30 +314,23 @@ You can add menus to existing menus, to get a hierarchy: ```C++ auto rootMenu = make_unique("myprompt"); - auto menuA = make_unique("a_prompt"); -rootMenu->Insert( std::move(menuA) ); - auto menuAA = make_unique("aa_prompt"); -menuA->Insert( std::move(menuAA) ); - auto menuAB = make_unique("ab_prompt"); -menuA->Insert( std::move(menuAB) ); - auto menuAC = make_unique("ac_prompt"); -menuA->Insert( std::move(menuAC) ); - auto menuACA = make_unique("aca_prompt"); -menuAC->Insert( std::move(menuACA) ); - auto menuB = make_unique("b_prompt"); -rootMenu->Insert( std::move(menuB) ); - auto menuBA = make_unique("ba_prompt"); -menuB->Insert( std::move(menuBA) ); - auto menuBB = make_unique("bb_prompt"); + +menuAC->Insert( std::move(menuACA) ); +menuB->Insert( std::move(menuBA) ); menuB->Insert( std::move(menuBB) ); +menuA->Insert( std::move(menuAA) ); +menuA->Insert( std::move(menuAB) ); +menuA->Insert( std::move(menuAC) ); +rootMenu->Insert( std::move(menuA) ); +rootMenu->Insert( std::move(menuB) ); ``` This results in this tree: From a4a0474ad10b0f36acd5bec700caeb1ea559901f Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 7 May 2024 00:47:07 +0200 Subject: [PATCH 063/223] add clear terminal with CTRL+L --- include/cli/detail/inputdevice.h | 2 +- include/cli/detail/inputhandler.h | 6 ++++++ include/cli/detail/linuxkeyboard.h | 1 + include/cli/detail/terminal.h | 12 +++++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/cli/detail/inputdevice.h b/include/cli/detail/inputdevice.h index bb536e3..62a369f 100644 --- a/include/cli/detail/inputdevice.h +++ b/include/cli/detail/inputdevice.h @@ -39,7 +39,7 @@ namespace cli namespace detail { -enum class KeyType { ascii, up, down, left, right, backspace, canc, home, end, ret, eof, ignored }; +enum class KeyType { ascii, up, down, left, right, backspace, canc, home, end, ret, eof, ignored, clear, }; class InputDevice { diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/inputhandler.h index 5f0310e..bc5ee34 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/inputhandler.h @@ -121,6 +121,12 @@ class InputHandler terminal.SetLine( line ); break; } + case Symbol::clear: + { + session.Prompt(); + terminal.ResetCursor(); + break; + } } } diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index d58e396..8fa2401 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -177,6 +177,7 @@ class LinuxKeyboard : public InputDevice case 8: return std::make_pair(KeyType::backspace,' '); break; case 10: return std::make_pair(KeyType::ret,' '); break; + case 12: return std::make_pair(KeyType::clear, ' '); break; case 27: // symbol ch = GetChar(); if ( ch == 91 ) // arrow keys diff --git a/include/cli/detail/terminal.h b/include/cli/detail/terminal.h index e9a4f6d..6489055 100644 --- a/include/cli/detail/terminal.h +++ b/include/cli/detail/terminal.h @@ -46,7 +46,8 @@ enum class Symbol up, down, tab, - eof + eof, + clear }; class Terminal @@ -193,9 +194,16 @@ class Terminal position = 0; break; } + case KeyType::clear: + { + out << CLEAR_ESCAPE << std::flush; + return std::make_pair(Symbol::clear, std::string()); + break; + } case KeyType::ignored: // TODO break; + } return std::make_pair(Symbol::nothing, std::string()); @@ -205,6 +213,8 @@ class Terminal std::string currentLine; std::size_t position = 0; // next writing position in currentLine std::ostream &out; + const std::string_view CLEAR_ESCAPE = "\033[H\033[J"; + }; } // namespace detail From b99fbead4d292c582745f528fb0bc60f32767e09 Mon Sep 17 00:00:00 2001 From: Luca Date: Tue, 7 May 2024 00:58:14 +0200 Subject: [PATCH 064/223] add windows ctrl-L --- include/cli/detail/winkeyboard.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/cli/detail/winkeyboard.h b/include/cli/detail/winkeyboard.h index 0ed159d..b02b6b8 100644 --- a/include/cli/detail/winkeyboard.h +++ b/include/cli/detail/winkeyboard.h @@ -160,6 +160,9 @@ class WinKeyboard : public InputDevice case 8: return std::make_pair(KeyType::backspace, c); break; + case 12: // CTRL-L + return std::make_pair(KeyType::clear, ' '); + break; case 13: return std::make_pair(KeyType::ret, c); break; From 8ae64716ff353bc673eefc932ebe66bd1f1c3789 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 9 May 2024 23:46:00 +0200 Subject: [PATCH 065/223] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1bac29b..3fafbfa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ ![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg) +[![CodeQL](https://github.com/daniele77/cli/actions/workflows/codeql.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/codeql.yml) + # cli From 66c94062a990ff26980973f140a4bccdea3c74ce Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 14 May 2024 16:05:40 +0200 Subject: [PATCH 066/223] Clear Screen preserves current input line --- include/cli/detail/genericasioremotecli.h | 4 ++++ include/cli/detail/inputhandler.h | 3 +++ include/cli/detail/terminal.h | 8 ++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 2328831..8cf7a72 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -475,12 +475,16 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes switch( c ) { case static_cast(EOF): + [[fallthrough]]; case 4: // EOT Notify(std::make_pair(KeyType::eof,' ')); break; case 8: // Backspace + [[fallthrough]]; case 127: // Backspace or Delete Notify(std::make_pair(KeyType::backspace, ' ')); break; //case 10: Notify(std::make_pair(KeyType::ret,' ')); break; + case 12: // ctrl+L + Notify(std::make_pair(KeyType::clear, ' ')); break; case 27: step = Step::_2; break; // symbol case 13: step = Step::wait_0; break; // wait for 0 (ENTER key) default: // ascii diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/inputhandler.h index bc5ee34..4f7c6d6 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/inputhandler.h @@ -123,8 +123,11 @@ class InputHandler } case Symbol::clear: { + const auto currentLine = terminal.GetLine(); + terminal.Clear(); session.Prompt(); terminal.ResetCursor(); + terminal.SetLine(currentLine); break; } } diff --git a/include/cli/detail/terminal.h b/include/cli/detail/terminal.h index 6489055..d6a1d73 100644 --- a/include/cli/detail/terminal.h +++ b/include/cli/detail/terminal.h @@ -57,6 +57,8 @@ class Terminal void ResetCursor() { position = 0; } + void Clear() const { out << "\033[H\033[J" << std::flush; } + void SetLine(const std::string &newLine) { out << beforeInput @@ -195,15 +197,11 @@ class Terminal break; } case KeyType::clear: - { - out << CLEAR_ESCAPE << std::flush; return std::make_pair(Symbol::clear, std::string()); break; - } case KeyType::ignored: // TODO break; - } return std::make_pair(Symbol::nothing, std::string()); @@ -213,8 +211,6 @@ class Terminal std::string currentLine; std::size_t position = 0; // next writing position in currentLine std::ostream &out; - const std::string_view CLEAR_ESCAPE = "\033[H\033[J"; - }; } // namespace detail From ff211359bb6a97ebf73ce3d508aa8ea93960c389 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 15 May 2024 19:00:06 +0200 Subject: [PATCH 067/223] ctrl+L works on linux, windows and telnet --- include/cli/clilocalsession.h | 3 +- include/cli/detail/genericasioremotecli.h | 3 +- include/cli/detail/inputhandler.h | 3 +- include/cli/detail/screen.h | 59 +++++++++++++++++++++ include/cli/detail/telnetscreen.h | 48 ++++++++++++++++++ include/cli/detail/terminal.h | 3 +- include/cli/detail/winscreen.h | 62 +++++++++++++++++++++++ 7 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 include/cli/detail/screen.h create mode 100644 include/cli/detail/telnetscreen.h create mode 100644 include/cli/detail/winscreen.h diff --git a/include/cli/clilocalsession.h b/include/cli/clilocalsession.h index 5528350..9d1feeb 100644 --- a/include/cli/clilocalsession.h +++ b/include/cli/clilocalsession.h @@ -34,6 +34,7 @@ #include "detail/inputhandler.h" #include "cli.h" // CliSession #include "detail/keyboard.h" +#include "detail/screen.h" namespace cli { @@ -70,7 +71,7 @@ class CliLocalTerminalSession : public CliSession private: detail::Keyboard kb; - detail::InputHandler ih; + detail::InputHandler ih; }; using CliLocalSession = CliLocalTerminalSession; diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 8cf7a72..1d7a329 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -36,6 +36,7 @@ #include "server.h" #include "inputdevice.h" #include "genericasioscheduler.h" +#include "screen.h" namespace cli { @@ -545,7 +546,7 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes enum class Step { _1, _2, _3, _4, wait_0 }; Step step = Step::_1; - InputHandler poll; + InputHandler poll; }; template diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/inputhandler.h index 4f7c6d6..214df44 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/inputhandler.h @@ -42,6 +42,7 @@ namespace cli namespace detail { +template class InputHandler { public: @@ -135,7 +136,7 @@ class InputHandler } CliSession& session; - Terminal terminal; + Terminal terminal; InputDevice& kb; }; diff --git a/include/cli/detail/screen.h b/include/cli/detail/screen.h new file mode 100644 index 0000000..d8ce34b --- /dev/null +++ b/include/cli/detail/screen.h @@ -0,0 +1,59 @@ +/******************************************************************************* + * CLI - A simple command line interface. + * Copyright (C) 2016-2024 Daniele Pallastrelli + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ******************************************************************************/ + +#ifndef CLI_DETAIL_SCREEN_H_ +#define CLI_DETAIL_SCREEN_H_ + +#if defined(__unix__) || defined(__unix) || defined(__linux__) + #define OS_LINUX +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) + #define OS_WIN +#elif defined(__APPLE__) || defined(__MACH__) + #define OS_MAC +#else + #error "Platform not supported (yet)." +#endif + +#include "telnetscreen.h" + +#if defined(OS_LINUX) || defined(OS_MAC) + namespace cli { namespace detail { using LocalScreen = TelnetScreen; } } +#elif defined(OS_WIN) + #include "winscreen.h" + namespace cli { namespace detail { using LocalScreen = WinScreen; } } +#else + #error "Platform not supported (yet)." +#endif + +#undef OS_LINUX +#undef OS_WIN +#undef OS_MAC + +#endif // CLI_DETAIL_SCREEN_H_ + diff --git a/include/cli/detail/telnetscreen.h b/include/cli/detail/telnetscreen.h new file mode 100644 index 0000000..71916b3 --- /dev/null +++ b/include/cli/detail/telnetscreen.h @@ -0,0 +1,48 @@ +/******************************************************************************* + * CLI - A simple command line interface. + * Copyright (C) 2016-2024 Daniele Pallastrelli + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ******************************************************************************/ + +#ifndef CLI_DETAIL_TELNETSCREEN_H_ +#define CLI_DETAIL_TELNETSCREEN_H_ + +#include + +namespace cli +{ +namespace detail +{ + +struct TelnetScreen +{ + static void Clear(std::ostream& out) { out << "\033[H\033[J" << std::flush; } +}; + +} // namespace detail +} // namespace cli + +#endif // CLI_DETAIL_TELNETSCREEN_H_ diff --git a/include/cli/detail/terminal.h b/include/cli/detail/terminal.h index d6a1d73..f720fd8 100644 --- a/include/cli/detail/terminal.h +++ b/include/cli/detail/terminal.h @@ -50,6 +50,7 @@ enum class Symbol clear }; +template class Terminal { public: @@ -57,7 +58,7 @@ class Terminal void ResetCursor() { position = 0; } - void Clear() const { out << "\033[H\033[J" << std::flush; } + void Clear() const { SCREEN::Clear(out); } void SetLine(const std::string &newLine) { diff --git a/include/cli/detail/winscreen.h b/include/cli/detail/winscreen.h new file mode 100644 index 0000000..9af3e8d --- /dev/null +++ b/include/cli/detail/winscreen.h @@ -0,0 +1,62 @@ +/******************************************************************************* + * CLI - A simple command line interface. + * Copyright (C) 2016-2024 Daniele Pallastrelli + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ******************************************************************************/ + +#ifndef CLI_DETAIL_WINSCREEN_H_ +#define CLI_DETAIL_WINSCREEN_H_ + +#if !defined(NOMINMAX) +#define NOMINMAX 1 // prevent windows from defining min and max macros +#endif // !defined(NOMINMAX) +#include + +namespace cli +{ +namespace detail +{ + +struct WinScreen +{ + static void Clear(std::ostream& /*out*/) + { + HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + COORD coord = { 0, 0 }; + DWORD count; + + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hStdOut, &csbi); + + FillConsoleOutputCharacter(hStdOut, ' ', csbi.dwSize.X * csbi.dwSize.Y, coord, &count); + SetConsoleCursorPosition(hStdOut, coord); + } +}; + +} // namespace detail +} // namespace cli + +#endif // CLI_DETAIL_WINSCREEN_H_ From e9d1bab7fb3cfcf3770f93368807cf7a91c7637a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 21 May 2024 09:24:26 +0200 Subject: [PATCH 068/223] Export platform detection macros in a separate header file --- include/cli/detail/keyboard.h | 18 +++----------- include/cli/detail/platform.h | 44 +++++++++++++++++++++++++++++++++++ include/cli/detail/screen.h | 19 +++------------ 3 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 include/cli/detail/platform.h diff --git a/include/cli/detail/keyboard.h b/include/cli/detail/keyboard.h index e300d25..6d71be2 100644 --- a/include/cli/detail/keyboard.h +++ b/include/cli/detail/keyboard.h @@ -30,29 +30,17 @@ #ifndef CLI_DETAIL_KEYBOARD_H_ #define CLI_DETAIL_KEYBOARD_H_ -#if defined(__unix__) || defined(__unix) || defined(__linux__) - #define OS_LINUX -#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) - #define OS_WIN -#elif defined(__APPLE__) || defined(__MACH__) - #define OS_MAC -#else - #error "Platform not supported (yet)." -#endif +#include "platform.h" -#if defined(OS_LINUX) || defined(OS_MAC) +#if defined(CLI_OS_LINUX) || defined(CLI_OS_MAC) #include "linuxkeyboard.h" namespace cli { namespace detail { using Keyboard = LinuxKeyboard; } } -#elif defined(OS_WIN) +#elif defined(CLI_OS_WIN) #include "winkeyboard.h" namespace cli { namespace detail { using Keyboard = WinKeyboard; } } #else #error "Platform not supported (yet)." #endif -#undef OS_LINUX -#undef OS_WIN -#undef OS_MAC - #endif // CLI_DETAIL_KEYBOARD_H_ diff --git a/include/cli/detail/platform.h b/include/cli/detail/platform.h new file mode 100644 index 0000000..1ed999c --- /dev/null +++ b/include/cli/detail/platform.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * CLI - A simple command line interface. + * Copyright (C) 2016-2024 Daniele Pallastrelli + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + ******************************************************************************/ + +#ifndef CLI_DETAIL_PLATFORM_H_ +#define CLI_DETAIL_PLATFORM_H_ + +#if defined(__unix__) || defined(__unix) || defined(__linux__) + #define CLI_OS_LINUX +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) + #define CLI_OS_WIN +#elif defined(__APPLE__) || defined(__MACH__) + #define CLI_OS_MAC +#else + #error "Platform not supported (yet)." +#endif + +#endif // CLI_DETAIL_PLATFORM_H_ + diff --git a/include/cli/detail/screen.h b/include/cli/detail/screen.h index d8ce34b..df4936a 100644 --- a/include/cli/detail/screen.h +++ b/include/cli/detail/screen.h @@ -30,30 +30,17 @@ #ifndef CLI_DETAIL_SCREEN_H_ #define CLI_DETAIL_SCREEN_H_ -#if defined(__unix__) || defined(__unix) || defined(__linux__) - #define OS_LINUX -#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64) - #define OS_WIN -#elif defined(__APPLE__) || defined(__MACH__) - #define OS_MAC -#else - #error "Platform not supported (yet)." -#endif - +#include "platform.h" #include "telnetscreen.h" -#if defined(OS_LINUX) || defined(OS_MAC) +#if defined(CLI_OS_LINUX) || defined(CLI_OS_MAC) namespace cli { namespace detail { using LocalScreen = TelnetScreen; } } -#elif defined(OS_WIN) +#elif defined(CLI_OS_WIN) #include "winscreen.h" namespace cli { namespace detail { using LocalScreen = WinScreen; } } #else #error "Platform not supported (yet)." #endif -#undef OS_LINUX -#undef OS_WIN -#undef OS_MAC - #endif // CLI_DETAIL_SCREEN_H_ From 18396ab8e4b825abcf09116c8ad083166742b081 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 21 May 2024 10:05:15 +0200 Subject: [PATCH 069/223] Rename InputHandler to CommandProcessor --- include/cli/clilocalsession.h | 4 +- .../{inputhandler.h => commandprocessor.h} | 37 ++++++++++++++++--- include/cli/detail/genericasioremotecli.h | 4 +- 3 files changed, 36 insertions(+), 9 deletions(-) rename include/cli/detail/{inputhandler.h => commandprocessor.h} (81%) diff --git a/include/cli/clilocalsession.h b/include/cli/clilocalsession.h index 9d1feeb..3265a19 100644 --- a/include/cli/clilocalsession.h +++ b/include/cli/clilocalsession.h @@ -31,7 +31,7 @@ #define CLI_CLILOCALSESSION_H #include // std::ostream -#include "detail/inputhandler.h" +#include "detail/commandprocessor.h" #include "cli.h" // CliSession #include "detail/keyboard.h" #include "detail/screen.h" @@ -71,7 +71,7 @@ class CliLocalTerminalSession : public CliSession private: detail::Keyboard kb; - detail::InputHandler ih; + detail::CommandProcessor ih; }; using CliLocalSession = CliLocalTerminalSession; diff --git a/include/cli/detail/inputhandler.h b/include/cli/detail/commandprocessor.h similarity index 81% rename from include/cli/detail/inputhandler.h rename to include/cli/detail/commandprocessor.h index 214df44..ea8f6a0 100644 --- a/include/cli/detail/inputhandler.h +++ b/include/cli/detail/commandprocessor.h @@ -27,8 +27,8 @@ * DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#ifndef CLI_DETAIL_INPUTHANDLER_H_ -#define CLI_DETAIL_INPUTHANDLER_H_ +#ifndef CLI_DETAIL_COMMANDPROCESSOR_H_ +#define CLI_DETAIL_COMMANDPROCESSOR_H_ #include #include @@ -42,11 +42,27 @@ namespace cli namespace detail { +/** + * @class CommandProcessor + * @brief This class handles user input and processes commands in a CLI session. + * + * The CommandProcessor class is responsible for handling user input from an InputDevice, + * processing the input into commands, and executing these commands in a CLI session. + * It also provides functionality for command history navigation and command auto-completion. + * + * @tparam SCREEN The type of the terminal screen. + */ template -class InputHandler +class CommandProcessor { public: - InputHandler(CliSession& _session, InputDevice& _kb) : + /** + * @brief Construct a new CommandProcessor object. + * + * @param _session The CLI session to be managed. + * @param _kb The input device to be used. + */ + CommandProcessor(CliSession& _session, InputDevice& _kb) : session(_session), terminal(session.OutStream()), kb(_kb) @@ -56,12 +72,22 @@ class InputHandler private: + /** + * @brief Handle a keypress event. + * + * @param k The key that was pressed. + */ void Keypressed(std::pair k) { const std::pair s = terminal.Keypressed(k); NewCommand(s); } + /** + * @brief Process a new command. + * + * @param s The symbol and string representing the command. + */ void NewCommand(const std::pair& s) { switch (s.first) @@ -143,5 +169,6 @@ class InputHandler } // namespace detail } // namespace cli -#endif // CLI_DETAIL_INPUTHANDLER_H_ +#endif // CLI_DETAIL_COMMANDPROCESSOR_H_ + diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 1d7a329..5b07d06 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -32,7 +32,7 @@ #include #include "../cli.h" -#include "inputhandler.h" +#include "commandprocessor.h" #include "server.h" #include "inputdevice.h" #include "genericasioscheduler.h" @@ -546,7 +546,7 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes enum class Step { _1, _2, _3, _4, wait_0 }; Step step = Step::_1; - InputHandler poll; + CommandProcessor poll; }; template From 8b5da1759873cbd0dce51aa9fbbab6efb9ca7fd4 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 21 May 2024 10:27:15 +0200 Subject: [PATCH 070/223] close #229 (add clear screen command using ctrl-L) --- CHANGELOG.md | 1 + README.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 566faa3..42c5c0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) - Enable Keyboard Handling in Command Handlers on Linux Platform (issue [#239](https://github.com/daniele77/cli/issues/239)) + - Add clear screen command using ctrl + L (issue [#229](https://github.com/daniele77/cli/issues/229)) ## [2.1.0] - 2023-06-29 diff --git a/README.md b/README.md index 3fafbfa..8c72e30 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,10 @@ This indicates you're in the root menu. Use the Tab key to get suggestions for completing command or menu names as you type. +### Screen Clearing + +Press `Ctrl-L` to clear the screen at any time. + ### Parameter parsing The CLI interpreter can handle sentences using single quotes (`'`) and double quotes (`"`). From b3c8f8210e3cede87761865b10c3739a5175a980 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 21 May 2024 10:45:46 +0200 Subject: [PATCH 071/223] Update UML diagrams and remove [[fallthrough]] because it's C++17 --- doc/uml/cli.uml | 340 +++++++++++++++++++--- doc/uml/implementation.png | Bin 47708 -> 53237 bytes include/cli/detail/genericasioremotecli.h | 2 - 3 files changed, 301 insertions(+), 41 deletions(-) diff --git a/doc/uml/cli.uml b/doc/uml/cli.uml index 19d92ed..e7e7930 100644 --- a/doc/uml/cli.uml +++ b/doc/uml/cli.uml @@ -20,7 +20,7 @@ oEKMHKU6mE+m/a0pz8BhbAAA oEKMHKU6mE+m/a0pz8BhbAAA -63 +69 clMaroon $008CC7FF @@ -641,8 +641,8 @@ $00ADD39C 708 668 -118 -82 +140 +98 k0xzFwLELEuiW5O6+cJeKgAA @@ -663,7 +663,6 @@ k0xzFwLELEuiW5O6+cJeKgAA -False k0xzFwLELEuiW5O6+cJeKgAA @@ -671,14 +670,14 @@ clMaroon $00ADD39C 660 -800 -129 -46 +820 +153 +59 ZrKIbc2h9UiX3VckmuMUxAAA 1 -InputHandler +CommandProcessor False @@ -694,7 +693,6 @@ ZrKIbc2h9UiX3VckmuMUxAAA -False ZrKIbc2h9UiX3VckmuMUxAAA @@ -702,7 +700,7 @@ clMaroon $00B9FFFF lsRectilinear -680,800;680,553 +680,820;680,553 Lcf1JQtSikCLkJLFQhEojAAA cAYfTB+XvkKH0Itv3nkBcAAA 7Ef3BQms7EmzQhyYeH2k3gAA @@ -1161,7 +1159,7 @@ clMaroon $00B9FFFF lsRectilinear -788,812;872,812;872,708;984,708 +812,840;872,840;872,708;984,708 kBMx9okl1E+/6otAoCk92wAA RfCB3p//B06jtFIxJ3bt8QAA 7Ef3BQms7EmzQhyYeH2k3gAA @@ -1447,7 +1445,7 @@ clMaroon $00B9FFFF lsRectilinear -788,832;848,832;848,948;1132,948 +812,868;848,868;848,948;1132,948 PouNuHuoq0urswc/Z8Vz2wAA HxW4qmceQ0K97zXdfiP5HAAA 7Ef3BQms7EmzQhyYeH2k3gAA @@ -1532,7 +1530,7 @@ clMaroon $00B9FFFF lsRectilinear -756,749;756,800 +756,765;756,820 ivhaI9tpsEyvRvOTq9QsUQAA 7Ef3BQms7EmzQhyYeH2k3gAA wezzfHtUP0CYmR9LnpXbfgAA @@ -1760,7 +1758,7 @@ clMaroon $00B9FFFF lsRectilinear -680,845;680,948 +680,878;680,948 Xuoq/PcdGUi7vE2IM10R+AAA jpsEsVgK9k6jXu/jiH9jSgAA 7Ef3BQms7EmzQhyYeH2k3gAA @@ -2787,8 +2785,8 @@ clMaroon $00CEB694 -764 -488 +724 +504 96 56 s2Iwv+rItUqlsLKHfr2iuwAA @@ -2819,7 +2817,7 @@ clMaroon $00B9FFFF lsRectilinear -792,668;792,543 +764,668;764,559 IlzfnO06D0OvY+GUMXxxAQAA qtX+GLbeIEKZf8LW43rK8wAA wezzfHtUP0CYmR9LnpXbfgAA @@ -2904,7 +2902,7 @@ clMaroon $00B9FFFF lsRectilinear -764,524;692,524 +724,524;692,524 RgNqxlPBVEmE427D4nszbwAA cAYfTB+XvkKH0Itv3nkBcAAA qtX+GLbeIEKZf8LW43rK8wAA @@ -2985,6 +2983,180 @@ VEgY36xa4U2KMtQJCuBQUwAA + +clMaroon +$00ADD39C +936 +432 +80 +56 +J7ZlA8kB00KGuPg6YlBfzAAA + + +1 +LocalScreen + + +False + + +False + + + +J7ZlA8kB00KGuPg6YlBfzAAA + + +J7ZlA8kB00KGuPg6YlBfzAAA + + +False +J7ZlA8kB00KGuPg6YlBfzAAA + + + +clMaroon +$00ADD39C +936 +496 +86 +56 +5YW72IpFpkyfjBJV0jX9SAAA + + +1 +TelnetScreen + + +False + + +False + + + +5YW72IpFpkyfjBJV0jX9SAAA + + +5YW72IpFpkyfjBJV0jX9SAAA + + +False +5YW72IpFpkyfjBJV0jX9SAAA + + + +clMaroon +$00ADD39C +932 +560 +91 +56 +6fgV4QJsJk6Jjpc1CxIwIAAA + + +1 +WinScreen + + +False + + +False + + + +6fgV4QJsJk6Jjpc1CxIwIAAA + + +6fgV4QJsJk6Jjpc1CxIwIAAA + + +False +6fgV4QJsJk6Jjpc1CxIwIAAA + + + +clMaroon +$00B9FFFF +lsRectilinear +847,684;952,684;952,615 +NrNJq/Wiw0m42wrCXstKTAAA +/HuKWa4wMkqkSbZxvyRL/AAA +wezzfHtUP0CYmR9LnpXbfgAA + +False +1,5707963267949 +15 +NrNJq/Wiw0m42wrCXstKTAAA + + +False +1,5707963267949 +30 +NrNJq/Wiw0m42wrCXstKTAAA + + +False +-1,5707963267949 +15 +NrNJq/Wiw0m42wrCXstKTAAA + + + +clMaroon +$00B9FFFF +lsRectilinear +847,676;900,676;900,516;936,516 +7O5BCh3Sg0iP6Vt8/PxZ2AAA +640IYTOgRkuoUkMurgkBTwAA +wezzfHtUP0CYmR9LnpXbfgAA + +False +1,5707963267949 +15 +7O5BCh3Sg0iP6Vt8/PxZ2AAA + + +False +1,5707963267949 +30 +7O5BCh3Sg0iP6Vt8/PxZ2AAA + + +False +-1,5707963267949 +15 +7O5BCh3Sg0iP6Vt8/PxZ2AAA + + + +clMaroon +$00B9FFFF +lsRectilinear +847,668;884,668;884,456;936,456 +GUId6shvmUaYZUsbjBkRoQAA +O6idmn/2F0G2QGsbJviViwAA +wezzfHtUP0CYmR9LnpXbfgAA + +False +1,5707963267949 +15 +GUId6shvmUaYZUsbjBkRoQAA + + +False +1,5707963267949 +30 +GUId6shvmUaYZUsbjBkRoQAA + + +False +-1,5707963267949 +15 +GUId6shvmUaYZUsbjBkRoQAA + + @@ -3715,7 +3887,7 @@ -69 +75 CliSession NLtrxd0pREa5saxYXXatOgAA @@ -4035,36 +4207,45 @@ GSfST7YktkCZZRTCzfeZfQAA z3eJDl7ylUSYd2pkk49hEgAA C5aHiT2+QUigN7/IKHMmxwAA -3 - -Register -k0xzFwLELEuiW5O6+cJeKgAA -1 - -handler -PJCV2TnlnEO4f0j5mPwHqAAA - +3 +NrNJq/Wiw0m42wrCXstKTAAA +7O5BCh3Sg0iP6Vt8/PxZ2AAA +GUId6shvmUaYZUsbjBkRoQAA +1 + +SCREEN +k0xzFwLELEuiW5O6+cJeKgAA - +3 + SetLine k0xzFwLELEuiW5O6+cJeKgAA - + ResetCursor k0xzFwLELEuiW5O6+cJeKgAA + +KeyPressed +k0xzFwLELEuiW5O6+cJeKgAA + 2 odPh4KR73EOr2nyHtHHmdAAA 9b7b8YY8r0SlDrXweD49RQAA -InputHandler +CommandProcessor NLtrxd0pREa5saxYXXatOgAA 4 7Ef3BQms7EmzQhyYeH2k3gAA fun+n57M4Ei1awtQKPu8bQAA oKEtOL8xpUyEfcOk8B7e0wAA BR5RgDC9U0yt7g8GGX/PXQAA +1 + +SCREEN +ZrKIbc2h9UiX3VckmuMUxAAA + 5 qYli0bcUo06T8FGe7cOpYQAA K0X4B2lQtkSZs9vWQqU97gAA @@ -5121,8 +5302,8 @@ k0xzFwLELEuiW5O6+cJeKgAA 4 DInaM1xL3EKpPRbQpqSLNQAA -10N81H03+Uu5MvalmW/WHwAA -K+DZQTBi80Oh/lYi9qc2JQAA +K+DZQTBi80Oh/lYi9qc2JQAA +10N81H03+Uu5MvalmW/WHwAA KlDlNHGXVkG1+TiODEhk4gAA @@ -5130,8 +5311,8 @@ s2Iwv+rItUqlsLKHfr2iuwAA 4 0VSXW3LqnEKW9/1MVUT8vQAA -HFiqWFrizEinscWbyku6DgAA -BjRaQOgdbUK9NsIEvHAcFwAA +BjRaQOgdbUK9NsIEvHAcFwAA +HFiqWFrizEinscWbyku6DgAA zkzsJNWYnEu8UAGktaYq5gAA @@ -5148,8 +5329,8 @@ s2Iwv+rItUqlsLKHfr2iuwAA 4 EH7z3/T88E2Fsqc8iipgiQAA -yjxcYUIl9EGueWh803dXhwAA -PVxU6qCGYE2X6Fnqy8wCigAA +PVxU6qCGYE2X6Fnqy8wCigAA +yjxcYUIl9EGueWh803dXhwAA 1npp+CihGki5SxEbgnqASQAA @@ -5158,11 +5339,92 @@ TRhgwOteGUCFcmtcX/iZ1wAA 4 oa26Yq7qhUGpdSN9IpHFlAAA -MdhKVdpkVke/ou3lM9pa9wAA -5JLMNItIqkaYrfkV4QdFfgAA +5JLMNItIqkaYrfkV4QdFfgAA +MdhKVdpkVke/ou3lM9pa9wAA E2q7kEICT0qDkzrdEugyAAAA + +LocalScreen +NLtrxd0pREa5saxYXXatOgAA +4 +O6idmn/2F0G2QGsbJviViwAA +zl4Olroye0qEkPw75NCrLgAA +fZEWtYhB2EStzpWh1QhE2QAA +5luvnapvEkirk5WImWIK3AAA +1 +GUId6shvmUaYZUsbjBkRoQAA +1 + +Clear +skClassifier +J7ZlA8kB00KGuPg6YlBfzAAA + + + +TelnetScreen +NLtrxd0pREa5saxYXXatOgAA +4 +640IYTOgRkuoUkMurgkBTwAA +E0tXV9S+4UK5M+KlcmoRaAAA +Lhxar+Z2XUq+kueLH+1wKgAA +4TLEU5rgkUWUUk+8+91KSAAA +1 +7O5BCh3Sg0iP6Vt8/PxZ2AAA +1 + +Clear +skClassifier +5YW72IpFpkyfjBJV0jX9SAAA + + + +WinScreen +NLtrxd0pREa5saxYXXatOgAA +4 +/HuKWa4wMkqkSbZxvyRL/AAA +XlWLuiDsvkipj3u4XPwmHwAA +H8hCvopcOU6zLTTS5/1q0QAA +7rhlVhsQ5UmbyIFS1GB4rgAA +1 +NrNJq/Wiw0m42wrCXstKTAAA +1 + +Clear +skClassifier +6fgV4QJsJk6Jjpc1CxIwIAAA + + + +NLtrxd0pREa5saxYXXatOgAA +k0xzFwLELEuiW5O6+cJeKgAA +6fgV4QJsJk6Jjpc1CxIwIAAA +4 +1bvTXiZdm0mMYUVeJD91AAAA +cPbslDDB1068fB9MUgvgFAAA +WZwo7RJddU+sJZBPMgngKgAA +YENya15VHUuO45hKZyW5iAAA + + +NLtrxd0pREa5saxYXXatOgAA +k0xzFwLELEuiW5O6+cJeKgAA +5YW72IpFpkyfjBJV0jX9SAAA +4 +5DdHxHDe102ZYKiqOEaeLQAA +rij/j4fEG0GS4FYF2OylBAAA +Dc0ds2ZMKkOSD1p27gxOhAAA +TgFVhLrxvkm6FmRsLzZAvwAA + + +NLtrxd0pREa5saxYXXatOgAA +k0xzFwLELEuiW5O6+cJeKgAA +J7ZlA8kB00KGuPg6YlBfzAAA +4 +pAaqPcHMxk6i8jyHJpnWLAAA +NVc8m7iV10+ndca3IgwoDAAA +iop1AkA+40Od0vbXCR9sJwAA +A7CFufc2qEe97xcmCbrbHAAA + diff --git a/doc/uml/implementation.png b/doc/uml/implementation.png index 25edd63cdc39422e61375e56246563a992578aad..a4105e9c11f404563fb6439d97e5998ccdbb1c16 100644 GIT binary patch literal 53237 zcmeFZcTkgEyDyAgP(Z;*lMW(=sv=00CLP2QAT%iop^6{~q1X@!(xo@SARq(;LT?Jv zq#C3*={58gTFwgA=h^R`+4G$_^Uaw#e>e`weXn)3b=BXB?{!TjN(x2_GBPqs6=j7R zWMqc|$;b{~Il3QwatLLyLq^t8s-hr!>ru~aKQZvkL>%je#qP5$+3#~_!#S$Y=(8!u zoAnLV4Z#Q4jE*Gjk9v$XQ>u%;z;XP5yzmjKL*ys(n6lD7?q_)7^juNwI-8?tS8fr_ zRr0SVy7Q>>Z9=FXIGpB?tz)!9hrP~?XeEA(nSP&{IhVP6;bMEgmQIYM1kxk3O_qATfq2M7fGO|@R44LIQM0LKQ=g{XNHIuRGixbq%#k?M92-#IBWhfcr z`8n)xoY@g$qXsYWrO$CG^9c__#lg2^p=ZIXsW015m);ky&sOsU4oc1BzYYeAsz;Ny zOVWVa?R-zJ&Yc&;NIQ--xU33l8Cz8BEMVjt><#)|=5ed*S!eyIGb-q*yp|{G8$77( zGo(Hs8zDU zG|=aAir4Jn!sg!347r)uPvKB=cZTcq;|jpDWM?%{B$T1J<4Ji!D**?m26T)w*@1*3*+{ZijDR!$Ojfh!AE2XnK&UA;H~j^~O@$7e9+;*5d`9 z3%KF#b^VI+J(KZidT2LKDPvqxUQ~GzX+&tAUbSf&#RL0j>MTWe)OHK~S&$E->uF}s zC}n_rI22~cWKBKW>{U`UiYaqpDeBE(&xmR!Y3=seMIArDJ_px)5SC_x6>TyXd8Ws zAer;t8A%=Dlr6@gxSmd*K}Bx|ZZ0`;r_qH3R1h1A@gS>HkNwI zkrA21@p|h(X|b7>#CyMmY^8>%9;4GdQ+{iMP)F+$U+$$};xWc+;lLd5nLFn2%oN(T4t(xd;cQ zaBaF$ADO!!H9Vuv?$Wi57xnU38xF0N>2Y6N?y#TN@GO;hPCY1&-L7fxND8BCiKRB| z4Th;d{p}$swV(nO_lI!@;y7Lo3k4;&bD0*dK8px=k!4UcQL9I$t$Znm-gH?fYqm!h zdB2jgGgqd$B@ zMaW7VJkenmq9bLaeTuKwu+g0aI@1ymjq2Ir*Dpw+CW zn>^M942eylEJrUe{MKV$GB#;~mt~4peT#Kk*wVED=zsUV)>2_md`i@fKSzQw3@}uC ziINd#?BQ-Vwl!3=UEB9&Y${9glM~}_0<09^4j^_EtlguY?{eSylIid6t|Z;Z>D8$8 zBTV^pEKO8?wXa~#tnd;s_Hjd z+TiG*3}bl?p~6q5C*c|s{?_nFIqo=!4~jp7>>X)CX=lDznTlso=No{xP|__MD4VT& z5~fxmU`{!e8YI|f;OUCV#g$ovas%(Q73Xs7nQTrSrxOI`6eyf%`b#Lw<4f7zRie%D z{m6^6McKuS&2|P?%8^Vl3^09Rb9&{?kxn~7=R+s(1(MDs%j!WS8+YFt%~O(3ROfsZ z=^GmN%dbQ#6*M!$`#i6Iy}*T;WH@}IkrBt5u=zdNy->-45L~bnwmiflH6ncqrXK!N zryonB9@#3kv|U9F$?cAe`?+%|OCL9%PtNq7dUQhTK-BqPHbJ-)>!iVS6 zqV`OAM{p(Us`qbwykEj5Su`pu?Y?Q_)OvZI6jp!cBk!{?Z2NyPOv#N&{iEvW7?RtcSFTyShm1!VR{Xm!i&T`Hw2oreq7y_O zhuYQ|;bDxi7N~F#*%}(y9q>GqPoHHT8Yt~7;o9jqG`TU~za3=Uo%gjY=eIFaszZw< zdR2@!m9}~fhXY&6?k^{%_#8f>SG*WAgP({u@*HYkSb5v) zJ-^VL{Y<9Maj|~Hgo&HWP|HW-cSQd72%%Ua=;1ObuIDWWk8fpcxGzO;MXdUcvF->- zijMLh31Q>xZorofO;~qUeer9Vb>(*5A_YvZq+Iu#NR^VurmdQRq;QpvjB^(>A%xmz z7)|%Wot;Dj&Jd*r8)8EizcQ{4Wi3OZp9M@!O(Ro7ILXA^h{=Qtm0;;yXxJGy9(2ijDzKPldSP zQ#(r7i6+x-Iif`fHn(i7lAXt!D=?YT^A4vMdS*Oepa(fI)k-Y#mb9Bxfx1N-x^1uz zKCpP>|63cY$&k1kPYqJ;v15-h;Ch}kf1^&+trogZ;k&y?r+4^kgqV{?U+eqXM-Iel zogAv|mvN^DdqI{TcEP;2TQa=)OFxrfx$tpiXmL*w;VZN5yb5iPcI6nIk=uH9hi+iG zyzZITu;U14&y7Sb&0hz`G8O;oAn#P_dPTa;f-*OvIw;PL7c-f)Z%RwoE&P=-^aj2$ zDYp%zn%f&Ut&xJ5K2NKw0gl$&*d!;|u{@ABlQhq0C6Q~hMp-!Nrc<(Pe7RwKKyAnD z(zSOGLo?AAb53>2LG1mzPG}WebMw`({5f(yWPsiBfhnp}0fzmK(ovG8%Z7v0#@5wP zJh_rq1u;f+ZYQqe8_f=q;j(?TcW^?HE6DdY0nO%@k@LBBm017Ky>#=mk0!SEromn| z-%U|nV6G*^A4ANM#7rJ{oz!=1)%0o3xq?3R;t>T1J(4R&Y6bvI(DnIf>2E-we1{TfQ>xEBt!5@kIu3y z*K=O!ra>rDUc$ofQM1B+u8_wsobz-VH*LA`B}{NoWG2wU2ozfX+}94SeTF<|e#jrhnlaI} zd^uFe6Q&q7lFeuL`h*V}*?FH-30i!+Q(qEdJ16e3P!kMNDBUi#Nnaiuzs;0h{HcHQ z(i#CPb)5a)VBJ5%$9(0)u3P6vVP@7f9d#_Ne`e{(TD@P1rmX;io7r1Wh$_Pv>6Fcb z=^E&w?Lk9CTCu-m8{Hw_1@hC(!LtksFqN-*Ad{U`L{!8KU0i zcJ%f;2%futM7l?9fGBt2G8Ys1(t}6YNE(f0*ewv}|EUgqqyEV`sjcB%zpRye3`~Nt zVtvt07n!cyIJ1}y#Nd>wJQW#iE)h=-BKp6CfA}5bW<PY0lzl2AZ0c`K0)%fs!z6r9n(s(7#qS z>EnrXmT7XD_cN0*a3=4Uae6+VxA z^mfBc{57XdraRJpgV3`&9MaJt&dr3EW$j-*MJkNGE`&ji%dIwD z3}@cNtD-{M-EgRKuHo<=6bjffs6NR+>)`|%A_Ww#B6QM7(s7qokKSQ(I(}KDd||OD zY~CjeU$LQ@e{a1oa4lrLBIp$*g6{6~_-^qgeeIKfc63WZ-J&g~7CLByfQSPmM! zo$9vr^>2C~xPhsFQtc}ErwmOBetj!rJW!$x+0hiG_2(N(9md;et3myjf|xh^|N58* z6ZsID8VRfx_!7X~)hZR}y?%=Gz)pYdk zfsm^9uR*khH9uA*OH4y3woUH4AQ+oY+J!7l@kRHE z?I-avx^luw9scQz!``1)Z#BBrox1da?$+$q)DapP3to~O6z(olt!AzoHx@&_b=UgH z^nNr7!agMo^BsE3hIyQ-42`^m@b+X|bPOjgdG!_=q7FaMhT08C$Ycw4ME(9S8p|OdAu|y=E=4qd1C}UnG+uL_C3qxRAH--Nkq_qQVgW!hUzF zWp{Dx{-l1zMhbBvBT#sMm=_}sHPpa<_~(17$%yKf-TA7)LK+sr=4LMP?AMM$94hXN z&E`Np`I)cZWc*Fgkg5pzLPO#w(&w>T_=?S3ul1IeQWv7H z*YdELOR|dWc|)3>MOoy~+x0lt)d%H6Xr_u8+z9a=9=|fN1v4V*D9z2;EGLw&+ZW&T z#fBR6d0MD!u2pRD)X&WgdJRh0S43om+X+2CiR88Ra@dLiN1?w&dC;?DrYz8XM`pmq zwRD66)52wK@u~KJO#0fQ-Q1Y|P+;5Jb1YkR5I5=AmA8`w`UV;QS$E~*$9=D5aboC~ z3xwn~HTPt!YHzEU=s7e}YP{pM5P-c6vf;ctc<=SF=x`C1+W_r75 zm$sT}jnflQLv6x0n(jJxmB^M`dt zSab;GFWh0(eHQ7^*PddmVIHrB2h*i{&G)h?LFjiVtWE9)!dzM&UsNmiMJ6Qx17 z*J>8$B$NcN*dx`rE>L@}&kQkn7!GHCI%ya;P%64RdBpVyQfq>ryNW~AigH)qHE?qz za~y(0tr!;mPx{GW5sL6D;FPmBMoRGP_J?;iW21f;!>%h79@pMvho`OBoER*`-89#xFTLK8!YqNQs||4)2%BVP z)jm_6O&B;JGc|vYI7ghGN~W`h=9Im%@w!XeQ)II$LjZG*ct1ZLmWrVd1?OX|@!;P1 zc-@%OJ^jdMYrSG!vrhFu&bK!uba48J?A2hlY9o(#UIQpoZy>Il}BGE_^Uz>GwbMeSEsgEArXoMpPS*Zl`+O~OjpjL1hUv$p$_rG zFnN(@l}m_vvqlfHXGyntI$!Ht2puSXF{~U^`rL%*v0kxbgn(-g z?6ywbD|jW*aIZvb;I>9kOU{+)LW&WE;>#P0tu0n1oU&h}V*^!XYN#8eDO(P9??)VR zZ2Gxd+6wtQ5s?cfCaGu95PkgA6ax*@1lP~gt=($46x2bxd zsuBtV-bg6=hg(bHz}&&1fjd0(YW(LiHY0k6Kiu}mADa5@4o^VxAnMUQD7}LH*Bmqd z@=B&1n8#m#xJ*(fA2h9jx4v^};{0zS_q;WIQxV19=?{hpA#nfu%XF8@$33J?t*BXh zxT^8bltVq8)|+*$4HG74g0Tdw>elb|;FRMA1f|M%yfgto;>twx1&Sk=(?k(^93f5OS`@~%)EeqK&mY4qs@)B^5 z;IFD5QodBVjfTY7M%o^@gS@vps2TV9K1ju*z^sQ-NC#2f*h{8AR*DI4+4HKF;Do7% zEa$_e_d@HNwH%A5*o=(9E5z>~Ma(AIKerz4IzM5X=N`Y8D-_YY9Tmpz%m3o4&!50U zviz$8FIeP`+djrT7=SfQ?D>}?EX~FUI?e?{>`T z8SHq?^`+gj7UFm7{Jjbq@zOS$LcK zLu=(jEU_Jko${F-Ozhi*7aB}@w$)>1$9y__(oY?SOLMl5i!}0-%~%m6N#2L-2Ie?h zY=7ZJ4kqOg?-(BaZ18YxHxTUJ6v9%izIOU0lk5)a$HJeyg&^O+tcr z*?lqWv!H=sHp43_pWckM@nEjb7hC<%#p6rCM`v7in}_0A`ZbGtUqGQ5&CFWTD(xF4Fz0ORg2s|V#{2u2Iyy4nNes9#C{Gj+PH!GlwB-1U z){zdF6J{VrgbPvaecx$u_<{6iPD5OR<*5F2v&30l{ovB%{tvs6X0aE7Mq4*2RKCI9 zxEPB3)V5uQE7UGdVr^W0V)@+g=u-7f573fYj~_cwjZKo|sXH8mE{Xb93Ng%9}(wHQwxqJHr!Bl%axt%cT@9ZuQH0e7wW zFd5I8ki}L|ITwnc7gQ0sqBfbtp`IReJUK1_mLX^?S-NxK1mckP2B9M6;jwF59iM1H z7oZC?6R)0q!BTm!_xdXc4u`^oKRF(Y=8SPZb&pgrh>!~T&#m&2Ht??u-Ps{6(%Ie@ zg7$^cOKqlAH~@63=W z2gd+ML7xB$E07oOJxMZnqeeBj$p9eb@DEZ*=fX9lMSpQf9~A26Bpug3ZssX*Ms42) z^z?#(DT$t!iIhTGC`5HZm3Q6|jx#f$f&ADOzj!Y!aau6)CU_V(tNGVAq?QP`L zqYq~Jv@4mcpMSnsse4) z|FNy|X#ZBXGtGH*=)DJQZhGpyl8yRcuD7=>7aF3S$65n~^*9=IP=5XymI4vJXb*Oa z17k*)a36*>S~NtcJku3w3Wm3jF~GTiddFJkl{`t(;G^iwl|_c!>GR6aJMPONzZtj` zhvleTt127^V){XRk^-XB`-WW#C~*{@<9!_P=P(-^eP3K)RaH#1o*^%Rhymx?rbg%0 zEbP(?j87!8PmLO^uO&k+Rcqoo1JwUFYgYT(ok6$A3`sItcbk1ujeZjTdvS zTn8>oJG(GA1DeWHpwm*nUg0=Buvg*19-R!AA=FGKADHQ6@wmTSJ0_a>E`3gITCkGZ z2rjwhxjS-Jk6I-~9| zG&Sat={#vd*|&`c$1ESLB!JGrB4M+st zQrk))gx)RVM#U`?HRqN2htaZJ+%%-oSd|oAf+WilclF?SmP?%U#uD5z%+Mw;?w`DZ z8T&9o#-`hO0#g`9J!7c{2a_&blct;l#_;~h;!rXq*=`=dHl`(%Ley&X0ht z>^AgnPOMh%&>8dc*$`dXg4NTb0uHKhdDE-d2wz@?k$vn?fvVbwVjfL&eZi-w%K6AP z^wwxWRd>a)+^h-ugvFGO%|U5PLMpW?T-I=p@mKb$c|n~34jDEF#7EZnM1{B}QEV_+r8JXya3sq(aIYH|> zNAt+?`eaCiv6#cgjm-xV7pak+hKhTtPVJo>$jQiJ>(O1f6*pZ<2uPsOa0SCKAT%ZU!*{G6i+0BZqBvR zvOXyt!dKa%YchF|Mjptd0j$Kz ziiUtpD@(AF#!A-=KS=b}JCngOwa&o`Mhb5Fetn6pdQq4}iF7N%YKy)k+6`kKV{-M%wff%N zz~r4ZcNf>?8iT}%1EnxeGjMgk8ZWtxzBGh>lKhUJ!8LwZVzVU!07wey8~d)i7gK|P%LaNgyWEsJY<#)HI5SL;LK z%#HmJ;o0pFsuxdK?@R?#xo@@R$^k{)28udYL5ml7%WNHc|4?2|KhoYBKR5E_aycHH z{7+8pG8o;Sic{r}hQ64URQXI$Nx2A@daS<3CiQ_F7*TdrjMPRRbRV(WVhuJuDSOl# zn3sZm%g zI*a42D26_#@>7o1*4vXx=fS}P`Sk0q8*t$j>32!kB==H>huU@dGUpJ7+S(suhd+0h zS=g}DcLgJQYSDGXH3KTa*1zOAa=un8&5Im%6**RWIT z?F4KxIBrr1MPD$P@K|?FYhrpEI`1`c-@)A82;F0pX#Zv@D`Kt8Yt;?ek-e7HLHye5 zbEL1`_U?!YsljSS zEtpewvkm3&Lhcrr3b{N|?B<_ zBM6G7%#1YKCOD5c?px}_@tv{ zq$x-50)s+5t-3v>Z-0Rd4SKdsV5eaIPPYXZfj(vk2F77zs~8PK&x9YQsIoGU(5`$# z=-Qm0uIvzHsX4P9yX%oQv(ONaSI3W>?415bk^_8uUz-mOjNP3VHsV5ESQ;4uP=Smz;LL ze7pTpqPa#*NtId!dRUzqz5(KuBWRfO%^MmTTDL2s$7t#Wd$?)K)Wl^3_Y!VR0b|Mb zF9HIr`i0nuS${w89KQ~@3P!PR9XHTwDzS9bd&8{c$k#6H@WwT9L^bD(OFW*78cfII zhuCo_lnX!RO$2Z%=Rro3y@TZlJ51q$sIEI%RN`l^W%Q7G5^q}*E@~ux!>#N4g!aux zs?c#2D6A`no3>s#AjpD7RBPZ0>t?uQm!W<(VfbbWod9!pm!sA4s`vd%#vwk;Q%mlG zF%nnuEI9RV!iB#qU`<^nPNt+amqNqXXFh*`@)8W)w0n#?eHS@eBsIpUY7(y3V@4KRymibUSjuv78?{9PdzreabR z8eo4$-}0evFN79jlay}Umm8-E0C{f!sseP8$R2+I=}F_J<|RMsnuNY|+>YH)a4HVv zdP5POT{59l&1KqZ1lrp#uunnT`v)}_%W3)3^CQv2+i`czv<`#DRA?sp&TKH7RJP)L zhxEhZoy?Fjr?zRfA#L&rMLmKLL|;xJ!u}Zb}1JoELnMIcQGaoI*k#36(oq z$Z+ka9{1`bVUUw3_iyIPD^+~I7spcHw;QV!H z1Tc}gpX&FRJpN#&Z^SR%J|!!nx!f~(MJ6R)oqbBJB7Dbcti+|6xVFY5&V{M-67fvR zE*c+>T8n(Tb9;5I)^_1d;QBZK0&cRoc7hJZ_PU*CUCLZj>hZJT$dKBxXdN7I-Gy?szi%)*Jjh0S&Pqd_Y9t% zG$!u|867SQb#ZRZr`VqDs%$`BE_ac%dHbA;_e-Jc65WK0JDD&*qgcJ{!v!B0%5qsH zItCd`w3H7Lc-~su`5l;{bBUYYRYHqmQf(fSLqKJ{ca&>3OY}N*hg|~7PBhDS5S!;X zC+zR%U`@f8Br5ahoBoJ_{sK){Vo*2_w&nuX(@1=)f6PzN=a~G!k}{1s7t+<<{*f)- zN>|Uzqa|$=51pwHtLV}zPb)(kUKO@Xfd)QjT7Q@oI?v5FFO^%|QIIz~>G^<51L`Ik zzq`iN&Gs~x$IgJy{0yGsWk+}@GynJ)j~dTq+~&(BB3^+V&%8R%ofUY_CjY~tb1o~N ztqIL>X3D|xoRQ(|NE|BPVSEo^De5IH^nFf0Dc{uSmt!nex_1|w}KOIY? zIsV+xQg-d2$9s{ExAP}XA4!JDN5`>xrrJ>8t|&v@67Fnz$28z=IMO~G?XQ36VCQF} za-m`T69HOc4Qc{1lJhss5Uxis+t+<@%WdQUQ_nJsGLIZF#v-qbr936NiTisN$d~}b zQZkU=z-iBW>2!Y&R>h&%CHil`zZxIF4NlDKUEshd=Uwz`)|8QSnbeYgIJO)?<+1SX z@tKK^4TK`%y!J>Bsy?!W*FTzc#efuD=yUUv-WWoKJ>g#q;#|+f@?j!@-@jMK7vph2 zpm?BtZabnWhd}tB0-?$XMa%VrGopj524dYPogUhN`0}DhW-U7UH`P|=?{<|!=&pH= zuf`Xc-WZ>C&~75N;7B31RcqzMu#i#*xuACeB6w$pM0dNo&b@GGJ&z!|UxMo+Rz&O9iW$LfG zg!89!E&%C%%0N@Vxn3QBqgk6+Zq+&>?Tj8hQJg@2K?rkBY8x(1dyo|LNXh-86;#~O z>NIg6O!JvO8du0D$)A(%7Ez&y_jLii(cNx-p`HLH$71jR?_r9*G z&=)&~cEcm8Xp+R~(V#8B4Si@qp`x{$H>(5Hj}1222v_sU%T;(g?&Yk zO@%|bpC7w*A#o|QZE7TQIV?0bX|)0%5L4);K@@erNWwNbP_bJ7X6f^3&{E7_n&_V4 z)N1@L{op=a*n3~gUbr$ZM(%a(wv`iE9}&gDWDo0mOPCZG}69l(*T$?Uu!M$K0cgSjJm4srgBtUM@`J!A!cEAr8pR6oAV2 zZKA-*$ObG2!yZm8h8}M1xtdt8 zUnWcMC|>SGGA)LR7$tYeGX-Vx{S=K9dEGFQC--=gpu=SJ<)qu)*}K(#DLET=K5P2T zcO!^@>?d)@%-yMHp}(YC0AP856bsao%{{?G%90hIgmx+l){@fJ@TX@B{3 z3A2!!I}X>x&t55$=P$1#hIHh*x0cx~t`&HxKr3{ClGk=1b{7uB11HzH0hA1IrhrVM z;oWCS=T)FDW}S{96wAl>a&^zhV9sf9e}m0Bb>43IEcu;A%6rNu74_SQm4k+j%f7(6 z00<+VCQd2!Xj z+E8l(A^h8x#A~kHil<+X&cv1%Pq>F@U@h7<>PjL0Y`}9<+MaWLim)iJUo!|(IltIl zW&JOpYvC`TtKMZA^nE_5mV*qy1}}fSDC=B4LvZ~f()Ozwd=&+Iem(YN?#{us5WUL< zmubvLylH*(X|3)((@=%-_GoF^QY)({J;e^>ZK^}V7Sw~T1;G?dPPbh(_onZqZwi*t zGDl(Jz(DnP@iy(iBmT?zD41Lhh2@W*=-=wc96BA*t93DIJp=&2lyyac8m zH@TLDiO2czKE;u>+!29Ntj&QZ!GlUV|L3vcO%(GYffSNoe1 zN}~5~R#7?DLeAx0VE}!8SYxLNStKKQqNmoVK zovSX0=G9Qlw7<+Il_M3HEM!M!RgnpafL5OGL^Ef6_y>|t>Uja~A!&R3;<2V1Ce7>seSLcQAwAi(zl_o1dMi^r z!xt(2H>(cS$bjwvFTm}44oqY*8lAMN-qzuG^)4ir^Dmmu3dFx+0|W!y5IBZ^c=>NX zPba=GgB7qXVxLo}K+iT720r>*PxUAs&X+0Nx0K=9NgE4(pVyupcC@Miql`bqx4tRy zpBnTg5ylNX9Y|24EgW|aaj3?Z*kOy>)8!5$voksYgZ=MIH~hx@ z=b8Ue*n_lTudttB0oRw}Y@UcI|7AYpKgm)9bs89JaLR^ja{0>VEP!gbd~+^wqSAYw zd2lD!?3m1z2NT^#B<6SeV*1-@%N9S6P0$H=NHaj>&irNV)#&3D?UCdD%0LMZfJKV8 zpD6mFwN0g`T%p%9%FDi`eK^-_yI8kb{0Lsjr3}6BwhiSpSvw(km)7E}B7;ep znDxCu$><0$dIy*3{+Rp8A3LZ7!OUMY>IbVQ5rCBgwDT?9=cN9Ct^wv^fnq*a)ZJy- zmV>_0*r$ws1o7i!H#sqpFCSfa`eU=R=cA^F$7$;)1Lwq#nX>(5Bkx6bHEPiIO2Y_p zT3}-z&}dT;-h#S>2daF3(XO~UTz~Y(BX6?*{=7Qh%}2OMA_QzRstmQ{`-^hz>?Vm< znDV<15Q<#gMn=I6 z-#O4Z+A}bZv5o#*X}4kz=bQq#y>LPr(=w~x#Lslnm@0*#-fC=gW}2cpOUmpFE?KeYI2yUHQq5W1)A~Kz`{28OKB(*(){F zHGew%>ertgCr)aqb&;xH>s*`sdpVQ9!~##anoGrXRbG@GfAZh%kbU#OIJ)rR++y`F z*Y(oppAYYIRELA7ELzo7&%;8K{5nQ7??M)Rr9inNybRYR*olwSkC`P%m4-`ltf#rK z8XI^Zr)FpFn)%`M%$6Awx`1oq`5CeIk4J+3W;7@OCxbu}I_i&9KmloO)P`!+ix*Jm zkMr0WZ4zXjlMEEC=R4iP?M+XhP`PqVeCG=ojD^ngvkd6M-L|INoe5gI=?F@L5ZHf` z#UXzYaBHBz6rPpb-k%4FKsx%5;{6a@*_}%{Qx-F~iH&xB~ape)D%>X#pG{9{dNT z07B*wiff;vN_RQ*XlgW|6jf4S3=^i*(P6|Sqc%-E9+Beb5}-nEh>F`H*gK z0bsBC+fS47jX(d4qN1%ho?Vz#r_nY&)D2vo@w$)DgbQEEBqz=9Z_>8JDM|91@BrAZ zRO*UitPiZAMN)1Rz=o9m%R{}YDfX$;)|fE{&@)$tz6bEwGo1%XNZd#z9Ln~L_M(?X zf6~(F=3>Yyn0bW*E)8f&w?6K$0K~6@0*(R=X$R{5LFJ*wICibYjM2G#PnUWe#SI+F z3K(0h$UcAsH?m)mAa@+pooc zi{SDy%w|OQa9Mz?4L%KuP|O3O9Em0)!FQLH;n`IqC_KHHwU(g@6a>-V?A(-kqUgPz z_pnSYfKX^^rw_8%e|(KYi8GS~3NC8=Sx{KyXHp~w*G?Hh71=%nH%R^n;oaFEPL^uy ziDI6yrD01@m4-607yJC`q7*u@bMB{nA9eR>b`vOU>F$Y{8E=t=UE3O z{mzonAFrxRRXKH$PvD;yo+aH!`S@*;SEE_1U{!cA{bu*(+muV}X3kNj z9a&i*dP9~gJF$nz({}K5_Ac3 zamy7_Gw+UbV(zFfuMgho`>nl`Oo-~(_lodEkZTO;Hh96ovz#(2Z76>!LBY)OGN-jw zXzhIbLryhiDE-Y9B4snfPlAGApFskfGA@Hrev8^6jXd04kWoFTDQ3A+a6}4;OtCV* z_3;uMRm~|y`hn=kH5sQBaxeAnJVf}}tY zEtl7$vY3grIxS@j4gFdbD~*Fl58af45;gaoK$a`(6GKmAJn^i=rV7u?9$PY7nDX`Q zK$&irY0N@NZ5GkbLt^`QaZG$me*L5*OoVO)9cI{J2g>~xF(Y) z;|k~k@eK^-)P;$nVu3$JYr+BgwJpw%bX>2dtfwb1Ba-+*FO3&Z?(!qe=o?- zU2JAu_FAnP^jg|N%x~HsF3(=4wPfw=n84JtsfUNH#Sf- zHh3w8IVvB22N=QjKS*iI!YG$y8R}0F4tRDaO#02A$47)yzpO(YU1CA#)t2X$w#LgG z)gOGMb4A`#gJqFvaHcfdLepnJ>&=d@tyy?ehi8?}?xQK<&L*_LO}r}sDri4tKV65d zq${Wr6lj!%3ul4Kzj9sqcB~rNiF@ET5}GT-Y92q$tn}w!RXYaR>NXztns*u8T(01Y zI&guNb0NiRy~4&}Bo4uws}124FFSDWO<%`FS$Gpw0$~MHv3a+pT(u1~tP>>qu#vP4 zUQj?8diEMzmdicxR&~)qGLys0FtniCxa^sfwiwl|WRJLkL=mDl;SjEXC+iDK?APwP zaM5@H`-gYsrQh5c)R&SPs+6USB!8f{e4hI=U!QIlTk;|u!^C2nO6V-(+x-{fn25!n>qRhD(#Mtw$b0!U5z{7{>>9{chc z_RyWU3LHGaE8)nbh_(y>YEm3)(lXLjznm@k)qi1$7hySHKG=$_Vc@fp1O;HK15(K*zOxH{0E!HAeRu=v6rG zescOmg1y_{%3GcM>>eO&Ofn7UctFLD$fXM)H95cwZY@F(iV#F~il$&}PiXSdh(P9J z6TO7W04}DABGJCC(90ZzMbo1V5BbMl63&>Fi$##Jf!x@?2X!Sm-}FUvB<$2QTZr7t zV?&nq9t!F4?8lA){Q8U1J4pr4IYtrH$($~394Iu6DL+=UK+JrEJw0L4rYv_cw1G}5 z4_;7Iq=sxBDC}zc)*Rh{)Y0jrC~0^beuW{EX8B5uyMw?!5d8L>I*{nMQY;7gNx66` z8|RT+EI^s`HiVx0K3*@ORfe<#NO+bT=7Ps!ik!IgQXmIy(De!y->&8R57P(8GT9TC z>XIdwCT+WtIhl}}t9(;>jt&p)i=m6y;D|7tDs&^dyA%H88p295!$2;IvuwE&&8S zr_$3=a=DHq%>x&9c;zi_w0yF5u6bd;CCE@ilN{M1Jnr|07Lx85b@Wf7+KdCD@8*h4 zaweE2t#%}bg^ijpcOye>l3dy=dmAjeXJ3t5YPkrzN2;9jx??pTjejVI49iFZ>30=y z0kZJDXbrFn*J;~O2I4pGaceR4zrVr|C#>-wEEW8$21POiI+I%u@?LIJ>Dov^5|Dzo$P0}Gj9132Lx&irP{_p1y)u1!zktWhV zw42K`=!aP`{^Ov2Qum$@Q@Cp3bGpR}?6)FD>OcrV(;=biCfU(bA|^mNf(W^xOtZ8tRYeMe6@Ut7cWuNHVXed19dP zn#J?v4tx7JX8Nso%( zrtWVDy=1bAPcE%YlEF-t+EMo%^|;F@WnX$Cz&V*~KCZ8D{?_1OWE;wsiU;6>|E*A~ z;boYCr{~auHE?T}n(K75I@~8yXjQ*89Br+K66 zuDz7py3_I|(B_2F1pv-c4szOI2LMKW(*YFX3`hgb+<*Gs56f874t!Q(FgROG%0<4Q zGMD_c;v3_q_pbH*hodvz6fYZUrIC*?UfaqhLdr<%sn=0uGhlLk<-Vn_#Z&bK5;bOD z1e?oMotr_~LQ0tLxPv>gV8&Ao#_OFzZT@L~SketepaKAy5WH(){=; zkzGn)khizvxpn2Zu;=imb*^3YC3oz6aF16E8E9BN=KZlMLkLWWT%+(Tz%&vN8!@!5S-yRQcqgBP)$O_r?zs74P36!K5(>*oWGMQ22<%pj z;HiS}a=YH06}6V_+`;IcU;sPM2fr$G6PIeypcVB)5}30FwC^Hd+f_vIUJh`3;$yxF z^s&IN;t#0rz%gTPiB7OPaIu5CDPB9X$12o~U931zc{B-xp5+!F9TvAS*cN}c6&@o+ zTqn9a9^+m;mCV%bp1t%n*O+=QF_(gFlXBo)7h3`K2>0=}65@130m>R|wnvgv+Kl0Y z##)GDFX^rb1>isk2G`bo@K@HK&aUyl*n97Is{8+cTwO^SNfIR#A{{dsnJIf#>fn%B zICdf1DI-Gmo@IuPk%R1zRYrF9-g}R5zR%a8uIjqppU>y}yM2EDegC;`UC!(Ed_Biw zKkkpmlc44Hpo-{D0=9I4blD2}=Pq*@RwZula};)+2-W&Py}2Xg(P_SATL4UbQ@KEk zS|K+VS(Ux~F1mQ>Id(5*&mFa}=BS*%BI%rAsS28Rm;(3_4bS}JD#r~v@a?#TfV68v z8t0hNA2ero@=*>#(bGytye?5)v`V3<>)5M_n-yGxmp+}66xnPVkRiP0%$J%r*{8jp zfss!z(0QC#XALT&K&zA+9+>z$rrcq&JMqHEh_~UHDipMO_mL8jtceoj=={|b3R5KG zQbeZHqot6AFwi~Z@%bv#@dfq=s+xEp<@Od7Jk};|)Kp<(ti97j3)S-JGx9EdFL|op zA=PwaK){y1J1F#}*OvYLAuc%2DMmL&dqekQZyqvAbD<|A>~p|BK&L5y$L{QrqXehU z1Pa7JDow#S3PTUDqt*LwhNe&yz%5QzgUGECb{<4w$hU*T%S(7(DeFYEyNRoUc+t#!h$edxZqzw|T#s6q{J@H6(@0y(qV z$Lj9d|JX&K8FCV$uq@Bnx%f+Z3Ni{{*dd3S&c%CaA>C7&4@ zYwY)sq5|a~8P%QX0IdqTV&WDJq(sKdV-nHP)hhqTBTIfqrXn-q@85lFJy1D=ot&#= z@bE}nm{V)%Hz8^93IG+n>B}?i{w*)gvV+g#4()EIrqcsIV`lwbdH**#CZWj`!ezKd zrQ6!r7p=DwHv1iAn(%@^(~{;CijlA;&Xg;TX^%||+`9?!s+rMvh2pk0Gar~9b|59F zmXEZ?(tB#8#L|;oApFv52YVlxfNVIxa<>8S%d-H$ z1HV3P;F5KVOKT(V0oOIZ_}w#jfMf6qKRJShfw-Gz?`sVGchiAeXI@LycM5~9Sv~;1 z^~=wTn8T7@TZP~qZAQR7m&S|KYwn{Z@9Q?PFtb^MI!D}}lQK%S3u!wQfn)L?W(QzS zuYfd$l$TYiai;Up8ta+fHwi-(AtOZwPP48!PS*C&EsZr7MQ;v@q9(c)b47sw&W_>3 zPJ5JLM>nuWD^)3F%j0Fc6~e9jcYi1ou7SSBuE#R4Z=i>j;OUh$MhZ#1GJ|Hhf&4J!*Cq-cgJSK`fOh#cQrM8nH>UHrZs#37-%}2FiZVwx< zdO#y!w-%V}q-=z%#y@Aep|{G;@SHan6pUSC{y-+X+SEHXl$pGI2nh#9%dsC?tK$b!qZBUI&7bKfX4UvF8F zCi_iIezfY5HkR9=+wRDCkZX)e7br5C<1jAkSXufjRXL?}cEdqsPGF|0J3TD}^pL^> zp^ZZq$`e5G1Jh_SMXGW9ml7oToBn$5RW@M7fM$agz;_X&eQa%t(v?^~%2&p-HnhB` z(iOtmFPOL0C+KP^+0ocaoK7uL;R^CmUHzZDZriMX(#~_|`ogPVV-_To$`}AwMR#03 z3Xpr@RG??k5x*9%*@z3faW3AOCdJo41y06OoyPSALs0OS?O}5}g;~M;@c6|oeQ{F_ zkyuJWa>mjY@#Uj+jPW+R-77Y3e2qmUmY}r38i-=X4?CTvTh>*LQ{SGfE1@>%O5)(A zUAiKrrjxy1qcpDfuX*%d)u;@*&&zdo9R4xzOO55seO_~CW23n1=hT_FpVka&nxkbK z(43&32c9Wd+J*A5GPBfljYJAx2J|z45^=z9CDa=>Hef0%zh>QE>BxKx4?_$sD-2thl<_10&JWrlSG-83xKHTfH(++GaZkE2=PlIHRNe=3_=d~$ zTg_Z{>iyxf?jf@6jGUC!uPQ$_gsRR!$Og~-s`JD5S1d!hl1Fzu)G4bqnYeN~gBnC5-A`VzV4tway`8U!x};-Cz9# zIR0mLKqW|9Y-Oqk8yh0X;z$C*&vFHnGdM1fezq~2QAj<;q_(5qy2A0!q>$*uzrVMP z(d8V9N8PM>YwQzYe<55lAX@41))<3dl*a&Sayz+akiCWQ7+5`Cy*JpU!$@~gFMx99 z7BfScj@8Umtccm?Yb*vu8|&AX&$qqYONh89^cYNb!i=<$upH`_1mWnzLEn~VM_LF` z4_myHVl}Q?3fV>7pMi&CHT=WX0~$Cq)v`Do6!f1;3ZSz@Ys6`g_-=MJiHwd8{I$Gd4qOgk zcxk^JxsLa`9iqs^PPFJ})kisHF8cG4kxh=;rzQdyV=jzb1k~g^f%gm!9q~u4{5^nZ zy~h-8u+$}7-bGhuccvBs_~AK1eEb|!LARDdF%;}IXQ{s^kwOJX3J-4+q915yBBf!R z5If-wa)bXKPo&tpfVMb~#AkghM1Y4m2kpUL;hKj75`W?)BS^pezKqkduwkur9e8xf z;$X=oGqGhNDOFc)cg*2X{@B0p5TJ48jl-zEZM|7@PBvk2=|l?0G9(z&&DvK~!Te^B zt?^$s$bM|rQv}%&Lb^ujlia#mpZyD zdu(upgY~?|0GUS4Re^=dcip8cyAoxdQWwLtM3z6;ZSHzxm>0?@0KYA(amiq)H(kM8 zf;&SIJ%J{{lK|#`^ab={%?G4}MRIjhnbVZV_|mJ)0cXzW&BeMPn1TGplLaB)1+60E zkxahQ<<-3OluUh~suX0z>af>&tAOW7J2u(oIle4NImyHZDROWk)9e{zG1o;L5PUQj|NTvmtF$ z?5YkBTXmP%c7Qdq&vKEV3xnYy=wM>wltQsU(^I@=nxnH(A3LT%2|2WQm!UoeLOj>d zZ*M-gzHFbv{nRmiCsWpx88Dn&G6kiQ{G4D|VbyzuR*rtut@YTTM2ex2Oke=F-P;k{ z4xQzHzY;)goDRA#989Gk6z-;crEmaQxOv+=(7n@08m5|}f22AnK|mxJwR>VTV*t+?SDM>(2Oata0Cz4QAyL!1zf7XvLLO?q~aRUv%qnK3*=etpL-Y_{|5u|>d%mp$91w47$C?QHBu z{jOWWwnIOe^(vhybu?JWOpZO)>cwfLnlo2l!QCaLxtsn*J-j=sh~N=a@B~K18%*s; zq;PMf&mJ9?xtvHr0`jRkJ>v?n3Oe$9&zoMG?!sRtw%>fTLB-jG2{V|a0+om-54A}Yx-W!2)=?(3s%Bg8eV4{gi#77|Y4+&S z`3O?`GDQA$RY6N#2B11s{N-1P&Da-Z5X~1}VJaR~wR)|xP^WT>EdwBx8g0aVUIrb; zY?IbXIRmBfWQyGt{wI9;v24IH#S_HM{pNu7Ip0y#-rOGE-b^KdbI#M6+QHXhW;>$U znJmJlPgmKM;-wKf?Jt#jcb4z9cpU|)Ui8<93nj|Dfh?7^m|?CUn=sH4z@EYf=<(Dw zmStZ3Z)d>XJfnfA`d&7MUL;VdUw>p~!c}f4mApCPw0`?~12t;TcWcPA=-n|FpFy>Z zJ~I)15re$*y>>k&78`5?aVVXk!EN6?p55c8D`Twy>%|cT=D&=sGTB+_%rEOeVM4M~ z>6J;3u*g3Vk(kH_nqy_cudUcsNC~!wol3#(-M3u8@-Mq$uP*61?sk)7Ep|F%hz5F> z&9MW8>RzI(NQri@jQ3rFGzrWGeO@M){Y$)=3c`mup|M+Sz-H*;tHDPHa|p^qJQAF1mh9%mJwxvePtm1fan zh4QAW8u6_#f9XpXs59s0ADxW&^k!u+HG+nqZ1=Ot##XW{H^hd-S0iUbW(`+2SQ8qALVE#dKEBOit|)E}pO>9E$6 zRjdAJWxezLgkgOYTztZ;{(B-r;}Mx83ejt#*HJx0V!TUhLu|~hYdjh6%_MFLpeK(W zVG6x)q^xkI1aO$`c+;W;W`N8KyIfs7p;p*&jnnNW`a}0dXmFd^`+v`G~ENA)@&mQ|PNng-_p> z*n)PP{q?Vhz!Sr=J*&t&se3TG4Rm*H&I;rYZ(pS5e2m~Su{+V!>eZWia!j)opjz;# zpqAJ|5(qMKr?Wxn7rt@$$<-bCgRtTRU3O(wwK$? zQ7h_Ydwn3yxaw;06DjU9pbhQ8I`P3`KPm?$Q^W}sJQ*LE6NIeg`Fd|HbD_;S z6@9_{f;stxV$z(nl^$S9HKlymSq`Xas4RbQTQwLiUrakx%s>ymeXWI%vI9-E1e^-I zXMoVam=djCn-Le3Ni_(YHow`LZn&52`LQuKkjC}vKLI>YLr$rvWrMSkPOm3~G<7Tj z$Y%lQfcuRXZ2d<=9Bs-Y$mApWV~ZQotYP&i_S)Fvr{2jtp3J%5Ozdsf>XqGiS&Y&W zb`JFVsLTUa^ubQ4q17SNy~&YN5>ejkwbY(tCeeDo(0l1&k~Hk6^|TlaKs3Ox6VT$>$TpKJb>WaspVx6pth-Z)BJIq3wJ{dU~-?tf*k*`R~Q#-ST8X6@bJN^o~5KI!YWuO`WCJ|aD2;G zcUTW}$U6x-<@P`>$v)NJcS0P3{V){3_TwesUX+HN?~KF@e?jf0#D&+8I%^?G?n5g5 zSGM!QR6O2)vl}F&fhn_aHA=G>`$A@ZXH3vf#A!L9(OsQRWM#zR43DxP*n-p0#Bc;1 zgsf6M1a_sGPZF`zpWUE7F#n)G%VGSbsC+csajnI&$hk;IziD}p%a0>EmUB4^@<8^N z1ZFk?3dT`;6HeIO-T9;<=hcM)_00o$zlq%K$SE@OHrsjBxQ5zlm{2O~+RdJF_LTr+ zJ61?hmr5>HYN6enSCEoiDB3tDtRJgtt6zZ&8YuIvCEq&|#9I1od0Nk=Q`rpk>->Ap z(cH+Yi89-9^U|IEGSot5#Q=Vt`_`Ssk$aV`B#)BF(rHEab;6d%``o3 znD`f_Fn_q?R%3!FPivhrZ#=aX`@5Ku^BV1f=mct0N27RSd5bTCp^dRZxlFZ!fh#Nm ze6c*D-?nOBt+i20{krH*kOd0AMYc6wGSje7dOh5LjP$BY-RZKTjkvNc{fWpjZqY9# zr7;GcpsRM4=}OA~T}UO?egqO;IOG2`(tSiDLOnnL25upFRGWBUh!-~mk{H(~xlaX& zRG8>?*RM0d-3oJ{RA?7v&zBr!k=M`*^2|logfV96% z8CO6)VmJ%=>o<(s>@-VAbN%7OKni>)Hp3sJ9_Lm}et~>p0iv*YuX%zcmDxex2`(tC z1OiH+nMVcapMv-7=`oMH=l)7Fl(oo#-UiXC*Fc~LT|_TJAAC&%cH$dxiixjO=={xJ3!)eW3bzVq(5~ zb9*b5fSpFG$?Gc|=2&jgudVIp=< z#_AvE49~g~EGX>h?f}H`tq>ECrz(U=a*5pgB0num<_5rUm0Dk%LL-#v${NZrcXouXX4E~|%HhWEMDN7*S z?X0+A`+7`~Xb;`4VWF7o%f8oofT^2qmAu#13TH7X%v(K6E=~os+eSS>$$*F2t#GFB za@Qlw#;X;cRq5j*f^;HnVwPIAHN_5V8N_tO)bgvAp$+2^5hEqkY$B_lTYJpTw(zwO zmO&aVn%Cq=d$rhJ){0uUs<#4p1<_ux4-o!tn2K8~$rMBMC+aB92a?l2sovQ_R_&06 z9HX%xazAc9;1oLQR3=jV2)kZjmaJXDNpBmSG?Yf3I;X}DOq}=z)m86kHZ4`dGe-|L zR#6$0BAcRmjL+s9#dXdup56Zleyi8w6H!)aapEO6;I(lLzp+P3U~4w#9181hE^n(M z0tgvs3q?d-J%>Zu>4M<6Ko?%hmOp&c6;ol5NI}*@NJ@dor*{^R$TDz zVDsn9usbr$^tVZdvmUPO26gP3NqDyIq=-S4)=} zG`8pqKp&#Zkf$;DmR>Jq{e(?V(b)Q>Ab49sJF==55=#*{FW+osKPZvfmF1w{^kijU z6>7xpX#I}SMVCBkl8Ph0-&qwO2(4=u&OTuLf6J!HhoFB4gJ1)^V*>}}b8hv8c zurj-DsxR2oQjj$^oqPkB}! zdRiKipURumTf^96!@F%VC@)8sjZCI#nF*t6BIv>&D8=m78iKk|bD%iJ;L5f*jiUV*cEw^L?gy^MYX-ALGN|R+-UqM+o|g z8SFnCghVbzm+KTRNnuxmK1r@p)=EFPz9T~fw(!@{eT@@XDUI$8Th3WOnRB{khG=d$ zQ9n&G-kWs4m1A$LH$e&eWa^yd^xWn(kDKLUR5GkRtBWmNK?Q&rgnToX8|mswu9mWc z=BQo(%uam3Q;kzQ_xa`@AT~OEni!r!v+n`70(>GMC&l-fVn<}x`UJp7W4Hr_$Qg4* zB+Sz!hUW`Z0^z{>@T&8N+d@&?9$H2%NiFOe zK~@Rx^69Acp%2`o$x(SR1EPShvyR`jb+gTZ0=mBr5C^ZN2g|mEF;(^wHbLSAaSIuo zevc?O0buElA>BOyg!L9;=sHe|Tz>T=#OTdazFg-%LU17)El9HeSQq-uwa@p{+`Ie4 z5kstizkkso9kBy|F=o2OYEY0H@5i9?Of7^40pOsr~!1`$n}9%~o>fE7U*o{i2G2 z3NMh&y)EdaZ6@JX@ULfc2RNsYmiV`~04@!XmnTLSWF=xD(*yIO<+4iZ86%q@SBQYz z{(W^n=BXRf^>Rsn>4z}^&7>&Gs>KUtK0EM;w*-ifpx&)7HndLLqf#+M`67XNPWduaz&QL1Y?&CVxN16wN0jo{&lFBVY00ALI4MdQX12YLidc{epeG4?%K z-)l>qx!JM7w0PtL*i>3 z(41&WFpg_LPi0#K*(jMx=Q=Z-(cEH1U73!Z6czHIZn#7*YM_Lh-{9fgtb&vS`Q?@+ zaoZ^2FX`#oz;frO-^-Y&B_`Ns&na^j!2Ep*jVb@P_Iu-1kYECd6ew|nTW2V=&c0Dc zM040NvSFA4qq)C4y*==IP*S!d#XX$)haq1QWF>LrFmM+~Us;-uR>t#_*CP_LA6?b6 zA)a6BNNejQtSqGXXwe1k7B=|sVqeCfq*(yhUyj#C=*T& z*l81VXB5V|EF3xX0_0!5LzW!+&8kN*j_LnMW*UMMKF2r9U%zx#5ekn2;?%l>qp|Z^ z`MN7@+sOjlz=8)UiRaY;@YfUvgQ-A+%`?@s62^hQ0-x3p|A5XYAUZoBUc-(_K0yz| z51_R)BpOjSanr`}`g48o9^1ia%==Tr$s@zt0Suf{NPZ|y3cVxx%R3-={aWJSosA&e z3_2jmhYz9>&(9o8e?Vz}`tqzlGH=g{$k=f|Mu6YdTXy$B=GM!Mu=+qS*|0tD|FkiHq0 z!8t(r;M*+y8ox73Un19xAnpAR1@1R`mKt4vfrUE-$`IVN!PpXu|D(V9dOg&-Qf&LI zWhw9XL43Wyym&7b26ZvIs30z+$m1$%Ftj)p=2Kr)xT#c>Jpoq9kYZ&*IL zAw$3NpOcM*{F((0evq)mZTlT)+ksvIk(fXKiuYCXPr35f4Ts0_FMeC&3B0)~uCt9$ zz6+wMd$>bU%|CpDthj6t5=!MM_gbUCb=F^*t}-|RR)oGBcbDf)(|WM|TO17)P~5N% z)(n!(y#bsjJdq@$n{jh2Yqx>uBp9Sl8VSG4b`rQv&y-RlzZy8m3f}`PcW6^`ia+@t z(I>DsgUV@4t6i~oNg>UOS9(Xlm!rL7T18XS702D{Oe#XUQ4ubn0R1o z_$sI2>jJ5>$a0^2+e9hV1JW_wzL@yC|GU2xMXBb4NpY~CZC5_#Y?O3hb*7)o)u?b} z+ZW?-8@=!N9frys1Vtb4JN0n`Ox5+h5v~200~&%2cw}&7KL^nhe#O)?or=z=*i0gv>(Ike&SXY@pDmthdNGMl z;xrVJ?ch#+E$_Ueb6>$Xc@hxn0MP?h0vY*WPo<(`w2OJ%5Il#7cGNv2nbOoMW5CK3 zY1H$+=VV!O@OmKpgTgiqa!NFU)nAH zvNB%lVXGG<{6w5O8FuM=rvRy;ZnnhqAr6DMM{70BFW9)W=tLHyatHYQ4CoSl$R$BI zE9D;o3ki_JpYPfs0zO~RMOJCcN>I_s2g5ZGJB=W`b1CoQhgZkv1;Y)Ro&5J6G)6}3 zDX-3xF`bJb$QF%o$5dGVL(YbRXxD32HU(JxS#nWsX3NgTS&_zJP&>I2^@_VDsE3;s z{Z{u7=z8Al*J{Nw-{R1v4do=Lcz#khiEf|Qse+wIlifm!%2u!Psf$bt(E%YV==Tw- z=JYwk`Ww9ZMoU}QEpcF{Qx0w*2c2Fdhq#wz!i=mE@~h0B7!PpVA2xcA=>89}4P_zd z!?c3fWMM5J0j}PDH3lxeG1U;Vxou(dpkA7P>EcrtNmPgeIjCK^SU>tXW|!sEZjFyw zgu>ln(h%&0j=B5ip91W@!tx{6$3V(kY;)YZbf7Gdx4|{u%hh|iIblVV2N4BVIUE>c zuAhW=Hr8&KwAs|BU~Pz7wAA3vuy4tXU&i)WN3^m0YF13q?0!hUB1#r9w4B#2tm~uX z{dPf(n&J8^sJD(B{c>~!D8<25t+%p2s62SI5VAO93R&do1j05VYt~t@(@7IgX;d+$ z^Qo!xY~$;++)AuM53W5gVD#7Xjl_*!atrtJN!Ac_!gYbB3Ryn$74r zbCBeheez8PafhcajHDWv0nhFz|KzD)dBoDtvNLD%8pt{9wYd%5WDK~vx^VXznlma- zqi=0K26zHWq42Dlm@3cgyMdM9gwte7O*jFn3(qI=hZYV^PAnyVXtuCjnNpbIFsnwp zb6z3FbAUPaYO#&U%949)%ol)T0P&SrUeFA_(55)gX18jgc>5clG%S%*_g(O4RuCrM zD3F8N2U7hB$v?DslGychlNUty-Q?~){L9^z6Tly=tYoFj3n+9j%>`dcIf8-F7tviv z5gTy+X<-!n6DZ$Pzmi+Xk;~S0w(6hjeSLA@_^H_8#}ifMvS*x@zFv&9Qy*| zH$v6cs?-xH)-IwAdFpgh5|9!*f?5d01FFz&yZ1wMUNiKEYuM>w%X*8s1qc$OSi_ss zO^)Vp*5_q|TpX)y_JYPWo&+G=0U8j^bbZzeAfN@P0iZay&b$XCy-W3*IpSv-))fkO zx6TdeDY9wuY;@TL?TGZ<6?nJ#zWf7_)SN~??UKkqjeN*Og1ow+u|1WbrxRkc0*lB6 zrij*Cg=IXIrJ2{98kSU@$n0OD;_m>CcLJ%=Wyn0_1bB@Q8*x`r%QHgVmmG( zC{=@jdCF7Y=-nQ_7h8q6-k0(TElwQ-ncL~Gc$i9Pr%nqYFqb%eBBu`wEO4~&F01oM z_b=h5Yd($5if4X^!;?59>rt+c&DZeMspnxa%S_v;5(C)LgV_zTP zgog}lHOp7uf$LA|{_P2WIEIp;T2|(SAm|6dw6%Zszkcq@ufQ)JQEsHfe>I|eiQ-EoRY`h*1jCL4e53r{r11jydOUt9&O| z`V^^&XfEK~XmgqGs|?n`Nt*iUgiI0ryGV(XcQw479c)%dwMtheTbV@*ang8VBawoN zdVh1}fCI>0^}v2#zWjXxV<5<0^NDR=j(`8Y^eK4i(z&prvu-c@oD6~PygIKa4C=E$ zi-|idpcgx>N2ez3ffT)A^kc(f6Dg)1vFa{;BB|y@Z_Y0$+gwC{bfe;e|1Ng_eqk9Y zfok^JyXJK}6L(Pg{rAU4RreMY#RoT~SI-0B*LQ%;^uQF&E5%vMqxt_j_zg z%cl8W5=cnPJ3DXfmM*k@ky0XdDomzPLk4=ryNqif+Tel_oyS=Jyk0H>ZlDV{?m zfL%|~E4CZNbS({*xDwP0Nn4C`nu~smYUZpZI%SYxggbUbkaQScoO#tObD81&%U+Cb zzllo$MS(;+$ZFnvJ4#e7Uc}-o()?FGU11)3cBt%z!^4V!40WA7%kse^arIMjVU~(a zg-?sN1~;R-o>)wn=9G_^TsO>htos%NGTlHFQ=xy*cp!Z8BHE(Yldq4_z(q)}Fo)4) zwVYA%aW-~Xar`h2=2bpT8pAazvr;+#EGx|ZAuS`tSs%@O`cVEOdW~@?K?4B$&Pm9> zU)S@g@noHo5m4Undt-o7?gy;A;gqicr3Oc*T*qHpwEq8_Tg89dSAvEjyt9NsaLku&bo+ zfFxA&d5?ZGFBE~oI%7ib%j-kFC%CQJ^#eC=2>B^9vcO{D zN49gAUw}flR@93a`BBhb)ePICSV{^k`BgtF-`7w)rnZ+*xE^g7GbxJvq5$ikZL;EA z;^8s1?!2(M(vW-f4CS`Lpog}&CX7qRjn=qLGyu8)muC5+g(>3Stn{rPENxWERq)8r1Uxxvi- zeG_wE%$!+6tCMwVjXtUEydkN@TkvhKo~Tp$hf-#V*)f1F%id*(VZe#kebO8FFmU|I z)>x|nT=>J>^b~W0D+envQ&ZGlr(HN1`G_S`Q%z~dwI*${hO6*gt5-iv+^Cj1)EQvZ zd=+iE?gAM#z$^jxL4>{9>!`fQP@PFix7pB5lg>fIZ~D}2=Co!}-_BAVU3IB|junEe zEV)cXH`X@vP6gkKLdhRyy~5O}DABKH?vJ@i3M_?3Qa;%WYm;5?cc1&A%$)P4x?2|I zWXQFOPHGWy38XL}x-H6;;Em@==^hzXomqK4DEKB)N+A}{BvfIm}1ledWW_B9e_1yL*0_GP-M32gd4;wQni%G73 zhw#qq^@7`!AmncK7sc;>#7?{VzG+R7M4=EiCfMQ?`k97{=?q#mLhTj(j#tg3H?6{~ zl^+1=aV8CqSX0to)0xh`${i8Ep6T_j_&_cF@JfD;R*(J)%01R){iwbV3~*(cfqSn} zY=mU&WsalF<2~gsF9JY(Ig%+8-ER_m{HnJ@PKq;Uemsfn4_o2i56Wx(^LOl=Qml}+ z=C{XAAHM2y_(<3Lgz#W1U~|M9D7aFr}S&^!Vx6E7(y$v}K*4iIbuF2y^H87i*d6wL1VG8)};+E{d&OfQMiBL+YjgATm$&Gh{J;A)gSETcFZ1rj*( zRhI;PXB|hYcX|$d;K`fQ+qzM!P{MwD?nQ*~mj;I#UOFxQ2b;d8;y}^+P{A(!Ahl$x zQ1^c+I{3crLeiQnBRaFIEqWn#CMU6gKW0$@YG zPcc|=F9%==p6vxRlHm+(0^d|OQ3NTdolhTw8n}7=q{Ny)PImF|oPi>`^0QG$) z&3572INF>bqKX{l8Jazb$bmuw0GK)XS=Bkf-XA{|Q!$+wcn07VIsRe7|0D_%3o{9M z8+cWOyTSXi7|^>~s8*#O{nn?&p&b9$)A)TN-&BDizQe({K+NFUzXr+;0SZ7N19g`5 zCJ07221@L_d5@Hscg-@Bcof`E#IF5G6*!FtMru+JmKEGk`WlsJc?2?ND#yp+#PF}@ zSv}5vS5(e1Q4Z&D`=Wj%-6Yn&2<251X*wkC1MVpjBx2aT0Km`p|N8+EtzP2?0LXnv z8gx_aZywV>j_VDWoXHg_6s-ri_iJ7E*ZJa%>b+_7eyGX3h0yPBf9-dd0uQy;feYi} zgt^x`C>()sfPaK#FCwcpHAGVZu(1R{vm|igNk@jVg8NeYzV!G?^Sq zzum&WQ}JA)XPcBKeiP81ZQ6Ie)xzgzUtAF3r&P48EfX`}zD1wsDcb5^K#`54sjE?niF=|y6!A?j z8Q|UxOaKfoja;FV@5mW5u!unTN09Tx+jQIy*i?>BfTAaHVw#-|Zuf^z{q4SO#-FN; zyA}W^M(uzurj{_bej1Hwnb9+*$c7qvV${Gi1>hpRB0w=17COuv4RlRqpZ~ zquqD2?fIzQeMZ`Y(CP#7Xy+$L9RPYN@QV{_NZjxQOzG0%a0ry5THNj#aIMTMo3jS% zLH)KKG}7IzKiXUPi}DI&3#emS~-vpjWaqCh?r`7JPAAbvBFu;bX%{h^t=~`ZgPf%|O|MuuB zaBreHr<224^I@$FGVD$NMM1$dV+9kUJ}otF02NANKwH2a23!*>~F2O=@cVFZ4 zM#7`{=pw$o^D^5$8QV+Nw~RwetEQFU#83r3N(p}t~YtQX7 z{t=DFK5mMkY;CdyXp8Uin})lloT;E;3Zn}6rZ_(KuilfY*AkO(XAa#KEaJa^=2@Y? z)tg_p9`mK~RxE9g%kx(as#pz6n#4b;zp(8+0F=A=Lne{LQ~s+Ay>?u-(}wQe7INF7 z`sM>MsR05imtx?I@Bu3_B)%+wMt$HdC8+5e=k1uJ-f{w{`M;0-RVKh-;h)p6rs)ql;9!YMV;@g-q7B3IV(3~w5mX@<)H^s zQh#f&>Q*o6!WsD9a*@wilW;Lo*2XqXNpf9K*o5aLZ-(sX4`oX(jzuJYyMY5%r zZaU4@Op$24QxG1}7HjB_V0x#{6$n13rUyg{F-z3zRoZ)LRea0e0crhhv;YjSeE3zz z?2+2W_A=SHNiq$>Aosmf;R&E{@LWW>!092G%ixCR!vWv?_{K9+3)W1@W7D4?LAd*B zBs6#;#k{gT=^x4KN}w+5?(Hfh;X6{qWDI|-hHA8v!nGeCx}|+bFlpoUA6a!PQFJ&_ zXQzoR`z>IIk4ix$%%Cp(1`Cs_#zz30SDX?C+4|q|?R`oxC|7XL>-uTMJJ1A%!IAu? zYWBGmz_?Q`mk@*)Exp<)1tE{0yL@Y(+krM!4(@lA%>@c?;8*do?>#~KkVSSu?2mLG z&PzEQ0>qP7ivs`){FYM0d2u(Aq+!wV(3bz6ApPNr5Z(hI(EXAB)YM?SIAasSlC_in zX>K5=E7JMxwEYYy*ZmKxOF}qiWV5Vx0Jzxx{``qbfPNO)2whXV9shDb>Yqz|d(XRx zhqr2?|E@!;`kTt+IN9$v|5zy4bjw!?O9lCD{j2cF3+S)u{~#~0?*-M#o4x8r=Jqfv zfB57-&k1b3hMuzHJXXh*MrBE7Zws1`{IZH@)N0;_-oA!qDvk!FKSF_@A=K!36T== zRaVd5d|VX%^O+vt8UMmG1yRHJ2JF3q#KlVuGG zpj+G7n8r29Zt7Ciq6H1d+kHG#Jv zz9#R}_fBs>4+b2pCfqs-iy2W*;!U+nq+kPCn%9oY2~7Ke>3eC9RG$yw&s~igmPG`d z^8}amZ2yJeR=su6G1@}42eq?_8r)b-p^7G&-{jL0?xxGGQBs{WZ{f``U-Y^Dh0jgb zb$YM*p-adMm9AN{Tl{T&J>$RE0_Xx_c%L0KN0i@s(5%I}ukEie-%QQGk~v1C#O5Zf zQPXy@f75mK0P_>~E(7XSV?W6qB}Ij)1(>DcJwDL5Og3OquJHG4eX6(z!o`!mVa_ z()q$I!{F{ICOZe!1f!mIHqSkvF3-oxkf*PdHWQLtBFhy2jB{<|l<%TFDTus$;`NO~#H=tW(0 zmcMH7#nP-tmB4Xor%r!#+oAbmZBeyi9!Ga1{1cX3B-)hhm9+}$yhb>p*l0dyg^8Dv z!7@w^N;%|C%D~Te@72r|L`bg}_}Fnj9avdHI^id+OM{W0RGw7RF$?6De`*w;91xB? z@s&DTsz7F0pJ^f3W6vo8Nt4g6wmvmhEM`3`9%7gSLTlSS(S`_p#OLBxbw}gbhu`Bv zkPX8k#H*Ma=};$+zZhJfaiVLZ zANi|2;%*UrG&qaeU2|HAjXlYp>tC2$b`}&2Q1xLqr)c|Ng~A%3=aYkT&f{@V_*_*h z7&?GEI&xZ`>+T0fms@@5E}Uy>PZK@954rveN(D5aB$B^ryR3CID;sx5)! z`@p8fDzz5X)k6JI4Zr?%kc#6j#CCnXD5Uf7Z@ksjQ3*&+yt*f)kZ}OJl}pReDGPj; z&$3^~c?^ty9jiopLhw6ZEohEOedOUnAit|#Rj4)Hc{9uV06-aq8FZQJPS z0~Iq0r^Md*(2^X?f7b}I9zgiN-_a%je&OfC4sD|+{&*N93dBIH^qA!@WB$uyf3HFU z(F_)Y_c=w_=n26A;P?dvmF8FWoS*xP4{Aa&prYZ~a-Cn~e)8^iYN!tW3rfrv6GB`? z?3H0t#2te=wz0;EW8aOzh46T?Orl0laM4r%VTPQA{nPTyN8)2uM9*2m5TH&4?{kf3 zJnaFd?JQi|_TrV+U1J0YME<#bTX%w>9GCsKGuWLatdTvr*LF`2R=qWf^Z34H0*ab} zV+>veCqi|o0|=4?5A@fJa@F0x67T+Vy*0`5W4tzOA|1E8`A z6h$2<{3EJB;rr3%f!I1pxO(%2ariwjYtT4rf75;rLeznN3$DxqG5#w6+yjCc`^wD+ zZw90~n=A7!{MSE&o>vEGm5t#*8sM})(X*JsSw4M5<+u`O8lH@IU+g^q{nhka zfhE*mVhM^OL7!$?kAM|`Df`zggG-ZCkFRHlI;J@k*2IpLH#N7t+;kddsoc-b^c6%4 zkU#8724+)KNwPx?s4CIgX-xNXa>eM**65510lowAybAyg1ck6J(=mLs2NHQTi|q-# ziv!nQOaqiFa`c)c9K7$PHNgWu*7&OIbj*l4w1%LmtVHs;#Il>C&E(wThRG^am zU*%9!F4^lV+a^u9w9BZ(!$Mm5@pF#zu1&dNKneo1);>#adZ$2qZVd1Uar3{!2j1mYZwzM{Kvb{L1%2CXFcN?4NU(f*?=o_$~`5+E$#Z9cjIdi?zew07F_J0E1nnw6-ZHqEN_Tao<* zs-Vw1Df5^OkdC^k~kyFy+=Bm!-`tTmr^%Sil#zG{Ad0 z_a4tw8aO*P#V7L#D+xetkv0m$Xo%p|HxX}`1x`QYs9h-l*SW)~L?w&U9KS*Cs+GuN z8mYLsf{x1U7OzZAd$Z2xN(YGHoKBB0hq96bH*LQO8i7h?*VDH1Czu7@j^8Y&UX6?2 z$kLfV*_SS=M^DT`KZS|k(1=P-X)v+HwL@zFEjP|Q%r71(`Bv;>+fP=;w3RsIl+#JP zP_Ip$OlTF0x#@>1b>*NzN)!{m^4b}y!^P1YeJlx`@+J_ZHK5m(io0in237AMwN6Kt zzW*^F2iJ0CsJ#Z1=M{W2vf)ZRj4(PUF+HD+sSv;TWm>C>KG0d@>W(j;RjfU(f!fs* z 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 literal 47708 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
^TPj5LY!hc7 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 BgPi~X diff --git a/include/cli/detail/genericasioremotecli.h b/include/cli/detail/genericasioremotecli.h index 5b07d06..f8f7760 100644 --- a/include/cli/detail/genericasioremotecli.h +++ b/include/cli/detail/genericasioremotecli.h @@ -476,11 +476,9 @@ class CliTelnetSession : public InputDevice, public TelnetSession, public CliSes switch( c ) { case static_cast(EOF): - [[fallthrough]]; case 4: // EOT Notify(std::make_pair(KeyType::eof,' ')); break; case 8: // Backspace - [[fallthrough]]; case 127: // Backspace or Delete Notify(std::make_pair(KeyType::backspace, ' ')); break; //case 10: Notify(std::make_pair(KeyType::ret,' ')); break; From 45d1c8b6f223f084d0c2ff3ba4fe9b377107b0a4 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 16:21:45 +0200 Subject: [PATCH 072/223] Add std:: to move(...) because clang wants std:: specified before move and forward! --- test/test_cli.cpp | 18 +++++++++--------- test/test_menu.cpp | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/test_cli.cpp b/test/test_cli.cpp index 7f16829..22cae5c 100644 --- a/test/test_cli.cpp +++ b/test/test_cli.cpp @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(Basics) rootMenu->Insert("int_cmd", [](ostream& out, int par){ out << par << "\n"; }, "int_cmd help", {"int_par"} ); rootMenu->Insert("string_cmd", [](ostream& out, const string& par){ out << par << "\n"; }, "string_cmd help", {"string_par"} ); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; @@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(parameters) rootMenu->Insert("long_double_cmd", [](ostream& out, long double par){ out << par << "\n"; }, "long_double_cmd help", {"long_double_par"} ); rootMenu->Insert("string_cmd", [](ostream& out, const string& par){ out << par << "\n"; }, "string_cmd help", {"string_par"} ); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; @@ -280,7 +280,7 @@ BOOST_AUTO_TEST_CASE(freeform) out << "\n"; }, "cmd_printer help", {""} ); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; UserInput(cli, oss, R"(cmd_printer_by_value a b 'c d e' f)"); @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(freeform) BOOST_AUTO_TEST_CASE(borderLine) { auto rootMenu = make_unique("cli"); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; @@ -323,10 +323,10 @@ BOOST_AUTO_TEST_CASE(Submenus) auto subSubMenu = make_unique("subsub"); subSubMenu->Insert("double_int_cmd", [](ostream& out, int par1, int par2){ out << par1 << par2 << "\n"; } ); subSubMenu->Insert("double_string_cmd", [](ostream& out, const string& par1, const string& par2){ out << par1 << par2 << "\n"; } ); - subMenu->Insert(move(subSubMenu)); - rootMenu->Insert(move(subMenu)); + subMenu->Insert(std::move(subSubMenu)); + rootMenu->Insert(std::move(subMenu)); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; @@ -399,7 +399,7 @@ BOOST_AUTO_TEST_CASE(ExitActions) rootMenu->Insert("int_cmd", [](ostream& out, int par){ out << par << "\n"; }, "int_cmd help", {"int_par"} ); rootMenu->Insert("string_cmd", [](ostream& out, const string& par){ out << par << "\n"; }, "string_cmd help", {"string_par"} ); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); bool exitActionDone = false; cli.ExitAction([&](std::ostream&) noexcept { exitActionDone=true; }); @@ -415,7 +415,7 @@ BOOST_AUTO_TEST_CASE(Exceptions) rootMenu->Insert("stdexception", [](ostream&){ throw std::logic_error("myerror"); } ); rootMenu->Insert("customexception", [](ostream&){ throw 42; } ); - Cli cli(move(rootMenu)); + Cli cli(std::move(rootMenu)); stringstream oss; diff --git a/test/test_menu.cpp b/test/test_menu.cpp index 0bfbcad..a47e76a 100644 --- a/test/test_menu.cpp +++ b/test/test_menu.cpp @@ -47,9 +47,9 @@ BOOST_AUTO_TEST_CASE(Basics) auto subMenu = make_unique("submenu"); auto subSubMenu = make_unique("subsubmenu"); subSubMenu->Insert("bar", [](ostream&){}); - subMenu->Insert(move(subSubMenu)); + subMenu->Insert(std::move(subSubMenu)); subMenu->Insert("foo", [](ostream&){}); - menu.Insert(move(subMenu)); + menu.Insert(std::move(subMenu)); /* menu From 651e6e3d3e220ede90ebea21694ef99b1f1bc44f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 16:24:23 +0200 Subject: [PATCH 073/223] close #244 (std::unique_ptr of forward-declared classes error on libc++ with c++23) --- include/cli/cli.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 1a85faf..6c18f22 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -136,13 +136,7 @@ namespace cli * * However, you can develop your own, just derive a class from @c HistoryStorage . */ - Cli(std::unique_ptr _rootMenu, std::unique_ptr historyStorage = std::make_unique()) : - globalHistoryStorage(std::move(historyStorage)), - rootMenu(std::move(_rootMenu)), - enterAction{}, - exitAction{} - { - } + Cli(std::unique_ptr _rootMenu, std::unique_ptr historyStorage = std::make_unique()); /** * @brief Add a global enter action that is called every time a session (local or remote) is established. @@ -314,7 +308,7 @@ namespace cli { public: CliSession(Cli& _cli, std::ostream& _out, std::size_t historySize = 100); - virtual ~CliSession() noexcept { coutPtr->UnRegister(out); } + virtual ~CliSession() noexcept; // disable value semantics CliSession(const CliSession&) = delete; @@ -863,6 +857,16 @@ namespace cli // ******************************************************************** + // Cli implementation + + inline Cli::Cli(std::unique_ptr _rootMenu, std::unique_ptr historyStorage) : + globalHistoryStorage{std::move(historyStorage)}, + rootMenu{std::move(_rootMenu)}, + enterAction{}, + exitAction{} + { + } + // CliSession implementation inline CliSession::CliSession(Cli& _cli, std::ostream& _out, std::size_t historySize) : @@ -960,6 +964,11 @@ namespace cli return v1; } + inline CliSession::~CliSession() noexcept + { + coutPtr->UnRegister(out); + } + // Menu implementation template From cb88d341c84146b138c718c8af001145020a02ae Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:17:59 +0200 Subject: [PATCH 074/223] New platforms and compilers in CI github actions --- .github/workflows/ccpp.yml | 84 +++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 5d151e6..56567d9 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -3,26 +3,90 @@ name: C/C++ CI of Cli on: [push,pull_request] jobs: - build: + Test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + + matrix: + os: + - ubuntu-20.04 + - ubuntu-latest + - macos-12 + compiler: + # you can specify the version after `-` like "llvm-13.0.0". + - llvm-13.0.0 + - gcc-11 + generator: + - "Ninja Multi-Config" + build_type: + - Release + - Debug + + exclude: + # mingw is determined by this author to be too buggy to support + - os: macos-12 + compiler: gcc-11 + - os: ubuntu-20.04 + compiler: llvm-13.0.0 + + include: + # Add appropriate variables for gcov version required. This will intentionally break + # if you try to use a compiler that does not have gcov set + - compiler: gcc-11 + gcov_executable: gcov + - compiler: llvm-13.0.0 + gcov_executable: "llvm-cov gcov" + + # Set up preferred package generators, for given build configurations + - build_type: Release + developer_mode: OFF + package_generator: TBZ2 + + - os: windows-2022 + compiler: msvc + generator: "Visual Studio 17 2022" + build_type: Debug + developer_mode: ON + - os: windows-2022 + compiler: msvc + generator: "Visual Studio 17 2022" + build_type: Release + developer_mode: ON + - os: windows-2022 + compiler: msvc + generator: "Visual Studio 17 2022" + build_type: Debug + developer_mode: OFF + - os: windows-2022 + compiler: msvc + generator: "Visual Studio 17 2022" + build_type: Release + developer_mode: OFF + package_generator: ZIP + + - runs-on: ubuntu-latest - steps: - uses: actions/checkout@v2 - name: setup dependencies run: | sudo apt-get -y update sudo apt-get -y install libboost-all-dev libasio-dev - - name: run cmake + - name: Configure CMake run: | mkdir build cd build - cmake .. -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - - name: make + cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + - name: Build run: | - cd /home/runner/work/cli/cli/build - make all - - name: run tests + # cd /home/runner/work/cli/cli/build + # make all + cmake --build ./build --config ${{matrix.build_type}} + + - name: run tests - Unix + if: runner.os != 'Windows' + working-directory: ./build/test run: | - cd /home/runner/work/cli/cli/build/test + # cd /home/runner/work/cli/cli/build/test ./test_suite From 2b87f6a5fb117f8b8a3ae861d5353d9e55ecab23 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:23:20 +0200 Subject: [PATCH 075/223] Change generator in CI github actions --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 56567d9..b19cf07 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -18,7 +18,7 @@ jobs: - llvm-13.0.0 - gcc-11 generator: - - "Ninja Multi-Config" + - "Ninja" build_type: - Release - Debug From 1e747d5fb4bf15c61437f6162464beefa770b5a9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:29:37 +0200 Subject: [PATCH 076/223] Setup dependencies in CI github actions --- .github/workflows/ccpp.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index b19cf07..ff4fbb2 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -69,6 +69,31 @@ jobs: steps: - uses: actions/checkout@v2 + + - name: Setup Cache + uses: ./.github/actions/setup_cache + with: + compiler: ${{ matrix.compiler }} + build_type: ${{ matrix.build_type }} + generator: ${{ matrix.generator }} + + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + compiler: ${{ matrix.compiler }} + vcvarsall: ${{ contains(matrix.os, 'windows' )}} + + cmake: true + ninja: true + vcpkg: false + ccache: true + clangtidy: true + + cppcheck: true + + gcovr: true + opencppcoverage: true + - name: setup dependencies run: | sudo apt-get -y update From 8c67b157a1cffd9fed434dd5ba73321264f4a0bd Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:33:11 +0200 Subject: [PATCH 077/223] Remove cache in CI github actions --- .github/workflows/ccpp.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index ff4fbb2..b923072 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -70,13 +70,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup Cache - uses: ./.github/actions/setup_cache - with: - compiler: ${{ matrix.compiler }} - build_type: ${{ matrix.build_type }} - generator: ${{ matrix.generator }} - - name: Setup Cpp uses: aminya/setup-cpp@v1 with: From d14d83944c6f5f88061609f38662b93a50c80a33 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:40:10 +0200 Subject: [PATCH 078/223] Remove cache in CI github actions --- .github/workflows/ccpp.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index b923072..45c1ca1 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -89,8 +89,16 @@ jobs: - name: setup dependencies run: | - sudo apt-get -y update - sudo apt-get -y install libboost-all-dev libasio-dev + if [[ "$RUNNER_OS" == "Linux" ]]; then + sudo apt-get -y update + sudo apt-get -y install -y ninja-build libboost-all-dev + elif [[ "$RUNNER_OS" == "macOS" ]]; then + brew install ninja boost + elif [[ "$RUNNER_OS" == "Windows" ]]; then + choco install ninja + choco install boost-msvc-14.1 + fi + - name: Configure CMake run: | mkdir build From 6fa5ca77e054f5ff5c601473ca7a2985e6e8a3ab Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:58:22 +0200 Subject: [PATCH 079/223] Setup dependencies according to OS in CI github actions --- .github/workflows/ccpp.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 45c1ca1..96680a5 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -87,17 +87,20 @@ jobs: gcovr: true opencppcoverage: true - - name: setup dependencies + - name: setup dependencies - Unix + if: runner.os == 'Linux' run: | - if [[ "$RUNNER_OS" == "Linux" ]]; then sudo apt-get -y update sudo apt-get -y install -y ninja-build libboost-all-dev - elif [[ "$RUNNER_OS" == "macOS" ]]; then + - name: setup dependencies - macOS + if: runner.os == 'macOS' + run: | brew install ninja boost - elif [[ "$RUNNER_OS" == "Windows" ]]; then + - name: setup dependencies - Windows + if: runner.os == 'Windows' + run: | choco install ninja choco install boost-msvc-14.1 - fi - name: Configure CMake run: | From ea905e087d4f6590a5eb74f887571f3d3ebae132 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:23:56 +0200 Subject: [PATCH 080/223] Add standalone asio in CI github actions --- .github/workflows/ccpp.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 96680a5..6d1bbbf 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -91,16 +91,17 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get -y update - sudo apt-get -y install -y ninja-build libboost-all-dev + sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev - name: setup dependencies - macOS if: runner.os == 'macOS' run: | - brew install ninja boost + brew install ninja boost asio - name: setup dependencies - Windows if: runner.os == 'Windows' run: | choco install ninja choco install boost-msvc-14.1 + choco install asio - name: Configure CMake run: | From 568870e6aaa41a0f16cc54030f6fab6c262e5f11 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:42:20 +0200 Subject: [PATCH 081/223] Add standalone asio in win CI github actions --- .github/workflows/ccpp.yml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 6d1bbbf..4155080 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -18,7 +18,7 @@ jobs: - llvm-13.0.0 - gcc-11 generator: - - "Ninja" + - "Ninja Multi-Config" build_type: - Release - Debug @@ -40,29 +40,16 @@ jobs: # Set up preferred package generators, for given build configurations - build_type: Release - developer_mode: OFF package_generator: TBZ2 - os: windows-2022 compiler: msvc generator: "Visual Studio 17 2022" build_type: Debug - developer_mode: ON - os: windows-2022 compiler: msvc generator: "Visual Studio 17 2022" build_type: Release - developer_mode: ON - - os: windows-2022 - compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Debug - developer_mode: OFF - - os: windows-2022 - compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Release - developer_mode: OFF package_generator: ZIP @@ -101,7 +88,11 @@ jobs: run: | choco install ninja choco install boost-msvc-14.1 - choco install asio + # Download and extract Asio + Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip + Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio + # Set ASIO_INCLUDE_DIR environment variable + echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV - name: Configure CMake run: | From 9c31f775309e402ebde27597d40c4fa33097fc5a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:44:49 +0200 Subject: [PATCH 082/223] Add standalone asio in win CI github actions --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 4155080..d4cf948 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -92,7 +92,7 @@ jobs: Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio # Set ASIO_INCLUDE_DIR environment variable - echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV + echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV - name: Configure CMake run: | From a7acdab3169fe13bdd6c9ce616571e68db71699d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:54:21 +0200 Subject: [PATCH 083/223] Add standalone asio in win CI github actions --- .github/workflows/ccpp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index d4cf948..1700220 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -107,7 +107,7 @@ jobs: - name: run tests - Unix if: runner.os != 'Windows' - working-directory: ./build/test + working-directory: ./build/test/${{matrix.build_type}} run: | - # cd /home/runner/work/cli/cli/build/test + # cd /home/runner/work/cli/cli/build/test/ ./test_suite From 3977410ae89243d133a3fdef087a5bc2edf1e640 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:12:28 +0200 Subject: [PATCH 084/223] Remove win test in CI github actions --- .github/workflows/ccpp.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1700220..4db01e8 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -88,17 +88,19 @@ jobs: run: | choco install ninja choco install boost-msvc-14.1 - # Download and extract Asio - Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip - Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio - # Set ASIO_INCLUDE_DIR environment variable - echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV + # # Download and extract Asio + # Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip + # Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio + # # Set ASIO_INCLUDE_DIR environment variable + # echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV - name: Configure CMake run: | - mkdir build - cd build - cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + # mkdir build + # cd build + # cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=-DDISABLE_STACK_PROTECTION:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + - name: Build run: | # cd /home/runner/work/cli/cli/build From 81f4a749d5b12570a0bf9005fc67b12c4db6b35f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:27:01 +0200 Subject: [PATCH 085/223] Remove win test in CI github actions --- .github/workflows/ccpp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 4db01e8..0d7acfd 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -99,7 +99,7 @@ jobs: # mkdir build # cd build # cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=-DDISABLE_STACK_PROTECTION:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: | From 5b17b3cfcce1f10e3f2bfae8ae62a8d2589689ce Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:52:56 +0200 Subject: [PATCH 086/223] Add compilers in CI github actions --- .github/workflows/ccpp.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 0d7acfd..955b845 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -16,7 +16,10 @@ jobs: compiler: # you can specify the version after `-` like "llvm-13.0.0". - llvm-13.0.0 + - clang++-10 + - clang++-14 - gcc-11 + - gcc-12 generator: - "Ninja Multi-Config" build_type: @@ -109,7 +112,9 @@ jobs: - name: run tests - Unix if: runner.os != 'Windows' - working-directory: ./build/test/${{matrix.build_type}} + # working-directory: ./build/test/${{matrix.build_type}} + working-directory: ./build run: | # cd /home/runner/work/cli/cli/build/test/ - ./test_suite + # ./test_suite + ctest -C ${{matrix.build_type}} From 4579743e739eb5d8a4c04245af6b2a73bf352ece Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:03:25 +0200 Subject: [PATCH 087/223] Test win in CI github actions --- .github/workflows/ccpp.yml | 9 +++--- .github/workflows/ci_win.yml | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/ci_win.yml diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 955b845..8a0e20f 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -12,14 +12,13 @@ jobs: os: - ubuntu-20.04 - ubuntu-latest - - macos-12 +# - macos-12 compiler: # you can specify the version after `-` like "llvm-13.0.0". - - llvm-13.0.0 - - clang++-10 - - clang++-14 +# - llvm-13.0.0 +# - clang++-14 - gcc-11 - - gcc-12 + # - gcc-12 generator: - "Ninja Multi-Config" build_type: diff --git a/.github/workflows/ci_win.yml b/.github/workflows/ci_win.yml new file mode 100644 index 0000000..f9b13e3 --- /dev/null +++ b/.github/workflows/ci_win.yml @@ -0,0 +1,55 @@ +name: CI_win + +on: [push, pull_request] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + # os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-latest] + os: [windows-latest] + compiler: [llvm-13.0.0, gcc-11] + generator: ["Ninja"] + build_type: [Release, Debug] + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up CMake + uses: jwlawson/actions-setup-cmake@v1 + + - name: Install vcpkg + run: | + git clone https://github.com/microsoft/vcpkg.git + ./vcpkg/bootstrap-vcpkg.sh + + - name: Install dependencies on Linux and macOS + if: runner.os != 'Windows' + run: | + if [[ "$RUNNER_OS" == "Linux" ]]; then + sudo apt-get update + sudo apt-get install -y ninja-build + elif [[ "$RUNNER_OS" == "macOS" ]]; then + brew install ninja + fi + + - name: Install dependencies on Windows + if: runner.os == 'Windows' + run: choco install ninja + + - name: Install Asio using vcpkg + run: | + ./vcpkg/vcpkg install asio + ./vcpkg/vcpkg integrate install + + - name: Configure CMake + run: cmake -S . -B build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + + - name: Build + run: cmake --build build --config ${{matrix.build_type}} + + - name: run tests + working-directory: ./build + run: ctest -C ${{matrix.build_type}} From 034525094d9a8f7ef0af6e354f6bbec9eb00dda3 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:08:59 +0200 Subject: [PATCH 088/223] Test win in CI github actions --- .github/workflows/{ccpp.yml => ccpp.yml.orig} | 6 +++--- .github/workflows/ci_win.yml | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) rename .github/workflows/{ccpp.yml => ccpp.yml.orig} (98%) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml.orig similarity index 98% rename from .github/workflows/ccpp.yml rename to .github/workflows/ccpp.yml.orig index 8a0e20f..c5739c7 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml.orig @@ -12,11 +12,11 @@ jobs: os: - ubuntu-20.04 - ubuntu-latest -# - macos-12 + - macos-12 compiler: # you can specify the version after `-` like "llvm-13.0.0". -# - llvm-13.0.0 -# - clang++-14 + - llvm-13.0.0 + - clang++-14 - gcc-11 # - gcc-12 generator: diff --git a/.github/workflows/ci_win.yml b/.github/workflows/ci_win.yml index f9b13e3..c175d19 100644 --- a/.github/workflows/ci_win.yml +++ b/.github/workflows/ci_win.yml @@ -7,10 +7,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - # os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-latest] os: [windows-latest] - compiler: [llvm-13.0.0, gcc-11] - generator: ["Ninja"] + compiler: [msvc] + generator: ["Visual Studio 17 2022"] build_type: [Release, Debug] steps: From daf1a0984cce85244821f6c940c89c7f67de7b37 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:14:50 +0200 Subject: [PATCH 089/223] Test win in CI github actions --- .github/workflows/ci_win.yml | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci_win.yml b/.github/workflows/ci_win.yml index c175d19..54e7e43 100644 --- a/.github/workflows/ci_win.yml +++ b/.github/workflows/ci_win.yml @@ -16,24 +16,28 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Set up CMake - uses: jwlawson/actions-setup-cmake@v1 + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + compiler: ${{ matrix.compiler }} + vcvarsall: ${{ contains(matrix.os, 'windows' )}} + + cmake: true + ninja: true + vcpkg: true + ccache: true + clangtidy: false + + cppcheck: false + + gcovr: false + opencppcoverage: false - name: Install vcpkg run: | git clone https://github.com/microsoft/vcpkg.git ./vcpkg/bootstrap-vcpkg.sh - - name: Install dependencies on Linux and macOS - if: runner.os != 'Windows' - run: | - if [[ "$RUNNER_OS" == "Linux" ]]; then - sudo apt-get update - sudo apt-get install -y ninja-build - elif [[ "$RUNNER_OS" == "macOS" ]]; then - brew install ninja - fi - - name: Install dependencies on Windows if: runner.os == 'Windows' run: choco install ninja From db4345140859848730abdaadb8a25f47141204f5 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:24:51 +0200 Subject: [PATCH 090/223] Test win in CI github actions --- .github/workflows/ci_win.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_win.yml b/.github/workflows/ci_win.yml index 54e7e43..9f62517 100644 --- a/.github/workflows/ci_win.yml +++ b/.github/workflows/ci_win.yml @@ -33,10 +33,8 @@ jobs: gcovr: false opencppcoverage: false - - name: Install vcpkg - run: | - git clone https://github.com/microsoft/vcpkg.git - ./vcpkg/bootstrap-vcpkg.sh + - name: Setup vcpkg + uses: lukka/run-vcpkg@v11 # Always specify the specific _version_ of the - name: Install dependencies on Windows if: runner.os == 'Windows' @@ -44,8 +42,8 @@ jobs: - name: Install Asio using vcpkg run: | - ./vcpkg/vcpkg install asio - ./vcpkg/vcpkg integrate install + vcpkg install asio + vcpkg integrate install - name: Configure CMake run: cmake -S . -B build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON From 495e3ae609c0011e48a79d0e47e82dc0e5f798b2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:29:24 +0200 Subject: [PATCH 091/223] Disabled win test build in CI github actions --- .github/workflows/{ccpp.yml.orig => ccpp.yml} | 0 .github/workflows/ci_win.yml | 56 ------------------- 2 files changed, 56 deletions(-) rename .github/workflows/{ccpp.yml.orig => ccpp.yml} (100%) delete mode 100644 .github/workflows/ci_win.yml diff --git a/.github/workflows/ccpp.yml.orig b/.github/workflows/ccpp.yml similarity index 100% rename from .github/workflows/ccpp.yml.orig rename to .github/workflows/ccpp.yml diff --git a/.github/workflows/ci_win.yml b/.github/workflows/ci_win.yml deleted file mode 100644 index 9f62517..0000000 --- a/.github/workflows/ci_win.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: CI_win - -on: [push, pull_request] - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [windows-latest] - compiler: [msvc] - generator: ["Visual Studio 17 2022"] - build_type: [Release, Debug] - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup Cpp - uses: aminya/setup-cpp@v1 - with: - compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows' )}} - - cmake: true - ninja: true - vcpkg: true - ccache: true - clangtidy: false - - cppcheck: false - - gcovr: false - opencppcoverage: false - - - name: Setup vcpkg - uses: lukka/run-vcpkg@v11 # Always specify the specific _version_ of the - - - name: Install dependencies on Windows - if: runner.os == 'Windows' - run: choco install ninja - - - name: Install Asio using vcpkg - run: | - vcpkg install asio - vcpkg integrate install - - - name: Configure CMake - run: cmake -S . -B build -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - - - name: Build - run: cmake --build build --config ${{matrix.build_type}} - - - name: run tests - working-directory: ./build - run: ctest -C ${{matrix.build_type}} From 0b4de32a40abad01ce67ec23e55f2053341b877e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:48:18 +0200 Subject: [PATCH 092/223] Try windows CI in github actions --- .github/workflows/{ccpp.yml => ccpp.yml.orig} | 2 +- .github/workflows/win_ci.yml | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) rename .github/workflows/{ccpp.yml => ccpp.yml.orig} (98%) create mode 100644 .github/workflows/win_ci.yml diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml.orig similarity index 98% rename from .github/workflows/ccpp.yml rename to .github/workflows/ccpp.yml.orig index c5739c7..c78d5e6 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml.orig @@ -107,7 +107,7 @@ jobs: run: | # cd /home/runner/work/cli/cli/build # make all - cmake --build ./build --config ${{matrix.build_type}} + cmake --build ./build --config ${{matrix.build_type}} - name: run tests - Unix if: runner.os != 'Windows' diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml new file mode 100644 index 0000000..3783519 --- /dev/null +++ b/.github/workflows/win_ci.yml @@ -0,0 +1,35 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up MSVC + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install Boost + run: | + curl -L -o boost.zip https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.zip + tar -xf boost.zip + move boost_1_81_0 boost + + - name: Install ASIO standalone + run: | + curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip + tar -xf asio.zip + move asio-asio-1-18-2 asio + + - name: Configure CMake + run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DBOOST_ROOT=%cd%/boost -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + + - name: Build + run: cmake --build build --config Release + + - name: Run tests + run: ctest --test-dir build --output-on-failure From 6616fed9224134fbde2c15c06968152ad1b9af2b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:01:53 +0200 Subject: [PATCH 093/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 3783519..40af5e1 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -14,10 +14,10 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: Install Boost - run: | - curl -L -o boost.zip https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.zip - tar -xf boost.zip - move boost_1_81_0 boost + run: choco install boost-msvc-14.1 + # curl -L -o boost.zip https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.zip + # tar -xf boost.zip + # move boost_1_81_0 boost - name: Install ASIO standalone run: | @@ -26,7 +26,8 @@ jobs: move asio-asio-1-18-2 asio - name: Configure CMake - run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DBOOST_ROOT=%cd%/boost -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + # run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DBOOST_ROOT=%cd%/boost -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From f2014deaac012f552ceb1847c223694d2d868ccd Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:16:37 +0200 Subject: [PATCH 094/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 40af5e1..05a2faf 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -15,9 +15,6 @@ jobs: - name: Install Boost run: choco install boost-msvc-14.1 - # curl -L -o boost.zip https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.zip - # tar -xf boost.zip - # move boost_1_81_0 boost - name: Install ASIO standalone run: | @@ -26,8 +23,7 @@ jobs: move asio-asio-1-18-2 asio - name: Configure CMake - # run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DBOOST_ROOT=%cd%/boost -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - run: cmake -S . -B build -DASIO_INCLUDE_DIR=%cd%/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DASIO_INCLUDEDIR=%cd%/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From 602b95b336911754ebac07a1fb20502319d3829d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:28:07 +0200 Subject: [PATCH 095/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 05a2faf..92f9660 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -23,7 +23,7 @@ jobs: move asio-asio-1-18-2 asio - name: Configure CMake - run: cmake -S . -B build -DASIO_INCLUDEDIR=%cd%/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DASIO_INCLUDEDIR=${GITHUB_WORKSPACE}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From f9a0602f3a2904699c36f47011a77169ea812608 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:49:22 +0200 Subject: [PATCH 096/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 92f9660..f777fa1 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -16,14 +16,22 @@ jobs: - name: Install Boost run: choco install boost-msvc-14.1 - - name: Install ASIO standalone - run: | - curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip - tar -xf asio.zip - move asio-asio-1-18-2 asio +# - name: Install ASIO standalone +# run: | +# curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip +# tar -xf asio.zip +# move asio-asio-1-18-2 asio +# + - name: Install Asio with vcpkg + uses: microsoft/vcpkg-action@v1 + with: + # Configura le opzioni di vcpkg + buildtype: release + args: install asio - name: Configure CMake - run: cmake -S . -B build -DASIO_INCLUDEDIR=${GITHUB_WORKSPACE}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + # run: cmake -S . -B build -DASIO_INCLUDEDIR=${GITHUB_WORKSPACE}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From d3c9394e961ce14e3748fca0b540676e661f55d4 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:50:10 +0200 Subject: [PATCH 097/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index f777fa1..e6c4bda 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -31,7 +31,7 @@ jobs: - name: Configure CMake # run: cmake -S . -B build -DASIO_INCLUDEDIR=${GITHUB_WORKSPACE}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - run: cmake -S . -B build -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From 6fa94915eb221bf4340328415e1d558a1a6a4c88 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:55:13 +0200 Subject: [PATCH 098/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index e6c4bda..eb57118 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -16,22 +16,14 @@ jobs: - name: Install Boost run: choco install boost-msvc-14.1 -# - name: Install ASIO standalone -# run: | -# curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip -# tar -xf asio.zip -# move asio-asio-1-18-2 asio -# - - name: Install Asio with vcpkg - uses: microsoft/vcpkg-action@v1 - with: - # Configura le opzioni di vcpkg - buildtype: release - args: install asio + - name: Install ASIO standalone + run: | + curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip + tar -xf asio.zip + move asio-asio-1-18-2 asio - name: Configure CMake - # run: cmake -S . -B build -DASIO_INCLUDEDIR=${GITHUB_WORKSPACE}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - run: cmake -S . -B build -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: cmake --build build --config Release From ea1d5f55fda340a2373cf35ec13fe9e259b7b0ea Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 23:12:19 +0200 Subject: [PATCH 099/223] Try windows CI in github actions --- .github/workflows/win_ci.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index eb57118..dd83be5 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -3,8 +3,15 @@ name: CI on: [push, pull_request] jobs: - build: + Test: runs-on: windows-latest + strategy: + fail-fast: false + + matrix: + build_type: + - Release + - Debug steps: - name: Checkout repository @@ -23,10 +30,11 @@ jobs: move asio-asio-1-18-2 asio - name: Configure CMake - run: cmake -S . -B build -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build - run: cmake --build build --config Release + run: cmake --build build --config ${{matrix.build_type}} - name: Run tests - run: ctest --test-dir build --output-on-failure + working-directory: build + run: ctest -C ${{matrix.build_type}} \ No newline at end of file From a7cb3dfc63fa6942bc4c1f37873b26f720d9ee7a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Oct 2024 23:22:59 +0200 Subject: [PATCH 100/223] Split CI in github actions --- .github/workflows/{ccpp.yml.orig => unix_ci.yml} | 2 +- .github/workflows/win_ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{ccpp.yml.orig => unix_ci.yml} (97%) diff --git a/.github/workflows/ccpp.yml.orig b/.github/workflows/unix_ci.yml similarity index 97% rename from .github/workflows/ccpp.yml.orig rename to .github/workflows/unix_ci.yml index c78d5e6..57161fe 100644 --- a/.github/workflows/ccpp.yml.orig +++ b/.github/workflows/unix_ci.yml @@ -116,4 +116,4 @@ jobs: run: | # cd /home/runner/work/cli/cli/build/test/ # ./test_suite - ctest -C ${{matrix.build_type}} + ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index dd83be5..411ed6f 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -37,4 +37,4 @@ jobs: - name: Run tests working-directory: build - run: ctest -C ${{matrix.build_type}} \ No newline at end of file + run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure \ No newline at end of file From 3abe7dcb2d21377dfb649539b2a3d09f3be74519 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 07:41:44 +0200 Subject: [PATCH 101/223] Not using ctest in win CI github actions --- .github/workflows/unix_ci.yml | 2 +- .github/workflows/win_ci.yml | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 57161fe..6aee6fb 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -1,4 +1,4 @@ -name: C/C++ CI of Cli +name: Unix CI on: [push,pull_request] diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 411ed6f..b546eab 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Windows CI on: [push, pull_request] @@ -36,5 +36,7 @@ jobs: run: cmake --build build --config ${{matrix.build_type}} - name: Run tests - working-directory: build - run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure \ No newline at end of file + # working-directory: build + working-directory: build/test/${{matrix.build_type}} + # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure + run: test_suite \ No newline at end of file From 3ab4ef73496aaee239609f28636ed41e266124a2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 08:53:45 +0200 Subject: [PATCH 102/223] Verbose ctest in win CI github actions --- .github/workflows/win_ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index b546eab..692e46b 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -36,7 +36,7 @@ jobs: run: cmake --build build --config ${{matrix.build_type}} - name: Run tests - # working-directory: build - working-directory: build/test/${{matrix.build_type}} - # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure - run: test_suite \ No newline at end of file + working-directory: build + # working-directory: build/test/${{matrix.build_type}} + run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose + # run: test_suite \ No newline at end of file From d100ab3b27d2ad4e9e2aeefb4b151ba58884953d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:39:35 +0200 Subject: [PATCH 103/223] Try explicit execution of test_suite in win CI github actions --- .github/workflows/win_ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 692e46b..e04fd32 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -36,7 +36,7 @@ jobs: run: cmake --build build --config ${{matrix.build_type}} - name: Run tests - working-directory: build - # working-directory: build/test/${{matrix.build_type}} - run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose - # run: test_suite \ No newline at end of file + # working-directory: build + working-directory: build/test/${{matrix.build_type}} + # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose + run: ./test_suite \ No newline at end of file From 8e941c06eec0130bc6c4fd7ab8d38645e50fdf57 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:59:49 +0200 Subject: [PATCH 104/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index e04fd32..f571d4e 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -2,6 +2,10 @@ name: Windows CI on: [push, pull_request] +env: + ACTIONS_RUNNER_DEBUG: true + ACTIONS_STEP_DEBUG: true + jobs: Test: runs-on: windows-latest @@ -15,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up MSVC uses: ilammy/msvc-dev-cmd@v1 @@ -39,4 +43,4 @@ jobs: # working-directory: build working-directory: build/test/${{matrix.build_type}} # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose - run: ./test_suite \ No newline at end of file + run: ./test_suite From 6e17dfbb67ee04650d4909d263530f84380087b9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:23:44 +0200 Subject: [PATCH 105/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index f571d4e..ca5607f 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -2,10 +2,6 @@ name: Windows CI on: [push, pull_request] -env: - ACTIONS_RUNNER_DEBUG: true - ACTIONS_STEP_DEBUG: true - jobs: Test: runs-on: windows-latest @@ -43,4 +39,4 @@ jobs: # working-directory: build working-directory: build/test/${{matrix.build_type}} # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose - run: ./test_suite + run: ./test_suite -l all From 33610468840c9b4764e89141f98278530f80c977 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:36:46 +0200 Subject: [PATCH 106/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index ca5607f..d46bbd3 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -36,7 +36,7 @@ jobs: run: cmake --build build --config ${{matrix.build_type}} - name: Run tests - # working-directory: build - working-directory: build/test/${{matrix.build_type}} - # run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --verbose - run: ./test_suite -l all + working-directory: build + # working-directory: build/test/${{matrix.build_type}} + run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --debug + # run: ./test_suite -l all From e1aa021000745f0de3ea345c1e885f245c7f5745 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:09:51 +0200 Subject: [PATCH 107/223] Remove test to understando which one throws exceptions in win CI github actions --- test/CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d0942e0..7700c93 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,16 +50,16 @@ target_link_libraries(standalone_asio_test INTERFACE Threads::Threads) add_executable( test_suite driver.cpp - test_history.cpp - test_volatilehistorystorage.cpp - test_filehistorystorage.cpp +# test_history.cpp +# test_volatilehistorystorage.cpp +# test_filehistorystorage.cpp test_split.cpp - test_commonprefix.cpp - test_menu.cpp - test_cli.cpp - test_loopscheduler.cpp - test_standaloneasioscheduler.cpp - test_boostasioscheduler.cpp +# test_commonprefix.cpp +# test_menu.cpp +# test_cli.cpp +# test_loopscheduler.cpp +# test_standaloneasioscheduler.cpp +# test_boostasioscheduler.cpp ) # indicates the include paths target_include_directories(test_suite SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) From b823f642ed986364a137e6827fafb18af56a4ac0 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:27:09 +0200 Subject: [PATCH 108/223] Enable all tests in win CI github actions --- .github/workflows/win_ci.yml | 2 +- test/CMakeLists.txt | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index d46bbd3..7dc8b0b 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -38,5 +38,5 @@ jobs: - name: Run tests working-directory: build # working-directory: build/test/${{matrix.build_type}} - run: ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure --debug + run: ctest -C ${{matrix.build_type}} --output-on-failure --debug # run: ./test_suite -l all diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7700c93..d0942e0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,16 +50,16 @@ target_link_libraries(standalone_asio_test INTERFACE Threads::Threads) add_executable( test_suite driver.cpp -# test_history.cpp -# test_volatilehistorystorage.cpp -# test_filehistorystorage.cpp + test_history.cpp + test_volatilehistorystorage.cpp + test_filehistorystorage.cpp test_split.cpp -# test_commonprefix.cpp -# test_menu.cpp -# test_cli.cpp -# test_loopscheduler.cpp -# test_standaloneasioscheduler.cpp -# test_boostasioscheduler.cpp + test_commonprefix.cpp + test_menu.cpp + test_cli.cpp + test_loopscheduler.cpp + test_standaloneasioscheduler.cpp + test_boostasioscheduler.cpp ) # indicates the include paths target_include_directories(test_suite SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) From e402647153c8dd1d47ebadeade58e55392283ff9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:13:52 +0200 Subject: [PATCH 109/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 7dc8b0b..4c2bea0 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -4,11 +4,15 @@ on: [push, pull_request] jobs: Test: - runs-on: windows-latest + # runs-on: windows-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: + - windows-2022 + - windows-2019 build_type: - Release - Debug From f3bf6ff8671580c5da0b99a8ab56a469f3cb1999 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:28:13 +0200 Subject: [PATCH 110/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 4c2bea0..eb07d50 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -25,7 +25,7 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: Install Boost - run: choco install boost-msvc-14.1 + run: choco install boost-msvc-14.2 - name: Install ASIO standalone run: | From 53638096787f2ea23b2bc2d5b124e5b1c5ce7c40 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:37:37 +0200 Subject: [PATCH 111/223] Update win_ci.yml --- .github/workflows/win_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index eb07d50..4c2bea0 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -25,7 +25,7 @@ jobs: uses: ilammy/msvc-dev-cmd@v1 - name: Install Boost - run: choco install boost-msvc-14.2 + run: choco install boost-msvc-14.1 - name: Install ASIO standalone run: | From 82e2a58a1fe14da75301376125594906d0554647 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:10:12 +0200 Subject: [PATCH 112/223] Add c++ std to cmake file and disabled CI tests on win --- .github/workflows/unix_ci.yml | 3 ++- .github/workflows/win_ci.yml | 7 ++++--- CMakeLists.txt | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 6aee6fb..8733a8f 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -19,6 +19,7 @@ jobs: - clang++-14 - gcc-11 # - gcc-12 + standard: [14, 17, 20, 23] generator: - "Ninja Multi-Config" build_type: @@ -101,7 +102,7 @@ jobs: # mkdir build # cd build # cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: | diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 4c2bea0..7ccc25e 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -39,8 +39,9 @@ jobs: - name: Build run: cmake --build build --config ${{matrix.build_type}} - - name: Run tests - working-directory: build +# - name: Run tests # working-directory: build/test/${{matrix.build_type}} - run: ctest -C ${{matrix.build_type}} --output-on-failure --debug # run: ./test_suite -l all +# working-directory: build +# run: ctest -C ${{matrix.build_type}} --output-on-failure --debug + diff --git a/CMakeLists.txt b/CMakeLists.txt index 750e7a9..8969743 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,11 @@ if (CLI_UseStandaloneAsio) # alternative way: # target_include_directories(cli SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) endif() -target_compile_features(cli INTERFACE cxx_std_14) + +if(NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() +target_compile_features(cli INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) # Examples if (CLI_BuildExamples) From 120ac1a398a530641195dc14533e2e150570e3c6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:11:11 +0200 Subject: [PATCH 113/223] Fix CI test --- .github/workflows/unix_ci.yml | 20 +++++++++++++------- .github/workflows/win_ci.yml | 5 +++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 8733a8f..1e8fd32 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -96,22 +96,28 @@ jobs: # Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio # # Set ASIO_INCLUDE_DIR environment variable # echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV - - - name: Configure CMake + curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip + tar -xf asio.zip + move asio-asio-1-18-2 asio + + - name: Configure CMake - Unix + if: runner.os != 'Windows' run: | - # mkdir build - # cd build - # cmake .. -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + - name: Configure CMake - Windows + if: runner.os == 'Windows' + run: | + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + - name: Build run: | # cd /home/runner/work/cli/cli/build # make all cmake --build ./build --config ${{matrix.build_type}} - - name: run tests - Unix - if: runner.os != 'Windows' + - name: run tests + # if: runner.os != 'Windows' # working-directory: ./build/test/${{matrix.build_type}} working-directory: ./build run: | diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 7ccc25e..1d840fc 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -16,7 +16,8 @@ jobs: build_type: - Release - Debug - + standard: [14, 17, 20] + steps: - name: Checkout repository uses: actions/checkout@v3 @@ -34,7 +35,7 @@ jobs: move asio-asio-1-18-2 asio - name: Configure CMake - run: cmake -S . -B build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + run: cmake -S . -B build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DCMAKE_CXX_STANDARD=${{matrix.standard}} - name: Build run: cmake --build build --config ${{matrix.build_type}} From ea6bad7bceec77c932044c60c329535c97bcd9a2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:41:41 +0200 Subject: [PATCH 114/223] Fix CI test --- .github/workflows/unix_ci.yml | 6 +++--- .github/workflows/win_ci.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 1e8fd32..eeb5d52 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -103,12 +103,12 @@ jobs: - name: Configure CMake - Unix if: runner.os != 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Configure CMake - Windows if: runner.os == 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests:BOOL=${{ runner.os != 'Windows' }} -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Build run: | @@ -123,4 +123,4 @@ jobs: run: | # cd /home/runner/work/cli/cli/build/test/ # ./test_suite - ctest -C ${{matrix.build_type}} --rerun-failed --output-on-failure + ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 1d840fc..59c525f 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -16,7 +16,7 @@ jobs: build_type: - Release - Debug - standard: [14, 17, 20] + standard: [14, 17, 20, 23] steps: - name: Checkout repository From f62a2e373bc88385f7a97a5e93da5918d34c2fab Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:32:17 +0200 Subject: [PATCH 115/223] Disable win test execution on CI test --- .github/workflows/unix_ci.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index eeb5d52..0e00e98 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -49,14 +49,14 @@ jobs: compiler: msvc generator: "Visual Studio 17 2022" build_type: Debug + standard: 23 - os: windows-2022 compiler: msvc generator: "Visual Studio 17 2022" build_type: Release + standard: 23 package_generator: ZIP - - steps: - uses: actions/checkout@v2 @@ -92,10 +92,6 @@ jobs: choco install ninja choco install boost-msvc-14.1 # # Download and extract Asio - # Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip - # Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio - # # Set ASIO_INCLUDE_DIR environment variable - # echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip move asio-asio-1-18-2 asio @@ -106,9 +102,10 @@ jobs: cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Configure CMake - Windows + # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include - name: Build run: | @@ -117,7 +114,8 @@ jobs: cmake --build ./build --config ${{matrix.build_type}} - name: run tests - # if: runner.os != 'Windows' + # on windows test_suite throws an exception, but only on the CI environment! + if: runner.os != 'Windows' # working-directory: ./build/test/${{matrix.build_type}} working-directory: ./build run: | From dc96e6b23795dd46e549605e2e5450bbc9bf39eb Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:27:41 +0200 Subject: [PATCH 116/223] Try to put all in one CI test file --- .github/workflows/unix_ci.yml | 61 +++++++++++------------------------ 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 0e00e98..916b653 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -9,53 +9,30 @@ jobs: fail-fast: false matrix: - os: - - ubuntu-20.04 - - ubuntu-latest - - macos-12 - compiler: - # you can specify the version after `-` like "llvm-13.0.0". - - llvm-13.0.0 - - clang++-14 - - gcc-11 - # - gcc-12 + os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-2022, windows-2019] + compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] - generator: - - "Ninja Multi-Config" - build_type: - - Release - - Debug - + # generator: ["Ninja Multi-Config", "Visual Studio 17 2022"] + generator: ["Ninja Multi-Config"] + build_type: [Release, Debug] exclude: - # mingw is determined by this author to be too buggy to support - - os: macos-12 - compiler: gcc-11 + # Exclude msvc on non-Windows platforms - os: ubuntu-20.04 - compiler: llvm-13.0.0 - - include: - # Add appropriate variables for gcov version required. This will intentionally break - # if you try to use a compiler that does not have gcov set - - compiler: gcc-11 - gcov_executable: gcov - - compiler: llvm-13.0.0 - gcov_executable: "llvm-cov gcov" - - # Set up preferred package generators, for given build configurations - - build_type: Release - package_generator: TBZ2 - - - os: windows-2022 compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Debug - standard: 23 - - os: windows-2022 + - os: ubuntu-latest + compiler: msvc + - os: macos-12 compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Release - standard: 23 - package_generator: ZIP + # Exclude gcc on Windows platforms + - os: windows-2022 + compiler: gcc-11 + - os: windows-2019 + compiler: gcc-11 + # Exclude llvm on Windows platforms + - os: windows-2022 + compiler: llvm-13.0.0 + - os: windows-2019 + compiler: llvm-13.0.0 steps: - uses: actions/checkout@v2 From 2cc6aa7635b15f0c9a3bcc39cfcd5e4198c60622 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:14:29 +0200 Subject: [PATCH 117/223] Try to put all in one CI test file --- .github/workflows/unix_ci.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 916b653..4173498 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -12,9 +12,20 @@ jobs: os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-2022, windows-2019] compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] - # generator: ["Ninja Multi-Config", "Visual Studio 17 2022"] - generator: ["Ninja Multi-Config"] build_type: [Release, Debug] + include: + # Ubuntu and macOS with Ninja + - os: ubuntu-20.04 + generator: "Ninja Multi-Config" + - os: ubuntu-latest + generator: "Ninja Multi-Config" + - os: macos-12 + generator: "Ninja Multi-Config" + # Windows with Visual Studio + - os: windows-2022 + generator: "Visual Studio 17 2022" + - os: windows-2019 + generator: "Visual Studio 17 2022" exclude: # Exclude msvc on non-Windows platforms - os: ubuntu-20.04 @@ -28,6 +39,9 @@ jobs: compiler: gcc-11 - os: windows-2019 compiler: gcc-11 + # Exclude gcc on mac platforms + - os: macos-12 + compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 compiler: llvm-13.0.0 @@ -35,7 +49,7 @@ jobs: compiler: llvm-13.0.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Cpp uses: aminya/setup-cpp@v1 From 4b7c604de9469e15ddf7c648895201a55786e040 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:30:12 +0200 Subject: [PATCH 118/223] Try to put all in one CI test file --- .github/workflows/unix_ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index 4173498..d62d2c5 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -51,6 +51,10 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Set up MSVC + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 + - name: Setup Cpp uses: aminya/setup-cpp@v1 with: From edba00289c200bc74980f97fd1163ff2aa29b67b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:57:57 +0200 Subject: [PATCH 119/223] Try to put all in one CI test file --- .github/workflows/unix_ci.yml | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index d62d2c5..f9170ab 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -13,19 +13,6 @@ jobs: compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] - include: - # Ubuntu and macOS with Ninja - - os: ubuntu-20.04 - generator: "Ninja Multi-Config" - - os: ubuntu-latest - generator: "Ninja Multi-Config" - - os: macos-12 - generator: "Ninja Multi-Config" - # Windows with Visual Studio - - os: windows-2022 - generator: "Visual Studio 17 2022" - - os: windows-2019 - generator: "Visual Studio 17 2022" exclude: # Exclude msvc on non-Windows platforms - os: ubuntu-20.04 @@ -94,13 +81,13 @@ jobs: - name: Configure CMake - Unix if: runner.os != 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Configure CMake - Windows # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include + cmake -S . -B ./build -G -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include - name: Build run: | From b3a273c91960a90cfbd6658c6251923c5c8ba0f4 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 20:13:27 +0200 Subject: [PATCH 120/223] Try to put all in one CI test file --- .github/workflows/unix_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index f9170ab..7d98707 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -87,7 +87,7 @@ jobs: # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -G -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include + cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include - name: Build run: | From 8f85d1582acd6fad94aba840ed8fba12d4545ded Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:58:39 +0200 Subject: [PATCH 121/223] Only one CI test file --- .github/workflows/{unix_ci.yml => ci.yml} | 6 +++--- .github/workflows/{win_ci.yml => win_ci.yml.disabled} | 0 README.md | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) rename .github/workflows/{unix_ci.yml => ci.yml} (97%) rename .github/workflows/{win_ci.yml => win_ci.yml.disabled} (100%) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/ci.yml similarity index 97% rename from .github/workflows/unix_ci.yml rename to .github/workflows/ci.yml index 7d98707..1199a7b 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,9 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up MSVC - if: runner.os == 'Windows' - uses: ilammy/msvc-dev-cmd@v1 + # - name: Set up MSVC + # if: runner.os == 'Windows' + # uses: ilammy/msvc-dev-cmd@v1 - name: Setup Cpp uses: aminya/setup-cpp@v1 diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml.disabled similarity index 100% rename from .github/workflows/win_ci.yml rename to .github/workflows/win_ci.yml.disabled diff --git a/README.md b/README.md index 8c72e30..0ee2c43 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg) +[![CI of Cli](https://github.com/daniele77/cli/actions/workflows/ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/ci.yml) [![CodeQL](https://github.com/daniele77/cli/actions/workflows/codeql.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/codeql.yml) +[:heart: Sponsor](https://github.com/sponsors/daniele77) # cli @@ -10,9 +11,6 @@ A cross-platform header only C++14 library for interactive command line interfac ![demo_telnet_session](https://user-images.githubusercontent.com/5451767/51046612-d1dadc00-15c6-11e9-83c2-beadb3593348.gif) -![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg) - -[:heart: Sponsor](https://github.com/sponsors/daniele77) **IMPORTANT: Breaking API changes!** Version 2.0 of `cli` has made breaking changes in order to add more functionality. To migrate your application to new `cli` version, see the section From 7d43bcde41d9c64edf04151bc2069875790d2df1 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 18 Oct 2024 23:06:07 +0200 Subject: [PATCH 122/223] Change CI name --- .github/workflows/ci.yml | 2 +- README.md | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1199a7b..ace6608 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Unix CI +name: CI on: [push,pull_request] diff --git a/README.md b/README.md index 0ee2c43..a400f86 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,6 @@ A cross-platform header only C++14 library for interactive command line interfac ![demo_telnet_session](https://user-images.githubusercontent.com/5451767/51046612-d1dadc00-15c6-11e9-83c2-beadb3593348.gif) - -**IMPORTANT: Breaking API changes!** Version 2.0 of `cli` has made breaking changes in order to add more functionality. -To migrate your application to new `cli` version, see the section -"Async programming and Schedulers" of this file, or the examples that come with the library. - ## Features * Header only From 59efd18e604d758b45aaa6d63d53ea445ac1e2a1 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:20:44 +0200 Subject: [PATCH 123/223] Basic retrieving commands from history --- include/cli/cli.h | 13 ++++++++++-- include/cli/detail/history.h | 39 ++++++++++++++++++++++++++++++++---- test/test_history.cpp | 35 +++++++++++++++++++++++++++++++- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index 6c18f22..4f8cb46 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -358,6 +358,12 @@ namespace cli void ShowHistory() const { history.Show(out); } + void ExecFromHistory(unsigned index) + { + const auto cmd = history.At(index); + Feed(cmd); + } + std::string PreviousCmd(const std::string& line) { return history.Previous(line); @@ -890,13 +896,16 @@ namespace cli [this](std::ostream&){ Exit(); }, "Quit the session" ); -#ifdef CLI_HISTORY_CMD globalScopeMenu->Insert( "history", [this](std::ostream&){ ShowHistory(); }, "Show the history" ); -#endif + globalScopeMenu->Insert( + "!", {"history entry index"}, + [this](std::ostream&, unsigned cmdIndex){ ExecFromHistory(cmdIndex); }, + "Exec a command by index in the history" + ); } inline void CliSession::Feed(const std::string& cmd) diff --git a/include/cli/detail/history.h b/include/cli/detail/history.h index 528109b..d1f791e 100644 --- a/include/cli/detail/history.h +++ b/include/cli/detail/history.h @@ -111,9 +111,13 @@ class History // Show the whole history on the given ostream void Show(std::ostream& out) const { + const auto size = buffer.size(); out << '\n'; - for (auto& item: buffer) - out << item << '\n'; + for (std::size_t i = 0; i < size; ++i) + { + const auto j = size-1-i; + out << IndexToId(j) << '\t' << buffer[j] << '\n'; + } out << '\n' << std::flush; } @@ -142,21 +146,48 @@ class History return result; } + std::string At(std::size_t id) const + { + std::size_t index = IdToIndex(id); + assert(index < buffer.size()); + return buffer[index]; + } + private: + // oldest has index = size-1 and id = idOfOldest + // newest has index = 0 and id = idOfOldest + size-1 + std::size_t IndexToId(std::size_t index) const + { + if (index > idOfOldest+buffer.size()-1) + throw std::out_of_range("Index not found in buffer"); + return idOfOldest + buffer.size() - 1 - index; + } + + std::size_t IdToIndex(std::size_t id) const + { + if (id < idOfOldest || id > idOfOldest+buffer.size()-1) + throw std::out_of_range("Index not found in buffer"); + return idOfOldest + buffer.size() - 1 - id; + } + void Insert(const std::string& item) { - buffer.push_front(item); + buffer.emplace_front(item); if (buffer.size() > maxSize) + { buffer.pop_back(); + ++idOfOldest; + } } const std::size_t maxSize; - std::deque buffer; + std::deque buffer; // buffer[0] is the newest element std::size_t current = 0; std::size_t commands = 0; // number of commands issued enum class Mode { inserting, browsing }; Mode mode = Mode::inserting; + std::size_t idOfOldest = 0; // the id of the oldest element kept in the history }; } // namespace detail diff --git a/test/test_history.cpp b/test/test_history.cpp index 61e4003..b14cf0f 100644 --- a/test/test_history.cpp +++ b/test/test_history.cpp @@ -80,6 +80,11 @@ BOOST_AUTO_TEST_CASE(Insertion) history.NewCommand("item3"); history.NewCommand("item4"); + BOOST_CHECK_EQUAL(history.At(0), "item1"); + BOOST_CHECK_EQUAL(history.At(1), "item2"); + BOOST_CHECK_EQUAL(history.At(2), "item3"); + BOOST_CHECK_EQUAL(history.At(3), "item4"); + BOOST_CHECK_EQUAL(history.Previous(""), "item4"); BOOST_CHECK_EQUAL(history.Previous("item4"), "item3"); BOOST_CHECK_EQUAL(history.Previous("foo"), "item2"); @@ -90,6 +95,12 @@ BOOST_AUTO_TEST_CASE(Insertion) history.NewCommand("item5"); + BOOST_CHECK_EQUAL(history.At(0), "item1"); + BOOST_CHECK_EQUAL(history.At(1), "item2"); + BOOST_CHECK_EQUAL(history.At(2), "foo"); + BOOST_CHECK_EQUAL(history.At(3), "item4"); + BOOST_CHECK_EQUAL(history.At(4), "item5"); + BOOST_CHECK_EQUAL(history.Previous(""), "item5"); BOOST_CHECK_EQUAL(history.Previous("item5"), "item4"); BOOST_CHECK_EQUAL(history.Next(), "item5"); @@ -150,6 +161,10 @@ BOOST_AUTO_TEST_CASE(Copies) const std::vector v = { "item1", "item2", "item3" }; history.LoadCommands(v); + BOOST_CHECK_EQUAL(history.At(0), "item1"); + BOOST_CHECK_EQUAL(history.At(1), "item2"); + BOOST_CHECK_EQUAL(history.At(2), "item3"); + BOOST_CHECK_EQUAL(history.Previous(""), "item3"); BOOST_CHECK_EQUAL(history.Previous("item3"), "item2"); BOOST_CHECK_EQUAL(history.Previous("item2"), "item1"); @@ -158,6 +173,12 @@ BOOST_AUTO_TEST_CASE(Copies) history.NewCommand("itemA"); history.NewCommand("itemB"); + BOOST_CHECK_EQUAL(history.At(0), "item1"); + BOOST_CHECK_EQUAL(history.At(1), "item2"); + BOOST_CHECK_EQUAL(history.At(2), "item3"); + BOOST_CHECK_EQUAL(history.At(3), "itemA"); + BOOST_CHECK_EQUAL(history.At(4), "itemB"); + BOOST_CHECK_EQUAL(history.Previous(""), "itemB"); BOOST_CHECK_EQUAL(history.Previous("itemB"), "itemA"); BOOST_CHECK_EQUAL(history.Previous("itemA"), "item3"); @@ -175,6 +196,10 @@ BOOST_AUTO_TEST_CASE(Copies) const std::vector v1 = { "item1", "item2", "item3" }; history1.LoadCommands(v1); + BOOST_CHECK_EQUAL(history1.At(0), "item1"); + BOOST_CHECK_EQUAL(history1.At(1), "item2"); + BOOST_CHECK_EQUAL(history1.At(2), "item3"); + BOOST_CHECK_EQUAL(history1.Previous(""), "item3"); BOOST_CHECK_EQUAL(history1.Previous("item3"), "item2"); BOOST_CHECK_EQUAL(history1.Previous("item2"), "item2"); @@ -182,6 +207,10 @@ BOOST_AUTO_TEST_CASE(Copies) history1.NewCommand("itemA"); history1.NewCommand("itemB"); + BOOST_CHECK_EQUAL(history1.At(2), "item3"); + BOOST_CHECK_EQUAL(history1.At(3), "itemA"); + BOOST_CHECK_EQUAL(history1.At(4), "itemB"); + BOOST_CHECK_EQUAL(history1.Previous(""), "itemB"); BOOST_CHECK_EQUAL(history1.Previous("itemB"), "itemA"); BOOST_CHECK_EQUAL(history1.Previous("itemA"), "itemA"); @@ -199,9 +228,13 @@ BOOST_AUTO_TEST_CASE(Copies) history2.NewCommand("itemD"); history2.NewCommand("itemE"); + BOOST_CHECK_EQUAL(history2.At(2), "itemC"); + BOOST_CHECK_EQUAL(history2.At(3), "itemD"); + BOOST_CHECK_EQUAL(history2.At(4), "itemE"); + auto cmds2 = history2.GetCommands(); const std::vector expected2 = { "itemC", "itemD", "itemE" }; BOOST_CHECK_EQUAL_COLLECTIONS(cmds2.begin(), cmds2.end(), expected2.begin(), expected2.end()); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From 63a4f863bfe964a584ed384e8e505a2281af4a7e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:33:41 +0200 Subject: [PATCH 124/223] Remove ! cmd from history --- include/cli/cli.h | 1 + include/cli/detail/history.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/cli/cli.h b/include/cli/cli.h index 4f8cb46..ba723f6 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -361,6 +361,7 @@ namespace cli void ExecFromHistory(unsigned index) { const auto cmd = history.At(index); + history.ForgetLatest(); Feed(cmd); } diff --git a/include/cli/detail/history.h b/include/cli/detail/history.h index d1f791e..c27ea8b 100644 --- a/include/cli/detail/history.h +++ b/include/cli/detail/history.h @@ -153,6 +153,12 @@ class History return buffer[index]; } + void ForgetLatest() + { + assert(!buffer.empty()); + buffer.pop_front(); + } + private: // oldest has index = size-1 and id = idOfOldest From 4e5ce756aeafac1a5e4a74979cf1d2704ad90dd9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:36:45 +0200 Subject: [PATCH 125/223] The symbol ! is now considered a token, even when near to other chars --- include/cli/cli.h | 3 +-- include/cli/detail/history.h | 4 ++-- include/cli/detail/split.h | 11 ++++++++++- test/test_split.cpp | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/include/cli/cli.h b/include/cli/cli.h index ba723f6..437e838 100644 --- a/include/cli/cli.h +++ b/include/cli/cli.h @@ -360,8 +360,8 @@ namespace cli void ExecFromHistory(unsigned index) { - const auto cmd = history.At(index); history.ForgetLatest(); + const auto cmd = history.At(index); Feed(cmd); } @@ -919,7 +919,6 @@ namespace cli try { - // global cmds check bool found = globalScopeMenu->ScanCmds(strs, *this); diff --git a/include/cli/detail/history.h b/include/cli/detail/history.h index c27ea8b..e8eb401 100644 --- a/include/cli/detail/history.h +++ b/include/cli/detail/history.h @@ -166,14 +166,14 @@ class History std::size_t IndexToId(std::size_t index) const { if (index > idOfOldest+buffer.size()-1) - throw std::out_of_range("Index not found in buffer"); + throw std::out_of_range("Index not found in history"); return idOfOldest + buffer.size() - 1 - index; } std::size_t IdToIndex(std::size_t id) const { if (id < idOfOldest || id > idOfOldest+buffer.size()-1) - throw std::out_of_range("Index not found in buffer"); + throw std::out_of_range("Index not found in history"); return idOfOldest + buffer.size() - 1 - id; } diff --git a/include/cli/detail/split.h b/include/cli/detail/split.h index fbd8686..cea4fe2 100644 --- a/include/cli/detail/split.h +++ b/include/cli/detail/split.h @@ -101,6 +101,10 @@ class Text state = State::escape; splitResult.emplace_back(""); } + else if (c == '!') + { + splitResult.emplace_back(1, c); + } else { state = State::word; @@ -114,6 +118,11 @@ class Text { state = State::space; } + else if (c == '!') + { + splitResult.emplace_back(1, c); + state = State::space; + } else if (c == '"' || c == '\'') { NewSentence(c); @@ -122,7 +131,7 @@ class Text { prev_state = state; state = State::escape; - } + } else { assert(!splitResult.empty()); diff --git a/test/test_split.cpp b/test/test_split.cpp index cb88398..8e04cd8 100644 --- a/test/test_split.cpp +++ b/test/test_split.cpp @@ -241,4 +241,39 @@ BOOST_AUTO_TEST_CASE(EscapedCases) BOOST_CHECK_EQUAL(strs[0], R"(foo\"bar)"); } +BOOST_AUTO_TEST_CASE(Symbols) +{ + VS strs; + + split(strs, "!foo"); // two words! + BOOST_CHECK_EQUAL(strs.size(), 2); + BOOST_CHECK_EQUAL(strs[0], "!"); + BOOST_CHECK_EQUAL(strs[1], "foo"); + + split(strs, " ! foo "); // two words + BOOST_CHECK_EQUAL(strs.size(), 2); + BOOST_CHECK_EQUAL(strs[0], "!"); + BOOST_CHECK_EQUAL(strs[1], "foo"); + + split(strs, "!42!69!"); // 5 words + BOOST_CHECK_EQUAL(strs.size(), 5); + BOOST_CHECK_EQUAL(strs[0], "!"); + BOOST_CHECK_EQUAL(strs[1], "42"); + BOOST_CHECK_EQUAL(strs[2], "!"); + BOOST_CHECK_EQUAL(strs[3], "69"); + BOOST_CHECK_EQUAL(strs[4], "!"); + + split(strs, " 38!42!69! 72 ! 33"); // 9 words + BOOST_CHECK_EQUAL(strs.size(), 9); + BOOST_CHECK_EQUAL(strs[0], "38"); + BOOST_CHECK_EQUAL(strs[1], "!"); + BOOST_CHECK_EQUAL(strs[2], "42"); + BOOST_CHECK_EQUAL(strs[3], "!"); + BOOST_CHECK_EQUAL(strs[4], "69"); + BOOST_CHECK_EQUAL(strs[5], "!"); + BOOST_CHECK_EQUAL(strs[6], "72"); + BOOST_CHECK_EQUAL(strs[7], "!"); + BOOST_CHECK_EQUAL(strs[8], "33"); +} + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 593d870a6ae5d853de86dd2bf2b8853625073ee3 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:32:17 +0200 Subject: [PATCH 126/223] Disable win test execution on CI test --- .github/workflows/unix_ci.yml | 80 +++++++++++++---------------------- 1 file changed, 30 insertions(+), 50 deletions(-) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/unix_ci.yml index eeb5d52..7d98707 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/unix_ci.yml @@ -9,56 +9,38 @@ jobs: fail-fast: false matrix: - os: - - ubuntu-20.04 - - ubuntu-latest - - macos-12 - compiler: - # you can specify the version after `-` like "llvm-13.0.0". - - llvm-13.0.0 - - clang++-14 - - gcc-11 - # - gcc-12 + os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-2022, windows-2019] + compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] - generator: - - "Ninja Multi-Config" - build_type: - - Release - - Debug - + build_type: [Release, Debug] exclude: - # mingw is determined by this author to be too buggy to support - - os: macos-12 - compiler: gcc-11 + # Exclude msvc on non-Windows platforms - os: ubuntu-20.04 - compiler: llvm-13.0.0 - - include: - # Add appropriate variables for gcov version required. This will intentionally break - # if you try to use a compiler that does not have gcov set - - compiler: gcc-11 - gcov_executable: gcov - - compiler: llvm-13.0.0 - gcov_executable: "llvm-cov gcov" - - # Set up preferred package generators, for given build configurations - - build_type: Release - package_generator: TBZ2 - - - os: windows-2022 compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Debug - - os: windows-2022 + - os: ubuntu-latest compiler: msvc - generator: "Visual Studio 17 2022" - build_type: Release - package_generator: ZIP - - + - os: macos-12 + compiler: msvc + # Exclude gcc on Windows platforms + - os: windows-2022 + compiler: gcc-11 + - os: windows-2019 + compiler: gcc-11 + # Exclude gcc on mac platforms + - os: macos-12 + compiler: gcc-11 + # Exclude llvm on Windows platforms + - os: windows-2022 + compiler: llvm-13.0.0 + - os: windows-2019 + compiler: llvm-13.0.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + + - name: Set up MSVC + if: runner.os == 'Windows' + uses: ilammy/msvc-dev-cmd@v1 - name: Setup Cpp uses: aminya/setup-cpp@v1 @@ -92,10 +74,6 @@ jobs: choco install ninja choco install boost-msvc-14.1 # # Download and extract Asio - # Invoke-WebRequest -Uri https://sourceforge.net/projects/asio/files/asio/1.18.2%20%28Stable%29/asio-1.18.2.zip -OutFile asio.zip - # Expand-Archive -Path asio.zip -DestinationPath $env:USERPROFILE\asio - # # Set ASIO_INCLUDE_DIR environment variable - # echo "ASIO_INCLUDE_DIR=$env:USERPROFILE\asio\asio-1.18.2\include" >> $env:GITHUB_ENV curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip move asio-asio-1-18-2 asio @@ -103,12 +81,13 @@ jobs: - name: Configure CMake - Unix if: runner.os != 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - name: Configure CMake - Windows + # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include - name: Build run: | @@ -117,7 +96,8 @@ jobs: cmake --build ./build --config ${{matrix.build_type}} - name: run tests - # if: runner.os != 'Windows' + # on windows test_suite throws an exception, but only on the CI environment! + if: runner.os != 'Windows' # working-directory: ./build/test/${{matrix.build_type}} working-directory: ./build run: | From 94c4a17e4f87f90b4876ba17eee62ea75ad038ea Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:58:39 +0200 Subject: [PATCH 127/223] Only one CI test file --- .github/workflows/{unix_ci.yml => ci.yml} | 6 +++--- .github/workflows/{win_ci.yml => win_ci.yml.disabled} | 0 README.md | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) rename .github/workflows/{unix_ci.yml => ci.yml} (97%) rename .github/workflows/{win_ci.yml => win_ci.yml.disabled} (100%) diff --git a/.github/workflows/unix_ci.yml b/.github/workflows/ci.yml similarity index 97% rename from .github/workflows/unix_ci.yml rename to .github/workflows/ci.yml index 7d98707..1199a7b 100644 --- a/.github/workflows/unix_ci.yml +++ b/.github/workflows/ci.yml @@ -38,9 +38,9 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up MSVC - if: runner.os == 'Windows' - uses: ilammy/msvc-dev-cmd@v1 + # - name: Set up MSVC + # if: runner.os == 'Windows' + # uses: ilammy/msvc-dev-cmd@v1 - name: Setup Cpp uses: aminya/setup-cpp@v1 diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml.disabled similarity index 100% rename from .github/workflows/win_ci.yml rename to .github/workflows/win_ci.yml.disabled diff --git a/README.md b/README.md index 8c72e30..0ee2c43 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg) +[![CI of Cli](https://github.com/daniele77/cli/actions/workflows/ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/ci.yml) [![CodeQL](https://github.com/daniele77/cli/actions/workflows/codeql.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/codeql.yml) +[:heart: Sponsor](https://github.com/sponsors/daniele77) # cli @@ -10,9 +11,6 @@ A cross-platform header only C++14 library for interactive command line interfac ![demo_telnet_session](https://user-images.githubusercontent.com/5451767/51046612-d1dadc00-15c6-11e9-83c2-beadb3593348.gif) -![C/C++ CI of Cli](https://github.com/daniele77/cli/workflows/C/C++%20CI%20of%20Cli/badge.svg) - -[:heart: Sponsor](https://github.com/sponsors/daniele77) **IMPORTANT: Breaking API changes!** Version 2.0 of `cli` has made breaking changes in order to add more functionality. To migrate your application to new `cli` version, see the section From 2363f7966f1ab41578f198d1f47ddc88b81a7d4f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 18 Oct 2024 23:06:07 +0200 Subject: [PATCH 128/223] Change CI name --- .github/workflows/ci.yml | 2 +- README.md | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1199a7b..ace6608 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Unix CI +name: CI on: [push,pull_request] diff --git a/README.md b/README.md index 0ee2c43..a400f86 100644 --- a/README.md +++ b/README.md @@ -11,11 +11,6 @@ A cross-platform header only C++14 library for interactive command line interfac ![demo_telnet_session](https://user-images.githubusercontent.com/5451767/51046612-d1dadc00-15c6-11e9-83c2-beadb3593348.gif) - -**IMPORTANT: Breaking API changes!** Version 2.0 of `cli` has made breaking changes in order to add more functionality. -To migrate your application to new `cli` version, see the section -"Async programming and Schedulers" of this file, or the examples that come with the library. - ## Features * Header only From f45cb4535b44fea9781abdda74dc41721ab25696 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 23 Oct 2024 09:21:30 +0200 Subject: [PATCH 129/223] Add new test case for tokenizer --- CHANGELOG.md | 1 + README.md | 3 +++ test/test_split.cpp | 8 ++++++++ 3 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42c5c0c..085641f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) - Enable Keyboard Handling in Command Handlers on Linux Platform (issue [#239](https://github.com/daniele77/cli/issues/239)) - Add clear screen command using ctrl + L (issue [#229](https://github.com/daniele77/cli/issues/229)) + - Add history view and execute an history command with bang + id (issue [#235](https://github.com/daniele77/cli/issues/235)) ## [2.1.0] - 2023-06-29 diff --git a/README.md b/README.md index a400f86..c48b9a5 100644 --- a/README.md +++ b/README.md @@ -174,9 +174,12 @@ This indicates you're in the root menu. ### Commands in any menu - `help`: Prints a list of available commands with descriptions. +- `history`: Displays the list of previously entered commands. +- `exit`: Terminates the CLI application. - **Command execution:** - **Current menu:** Enter the name of a command available in the current menu to execute it. - **Submenu (full path):** Specify the complete path (separated by spaces) to a command within a submenu to execute it. + - **History execution:** Use `!` followed by the identifier of a history item to execute that command again. ### Autocompletion diff --git a/test/test_split.cpp b/test/test_split.cpp index 8e04cd8..167cb6d 100644 --- a/test/test_split.cpp +++ b/test/test_split.cpp @@ -274,6 +274,14 @@ BOOST_AUTO_TEST_CASE(Symbols) BOOST_CHECK_EQUAL(strs[6], "72"); BOOST_CHECK_EQUAL(strs[7], "!"); BOOST_CHECK_EQUAL(strs[8], "33"); + + split(strs, R"( 38!"42!69"! "72 ! 33" )"); // 5 words + BOOST_CHECK_EQUAL(strs.size(), 5); + BOOST_CHECK_EQUAL(strs[0], "38"); + BOOST_CHECK_EQUAL(strs[1], "!"); + BOOST_CHECK_EQUAL(strs[2], "42!69"); + BOOST_CHECK_EQUAL(strs[3], "!"); + BOOST_CHECK_EQUAL(strs[4], "72 ! 33"); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 8eceadcbc0fe99843a344409074269887d7b71bd Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 24 Oct 2024 16:29:01 +0200 Subject: [PATCH 130/223] Add boost minimum version to CMakeLists --- CMakeLists.txt | 4 ++-- README.md | 2 +- test/CMakeLists.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8969743..69afd69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,7 @@ endif() if (CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows - find_package(Boost 1.55 REQUIRED COMPONENTS system) + find_package(Boost 1.66 REQUIRED COMPONENTS system) endif() if (CLI_UseStandaloneAsio) @@ -155,4 +155,4 @@ if(NOT CMAKE_SKIP_INSTALL_RULES) FILES "${CMAKE_CURRENT_BINARY_DIR}/cli.pc" DESTINATION ${PKGCONFIG_INSTALL_DIR} ) -endif() \ No newline at end of file +endif() diff --git a/README.md b/README.md index c48b9a5..e31d83d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ A cross-platform header only C++14 library for interactive command line interfac The library has no dependencies if you don't need remote sessions. -The library depends on asio (either the standalone version or the boost version) +The library depends on asio (either the standalone version or the boost version >= 1.66) *only* to provide telnet server (i.e., remote sessions). ## Installation diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d0942e0..669b777 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,7 +37,7 @@ set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows # finds boost, triggers an error otherwise -find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework) +find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) @@ -66,7 +66,7 @@ target_include_directories(test_suite SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) # indicates the shared library variant target_compile_definitions(test_suite PRIVATE "BOOST_TEST_DYN_LINK=1") # indicates the link paths -target_link_libraries(test_suite ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} standalone_asio_test cli::cli) +target_link_libraries(test_suite ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} Boost::system standalone_asio_test cli::cli) # declares a test with our executable add_test(NAME cli_test COMMAND test_suite) From 20e56f76954ee65d7f0f44215e2792c8b6681e5a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 25 Oct 2024 23:23:00 +0200 Subject: [PATCH 131/223] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index e31d83d..46e8926 100644 --- a/README.md +++ b/README.md @@ -144,9 +144,7 @@ E.g., from a visual studio console, use one of the following commands: ### Visual Studio solution -Currently, the VS solution compiles the examples only with the BOOST dependency. - -Set the environment variable BOOST. Then, open the file +Set the environment variables BOOST and/or ASIO. Then, open the file `cli/examples/examples.sln` ## Compilation of the Doxygen documentation From 80541c47bc4c7a6baa205136ca558860cb5e61af Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 25 Oct 2024 23:38:32 +0200 Subject: [PATCH 132/223] Bump version --- CHANGELOG.md | 8 ++++---- CMakeLists.txt | 2 +- doc/doxy/Doxyfile | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 085641f..38d4e8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,16 +3,16 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [2.2.0] - 2024-10-25 - - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) + - Add clear screen command using ctrl + L (issue [#229](https://github.com/daniele77/cli/issues/229)) + - Add history view and execute an history command with bang + id (issue [#235](https://github.com/daniele77/cli/issues/235)) - Custom handler for wrong commands (issue [#223](https://github.com/daniele77/cli/issues/223)) - Parent menus does not chain (issue [#234](https://github.com/daniele77/cli/issues/234)) - Parent menu shortcut (issue [#233](https://github.com/daniele77/cli/issues/233)) - Integer overflow warning detected by clang++ (issue [#236](https://github.com/daniele77/cli/issues/236)) - Enable Keyboard Handling in Command Handlers on Linux Platform (issue [#239](https://github.com/daniele77/cli/issues/239)) - - Add clear screen command using ctrl + L (issue [#229](https://github.com/daniele77/cli/issues/229)) - - Add history view and execute an history command with bang + id (issue [#235](https://github.com/daniele77/cli/issues/235)) + - Fix issue with remote session on ARM platforms (issue [#220](https://github.com/daniele77/cli/issues/220)) ## [2.1.0] - 2023-06-29 diff --git a/CMakeLists.txt b/CMakeLists.txt index 69afd69..4ca6aa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ cmake_minimum_required(VERSION 3.8) project( cli - VERSION 2.1.0 + VERSION 2.2.0 # DESCRIPTION "A library for interactive command line interfaces in modern C++" LANGUAGES CXX ) diff --git a/doc/doxy/Doxyfile b/doc/doxy/Doxyfile index d487e53..4ec97f1 100644 --- a/doc/doxy/Doxyfile +++ b/doc/doxy/Doxyfile @@ -29,7 +29,7 @@ #--------------------------------------------------------------------------- PROJECT_NAME = "Interactive CLI" -PROJECT_NUMBER = 2.1 +PROJECT_NUMBER = 2.2 #--------------------------------------------------------------------------- FULL_PATH_NAMES = NO #--------------------------------------------------------------------------- From 0476de20b02a4352426056110cdcdb19daf8f020 Mon Sep 17 00:00:00 2001 From: Elyorbek Kholikov Date: Fri, 13 Dec 2024 16:42:44 +0500 Subject: [PATCH 133/223] Fix mutex initialization issue in cli library --- include/cli/detail/linuxkeyboard.h | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index 8fa2401..b26601c 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -100,14 +100,13 @@ class InputSource }; // - - class LinuxKeyboard : public InputDevice { public: explicit LinuxKeyboard(Scheduler& _scheduler) : InputDevice(_scheduler), enabled(false), + closing(false), servant( [this]() noexcept { Read(); } ) { ActivateInput(); @@ -116,10 +115,17 @@ class LinuxKeyboard : public InputDevice { ToStandardMode(); is.Stop(); + + { + std::lock_guard lock(mtx); + closing = true; // Signal to stop + cv.notify_one(); // Wake up the thread if waiting + } + servant.join(); } void ActivateInput() override - { + { ToManualMode(); std::lock_guard lock(mtx); enabled = true; @@ -142,7 +148,11 @@ class LinuxKeyboard : public InputDevice { { std::unique_lock lock(mtx); - cv.wait(lock, [this]{ return enabled; }); // release mtx, suspend thread execution until enabled becomes true + cv.wait(lock, [this]{ return enabled || closing; }); // release mtx, suspend thread execution until enabled becomes true + if (closing) + { + break; + } } auto k = Get(); Notify(k); @@ -226,12 +236,13 @@ class LinuxKeyboard : public InputDevice } bool enabled; + bool closing; termios oldt; termios newt; InputSource is; - std::thread servant; std::mutex mtx; std::condition_variable cv; + std::thread servant; }; } // namespace detail @@ -239,3 +250,4 @@ class LinuxKeyboard : public InputDevice #endif // CLI_DETAIL_LINUXKEYBOARD_H_ + From 45220f5eda659b9e301371c0b7b1027638f079f6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 11 Apr 2025 09:32:29 +0200 Subject: [PATCH 134/223] Remove unneeded closing flag in LinuxKeyboard --- include/cli/detail/linuxkeyboard.h | 36 +++++++++++++----------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/include/cli/detail/linuxkeyboard.h b/include/cli/detail/linuxkeyboard.h index b26601c..17b40e1 100644 --- a/include/cli/detail/linuxkeyboard.h +++ b/include/cli/detail/linuxkeyboard.h @@ -100,36 +100,26 @@ class InputSource }; // + class LinuxKeyboard : public InputDevice { public: explicit LinuxKeyboard(Scheduler& _scheduler) : InputDevice(_scheduler), enabled(false), - closing(false), servant( [this]() noexcept { Read(); } ) { - ActivateInput(); + ActivateInputImpl(); } ~LinuxKeyboard() override { ToStandardMode(); is.Stop(); - - { - std::lock_guard lock(mtx); - closing = true; // Signal to stop - cv.notify_one(); // Wake up the thread if waiting - } - servant.join(); } void ActivateInput() override - { - ToManualMode(); - std::lock_guard lock(mtx); - enabled = true; - cv.notify_one(); + { + ActivateInputImpl(); } void DeactivateInput() override { @@ -137,8 +127,17 @@ class LinuxKeyboard : public InputDevice std::lock_guard lock(mtx); enabled = false; } + + private: -private: + // we need a private non virtual method to call from the constructor + void ActivateInputImpl() + { + ToManualMode(); + std::lock_guard lock(mtx); + enabled = true; + cv.notify_one(); + } void Read() noexcept { @@ -148,11 +147,7 @@ class LinuxKeyboard : public InputDevice { { std::unique_lock lock(mtx); - cv.wait(lock, [this]{ return enabled || closing; }); // release mtx, suspend thread execution until enabled becomes true - if (closing) - { - break; - } + cv.wait(lock, [this]{ return enabled; }); // release mtx, suspend thread execution until enabled becomes true } auto k = Get(); Notify(k); @@ -236,7 +231,6 @@ class LinuxKeyboard : public InputDevice } bool enabled; - bool closing; termios oldt; termios newt; InputSource is; From be98ce1615ec62cc53889e2ab8b1f0790a4d21ff Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 12 Apr 2025 11:51:46 +0200 Subject: [PATCH 135/223] Update ci.yml fix for clang++-14 --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ace6608..6920f59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,9 @@ jobs: if: runner.os != 'Windows' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + if [[ "${{ matrix.compiler }}" == "clang++-14" && "${{ runner.os }}" == "Linux" ]]; then + cmake -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++" -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++" -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + fi - name: Configure CMake - Windows # windows need asio library path From 478ab51d6cd33c68045a8de50059bcc6d7f0e63e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 12 Apr 2025 12:35:32 +0200 Subject: [PATCH 136/223] Update CI t use macos 13 --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6920f59..7097a53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-20.04, ubuntu-latest, macos-12, windows-2022, windows-2019] + os: [ubuntu-20.04, ubuntu-latest, macos-13, windows-2022, windows-2019] compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d4e8d..f8b7faa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + + - Fix mutex initialization issue in cli library (pr [#249](https://github.com/daniele77/cli/pull/249)) + ## [2.2.0] - 2024-10-25 - Add clear screen command using ctrl + L (issue [#229](https://github.com/daniele77/cli/issues/229)) From 44b08aa05ae5d249be4ec6037447ad49f3d96e45 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 12 Apr 2025 16:59:15 +0200 Subject: [PATCH 137/223] Update ci --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7097a53..25eb520 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,9 +82,6 @@ jobs: if: runner.os != 'Windows' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - if [[ "${{ matrix.compiler }}" == "clang++-14" && "${{ runner.os }}" == "Linux" ]]; then - cmake -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++" -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++" -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - fi - name: Configure CMake - Windows # windows need asio library path From 26f049538cf33ad5575e58ef7d584aaedd6b434e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 12 Apr 2025 18:12:33 +0200 Subject: [PATCH 138/223] Fix timer in boostasio_nonowner_iocontext.cpp example --- examples/boostasio_nonowner_iocontext.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/boostasio_nonowner_iocontext.cpp b/examples/boostasio_nonowner_iocontext.cpp index b3a214a..2ae996b 100644 --- a/examples/boostasio_nonowner_iocontext.cpp +++ b/examples/boostasio_nonowner_iocontext.cpp @@ -114,11 +114,8 @@ int main() { // main application that creates an asio io_context and uses it IoContext iocontext; - boost::asio::deadline_timer timer( - iocontext, - boost::posix_time::seconds(5) - ); - timer.async_wait([](const boost::system::error_code&){ cout << "Timer expired!\n"; }); + boost::asio::steady_timer timer(iocontext, std::chrono::seconds(5)); + timer.async_wait([](const error_code&){ cout << "Timer expired!\n"; }); // cli setup UserInterface interface(iocontext); From 9f4e1f5369c4e5563e967b444342bafde03fc79b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 07:48:57 +0200 Subject: [PATCH 139/223] Fix macos CI link --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25eb520..e10d4d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,7 +19,7 @@ jobs: compiler: msvc - os: ubuntu-latest compiler: msvc - - os: macos-12 + - os: macos-13 compiler: msvc # Exclude gcc on Windows platforms - os: windows-2022 @@ -27,7 +27,7 @@ jobs: - os: windows-2019 compiler: gcc-11 # Exclude gcc on mac platforms - - os: macos-12 + - os: macos-13 compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 @@ -82,6 +82,9 @@ jobs: if: runner.os != 'Windows' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + if [[ "${{ matrix.compiler }}" == "llvm-13.0.0" && "${{ runner.os }}" == "Linux" ]]; then + cmake -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++" -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++" -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + fi - name: Configure CMake - Windows # windows need asio library path From df4b38505b56fa629513a2e38f3dae686a339f3b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:09:16 +0200 Subject: [PATCH 140/223] CI update to ubuntu 22.04 --- .github/workflows/ci.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e10d4d4..d30169b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,13 +9,13 @@ jobs: fail-fast: false matrix: - os: [ubuntu-20.04, ubuntu-latest, macos-13, windows-2022, windows-2019] + os: [ubuntu-22.04, ubuntu-latest, macos-13, windows-2022, windows-2019] compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] exclude: # Exclude msvc on non-Windows platforms - - os: ubuntu-20.04 + - os: ubuntu-22.04 compiler: msvc - os: ubuntu-latest compiler: msvc @@ -82,9 +82,6 @@ jobs: if: runner.os != 'Windows' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - if [[ "${{ matrix.compiler }}" == "llvm-13.0.0" && "${{ runner.os }}" == "Linux" ]]; then - cmake -DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -stdlib=libc++" -DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++" -DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++" -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - fi - name: Configure CMake - Windows # windows need asio library path From 5e5cdcd7ef950c1f6f0770157bad59cbd4ed70bb Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:12:04 +0200 Subject: [PATCH 141/223] CI update to clang latest --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d30169b..fe59f2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: matrix: os: [ubuntu-22.04, ubuntu-latest, macos-13, windows-2022, windows-2019] - compiler: [llvm-13.0.0, clang++-14, gcc-11, msvc] + compiler: [llvm-13.0.0, clang++-latest, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] exclude: @@ -36,7 +36,7 @@ jobs: compiler: llvm-13.0.0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # - name: Set up MSVC # if: runner.os == 'Windows' @@ -77,7 +77,7 @@ jobs: curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip move asio-asio-1-18-2 asio - + - name: Configure CMake - Unix if: runner.os != 'Windows' run: | From a5bbdd64c0232478bb1c2be808a6184eb33e07db Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:55:11 +0200 Subject: [PATCH 142/223] CI update to clang 14 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe59f2b..c4e6130 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: matrix: os: [ubuntu-22.04, ubuntu-latest, macos-13, windows-2022, windows-2019] - compiler: [llvm-13.0.0, clang++-latest, gcc-11, msvc] + compiler: [llvm-17.0.2, clang++-14, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] exclude: @@ -31,9 +31,9 @@ jobs: compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 - compiler: llvm-13.0.0 + compiler: llvm-17.0.2 - os: windows-2019 - compiler: llvm-13.0.0 + compiler: llvm-17.0.2 steps: - uses: actions/checkout@v4 From de031ba71e795fcd4a73fec63aa5746c8904492b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 12:45:31 +0200 Subject: [PATCH 143/223] CI update to clang 14 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4e6130..742be21 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: matrix: os: [ubuntu-22.04, ubuntu-latest, macos-13, windows-2022, windows-2019] - compiler: [llvm-17.0.2, clang++-14, gcc-11, msvc] + compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] exclude: From 9b0b99f746fa9de3f5ad78a695b5d650738e0676 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 14 Apr 2025 15:31:17 +0200 Subject: [PATCH 144/223] CI remove ubuntu-latest --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 742be21..9dee47f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, ubuntu-latest, macos-13, windows-2022, windows-2019] + os: [ubuntu-22.04, macos-13, windows-2022, windows-2019] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] From 8c2defa6de27a2ff2814df0ed1603f85bfe56961 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 2 Oct 2025 19:36:48 +0200 Subject: [PATCH 145/223] Update CI to macos-15 --- .github/workflows/ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9dee47f..50289c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, windows-2022, windows-2019] + os: [ubuntu-22.04, macos-15, windows-2022, windows-2019] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] @@ -17,9 +17,7 @@ jobs: # Exclude msvc on non-Windows platforms - os: ubuntu-22.04 compiler: msvc - - os: ubuntu-latest - compiler: msvc - - os: macos-13 + - os: macos-15 compiler: msvc # Exclude gcc on Windows platforms - os: windows-2022 @@ -27,7 +25,7 @@ jobs: - os: windows-2019 compiler: gcc-11 # Exclude gcc on mac platforms - - os: macos-13 + - os: macos-15 compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 From 7e174ea52c48a9fa9e1cf2c834abc74743cfb375 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:51:35 +0200 Subject: [PATCH 146/223] Enhance CI workflow for macOS: separate dependency installation and configure CMake with BOOST_ROOT --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50289c0..a41d776 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,10 +62,15 @@ jobs: run: | sudo apt-get -y update sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev + - name: setup dependencies - macOS if: runner.os == 'macOS' run: | - brew install ninja boost asio + brew install ninja + brew install boost + echo "BOOST_ROOT=$(brew --prefix boost)" >> $GITHUB_ENV + brew install asio + - name: setup dependencies - Windows if: runner.os == 'Windows' run: | @@ -76,11 +81,16 @@ jobs: tar -xf asio.zip move asio-asio-1-18-2 asio - - name: Configure CMake - Unix - if: runner.os != 'Windows' + - name: Configure CMake - Unix (Linux) + if: runner.os == 'Linux' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + - name: Configure CMake - macOS + if: runner.os == 'macOS' + run: | + cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DBOOST_ROOT=$BOOST_ROOT -DBoost_NO_SYSTEM_PATHS=ON -DBoost_NO_BOOST_CMAKE=ON + - name: Configure CMake - Windows # windows need asio library path if: runner.os == 'Windows' From a26cbfa188d70a823f8455bfe9af54b366bc601c Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:06:20 +0200 Subject: [PATCH 147/223] Update CI configuration to use macOS 14 and streamline CMake setup --- .github/workflows/ci.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a41d776..b3c4ac6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, macos-15, windows-2022, windows-2019] + os: [ubuntu-22.04, macos-14, windows-2022, windows-2019] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] @@ -17,7 +17,7 @@ jobs: # Exclude msvc on non-Windows platforms - os: ubuntu-22.04 compiler: msvc - - os: macos-15 + - os: macos-14 compiler: msvc # Exclude gcc on Windows platforms - os: windows-2022 @@ -25,7 +25,7 @@ jobs: - os: windows-2019 compiler: gcc-11 # Exclude gcc on mac platforms - - os: macos-15 + - os: macos-14 compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 @@ -68,7 +68,6 @@ jobs: run: | brew install ninja brew install boost - echo "BOOST_ROOT=$(brew --prefix boost)" >> $GITHUB_ENV brew install asio - name: setup dependencies - Windows @@ -81,16 +80,11 @@ jobs: tar -xf asio.zip move asio-asio-1-18-2 asio - - name: Configure CMake - Unix (Linux) - if: runner.os == 'Linux' + - name: Configure CMake - Unix + if: runner.os != 'Windows' run: | cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON - - name: Configure CMake - macOS - if: runner.os == 'macOS' - run: | - cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DBOOST_ROOT=$BOOST_ROOT -DBoost_NO_SYSTEM_PATHS=ON -DBoost_NO_BOOST_CMAKE=ON - - name: Configure CMake - Windows # windows need asio library path if: runner.os == 'Windows' From bc5829ee99514866d3acbd66d398e222258e264f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 25 Nov 2025 09:20:34 +0100 Subject: [PATCH 148/223] Update CI configuration to use Windows 2024 instead of Windows 2019 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3c4ac6..9ff7fa1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, macos-14, windows-2022, windows-2019] + os: [ubuntu-22.04, macos-14, windows-2022, windows-2024] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] @@ -22,7 +22,7 @@ jobs: # Exclude gcc on Windows platforms - os: windows-2022 compiler: gcc-11 - - os: windows-2019 + - os: windows-2024 compiler: gcc-11 # Exclude gcc on mac platforms - os: macos-14 @@ -30,7 +30,7 @@ jobs: # Exclude llvm on Windows platforms - os: windows-2022 compiler: llvm-17.0.2 - - os: windows-2019 + - os: windows-2024 compiler: llvm-17.0.2 steps: From b13cc49c1bbc2c67ef4985e238d38942744a9d0b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:50:15 +0100 Subject: [PATCH 149/223] Update CI configuration to use Windows 2025 and enhance Boost installation --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ff7fa1..1ade988 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, macos-14, windows-2022, windows-2024] + os: [ubuntu-22.04, macos-14, windows-2022, windows-2025] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] @@ -22,7 +22,7 @@ jobs: # Exclude gcc on Windows platforms - os: windows-2022 compiler: gcc-11 - - os: windows-2024 + - os: windows-2025 compiler: gcc-11 # Exclude gcc on mac platforms - os: macos-14 @@ -30,7 +30,7 @@ jobs: # Exclude llvm on Windows platforms - os: windows-2022 compiler: llvm-17.0.2 - - os: windows-2024 + - os: windows-2025 compiler: llvm-17.0.2 steps: @@ -67,7 +67,7 @@ jobs: if: runner.os == 'macOS' run: | brew install ninja - brew install boost + brew install boost boost-system brew install asio - name: setup dependencies - Windows From 753d3839a887daa9e6aca0e376bf0d639981dc3e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:14:35 +0100 Subject: [PATCH 150/223] Refactor CI configuration: streamline Boost installation and enhance CMake options for better compatibility --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ade988..ae8ce66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: if: runner.os == 'macOS' run: | brew install ninja - brew install boost boost-system + brew install boost brew install asio - name: setup dependencies - Windows @@ -83,13 +83,33 @@ jobs: - name: Configure CMake - Unix if: runner.os != 'Windows' run: | - cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake \ + -S . \ + -B ./build \ + -G "Ninja Multi-Config" \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=ON \ + -DBOOST_ERROR_CODE_HEADER_ONLY=ON \ + -DBOOST_SYSTEM_NO_LIB=ON - name: Configure CMake - Windows # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include + cmake \ + -S . \ + -B ./build \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=ON \ + -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include \ + -DBOOST_ERROR_CODE_HEADER_ONLY=ON \ + -DBOOST_SYSTEM_NO_LIB=ON - name: Build run: | From 5e469e711973c18e5b4dd9ad4e5b1b8d2d662663 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 25 Nov 2025 17:56:59 +0100 Subject: [PATCH 151/223] Update CMake configuration: require CMake 3.12, enhance Boost integration, and streamline Asio handling --- .github/workflows/ci.yml | 1 + CMakeLists.txt | 76 ++++++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae8ce66..9d532e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,6 +98,7 @@ jobs: - name: Configure CMake - Windows # windows need asio library path if: runner.os == 'Windows' + shell: bash run: | cmake \ -S . \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ca6aa6..9993840 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.12) project( cli @@ -64,46 +64,60 @@ if(WIN32) endmacro() get_WIN32_WINNT(ver) - add_definitions(-D_WIN32_WINNT=${ver}) + # add_definitions(-D_WIN32_WINNT=${ver}) endif() -if (CLI_UseBoostAsio) - set(Boost_NO_BOOST_CMAKE ON) - add_definitions( -DBOOST_ALL_NO_LIB ) # for windows - find_package(Boost 1.66 REQUIRED COMPONENTS system) +find_package(Threads REQUIRED) + +# ---------------------------- +# Boost +# ---------------------------- +if(CLI_UseBoostAsio) + # Create a dummy INTERFACE library to carry Boost headers + add_library(BoostSystem INTERFACE) + target_compile_definitions(BoostSystem INTERFACE + BOOST_ERROR_CODE_HEADER_ONLY + BOOST_SYSTEM_NO_LIB + ) + + find_package(Boost REQUIRED) # without COMPONENTS, header-only usage + target_include_directories(BoostSystem SYSTEM INTERFACE ${Boost_INCLUDE_DIRS}) + + install(TARGETS BoostSystem EXPORT cliTargets) endif() -if (CLI_UseStandaloneAsio) +# ---------------------------- +# Standalone Asio +# ---------------------------- +if(CLI_UseStandaloneAsio) find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) endif() -find_package(Threads REQUIRED) - -# Add Library +# ---------------------------- +# Main CLI interface library +# ---------------------------- add_library(cli INTERFACE) -# Add target alias add_library(cli::cli ALIAS cli) target_include_directories(cli INTERFACE - $ - $ + $ + $ ) target_link_libraries(cli INTERFACE Threads::Threads) -if (CLI_UseBoostAsio) - target_link_libraries(cli INTERFACE Boost::system) - target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED=1) + +if(CLI_UseBoostAsio) + target_link_libraries(cli INTERFACE BoostSystem) + target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED) endif() -if (CLI_UseStandaloneAsio) - add_library(standalone_asio INTERFACE IMPORTED) - target_include_directories(standalone_asio SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) - target_link_libraries(standalone_asio INTERFACE Threads::Threads) - target_link_libraries(cli INTERFACE standalone_asio) - # alternative way: - # target_include_directories(cli SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) +if(CLI_UseStandaloneAsio) + add_library(standalone_asio INTERFACE IMPORTED) + target_include_directories(standalone_asio SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) + target_link_libraries(standalone_asio INTERFACE Threads::Threads) + target_link_libraries(cli INTERFACE standalone_asio) endif() if(NOT DEFINED CMAKE_CXX_STANDARD) @@ -111,18 +125,24 @@ if(NOT DEFINED CMAKE_CXX_STANDARD) endif() target_compile_features(cli INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) +# ---------------------------- # Examples -if (CLI_BuildExamples) +# ---------------------------- +if(CLI_BuildExamples) add_subdirectory(examples) endif() +# ---------------------------- # Tests -if (CLI_BuildTests) +# ---------------------------- +if(CLI_BuildTests) enable_testing() add_subdirectory(test) endif() +# ---------------------------- # Install +# ---------------------------- if(NOT CMAKE_SKIP_INSTALL_RULES) install(DIRECTORY include/cli DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) @@ -138,11 +158,7 @@ if(NOT CMAKE_SKIP_INSTALL_RULES) ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig CACHE PATH "Installation directory for pkg-config (cli.pc) file" ) - configure_file( - "cli.pc.in" - "cli.pc" - @ONLY - ) + configure_file("cli.pc.in" "cli.pc" @ONLY) install(TARGETS cli EXPORT cliTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(EXPORT cliTargets FILE cliTargets.cmake NAMESPACE cli:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cli) From 69781e73480b2ad0a9929a4a546fe6aaffdfd85e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 26 Nov 2025 19:29:11 +0100 Subject: [PATCH 152/223] Add windows_2025 and remove macos from CI github actions --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3c4ac6..38835f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,8 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, macos-14, windows-2022, windows-2019] + # os: [ubuntu-22.04, macos-14, windows-2022, windows-2025] + os: [ubuntu-22.04, windows-2022, windows-2025] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] @@ -22,7 +23,7 @@ jobs: # Exclude gcc on Windows platforms - os: windows-2022 compiler: gcc-11 - - os: windows-2019 + - os: windows-2025 compiler: gcc-11 # Exclude gcc on mac platforms - os: macos-14 @@ -30,7 +31,7 @@ jobs: # Exclude llvm on Windows platforms - os: windows-2022 compiler: llvm-17.0.2 - - os: windows-2019 + - os: windows-2025 compiler: llvm-17.0.2 steps: From 8d401f1cbcec7304d71d101abe123a2dd275c37b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 26 Nov 2025 20:26:10 +0100 Subject: [PATCH 153/223] Addd macos CI file --- .github/workflows/{ci.yml => ci.yml.disabled} | 0 .github/workflows/macos_ci.yml | 56 +++++++++++++++++++ 2 files changed, 56 insertions(+) rename .github/workflows/{ci.yml => ci.yml.disabled} (100%) create mode 100644 .github/workflows/macos_ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml.disabled similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/ci.yml.disabled diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml new file mode 100644 index 0000000..5b4ac7e --- /dev/null +++ b/.github/workflows/macos_ci.yml @@ -0,0 +1,56 @@ +name: CI + +on: [push,pull_request] + +jobs: + Test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + + matrix: + os: [macos-1] + compiler: [llvm-17.0.2, clang++-15] + standard: [14, 17, 20, 23] + build_type: [Release, Debug] + + steps: + - uses: actions/checkout@v4 + + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + compiler: ${{ matrix.compiler }} + vcvarsall: ${{ contains(matrix.os, 'windows' )}} + + cmake: true + ninja: true + vcpkg: false + ccache: true + clangtidy: true + + cppcheck: true + + gcovr: true + opencppcoverage: true + + - name: setup dependencies + run: | + brew install ninja + brew install boost + brew install asio + + - name: Configure CMake + run: | + cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + + - name: Build + run: | + cmake --build ./build --config ${{matrix.build_type}} + + - name: run test + working-directory: ./build + run: | + # cd /home/runner/work/cli/cli/build/test/ + # ./test_suite + ctest -C ${{matrix.build_type}} --output-on-failure From a663d1966411eefe1ebbd4113b881163442410b2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 07:37:21 +0100 Subject: [PATCH 154/223] Fix macos version in CI script --- .github/workflows/macos_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 5b4ac7e..f1bc36e 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [macos-1] + os: [macos-14] compiler: [llvm-17.0.2, clang++-15] standard: [14, 17, 20, 23] build_type: [Release, Debug] From ebf06fe9ab18515bb51f418ffcb59825aab9edcc Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:15:41 +0100 Subject: [PATCH 155/223] Refactor macOS CI workflow: enhance CMake configuration and streamline build process --- .github/workflows/macos_ci.yml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index f1bc36e..5aa0c1f 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -15,13 +15,14 @@ jobs: build_type: [Release, Debug] steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 - name: Setup Cpp uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows' )}} + vcvarsall: false cmake: true ninja: true @@ -36,17 +37,28 @@ jobs: - name: setup dependencies run: | + brew update brew install ninja brew install boost brew install asio - name: Configure CMake run: | - cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build \ + -G Ninja \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=ON \ + -DBOOST_ROOT=$BOOST_ROOT \ + -DBOOST_INCLUDEDIR=$BOOST_ROOT/include \ + -DBOOST_LIBRARYDIR=$BOOST_ROOT/lib \ + -DBoost_NO_BOOST_CMAKE=ON - name: Build run: | - cmake --build ./build --config ${{matrix.build_type}} + cmake --build ./build --config ${{matrix.build_type}} --parallel $(sysctl -n hw.logicalcpu) - name: run test working-directory: ./build From 8e12f6b0eebff77014577e8fc908a607f6c11dbe Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:21:40 +0100 Subject: [PATCH 156/223] Update macOS CI workflow to install Boost from source --- .github/workflows/macos_ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 5aa0c1f..328b535 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -39,7 +39,7 @@ jobs: run: | brew update brew install ninja - brew install boost + brew install boost --build-from-source brew install asio - name: Configure CMake From d930fef163f6a393de9fb0caf85762e133a937ee Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:38:43 +0100 Subject: [PATCH 157/223] Update macOS CI workflow: install Boost without building from source and adjust CMake configuration --- .github/workflows/macos_ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 328b535..e399fc0 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -39,22 +39,25 @@ jobs: run: | brew update brew install ninja - brew install boost --build-from-source + brew install boost brew install asio - name: Configure CMake run: | cmake -S . -B ./build \ -G Ninja \ - -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ - -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ + -DCMAKE_CXX_STANDARD=${{ matrix.standard }} \ + -DCMAKE_CXX_FLAGS="-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_LIB" \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ -DCLI_UseBoostAsio=ON \ -DBOOST_ROOT=$BOOST_ROOT \ -DBOOST_INCLUDEDIR=$BOOST_ROOT/include \ -DBOOST_LIBRARYDIR=$BOOST_ROOT/lib \ - -DBoost_NO_BOOST_CMAKE=ON + -DBoost_NO_BOOST_CMAKE=ON \ + -DBoost_USE_STATIC_LIBS=OFF \ + -DBoost_USE_STATIC_RUNTIME=OFF - name: Build run: | From b66d1a736ff380a24744c99a79d0879402f4cfc0 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:59:09 +0100 Subject: [PATCH 158/223] Refactor Boost integration in CMake: improve header-only fallback for Boost.System and streamline package finding --- .github/workflows/macos_ci.yml | 8 +------- CMakeLists.txt | 15 +++++++++++++-- test/CMakeLists.txt | 23 +++++++++++++++++++++-- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index e399fc0..219adaf 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -51,13 +51,7 @@ jobs: -DCMAKE_CXX_FLAGS="-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_LIB" \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=ON \ - -DBOOST_ROOT=$BOOST_ROOT \ - -DBOOST_INCLUDEDIR=$BOOST_ROOT/include \ - -DBOOST_LIBRARYDIR=$BOOST_ROOT/lib \ - -DBoost_NO_BOOST_CMAKE=ON \ - -DBoost_USE_STATIC_LIBS=OFF \ - -DBoost_USE_STATIC_RUNTIME=OFF + -DCLI_UseBoostAsio=ON - name: Build run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ca6aa6..f5c2d63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,8 +69,19 @@ endif() if (CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) - add_definitions( -DBOOST_ALL_NO_LIB ) # for windows - find_package(Boost 1.66 REQUIRED COMPONENTS system) + add_definitions(-DBOOST_ALL_NO_LIB) + + # Prima proviamo a trovare Boost::system (versioni classiche) + find_package(Boost 1.66 QUIET COMPONENTS system) + + if (NOT Boost_SYSTEM_FOUND) + message(STATUS "Boost.System non trovato: uso la modalità header-only") + add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) + add_definitions(-DBOOST_SYSTEM_NO_LIB) + + # Cerca solo le headers (funziona con homebrew >=1.86) + find_package(Boost 1.66 REQUIRED) + endif() endif() if (CLI_UseStandaloneAsio) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 669b777..3c07efb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,8 +36,27 @@ set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows -# finds boost, triggers an error otherwise -find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework system) +find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) + +if (NOT Boost_SYSTEM_FOUND) + message(STATUS "Boost.System mancante: uso header-only anche per i test") + add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) + add_definitions(-DBOOST_SYSTEM_NO_LIB) + + # cerca solo headers (unit_test_framework rimane comunque solo-header, ok) + find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework) +endif() +find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) + +if (NOT Boost_SYSTEM_FOUND) + message(STATUS "Boost.System mancante: uso header-only anche per i test") + add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) + add_definitions(-DBOOST_SYSTEM_NO_LIB) + + # cerca solo headers (unit_test_framework rimane comunque solo-header, ok) + find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework) +endif() + # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From 445e316aa9228f5e7a586159c22938dce13d0a5a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:13:42 +0100 Subject: [PATCH 159/223] Refactor Boost integration in test CMakeLists: improve handling of Boost.System and streamline test target linking --- CMakeLists.txt | 30 +++++++++++++++--------------- test/CMakeLists.txt | 36 +++++++++++++++++------------------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5c2d63..8da666a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,10 @@ option(CLI_BuildTests "Build the unit tests." OFF) option(CLI_UseBoostAsio "Use the boost asio library." OFF) option(CLI_UseStandaloneAsio "Use the standalone asio library." OFF) +# Add Library +add_library(cli INTERFACE) +# Add target alias +add_library(cli::cli ALIAS cli) if(WIN32) macro(get_WIN32_WINNT version) @@ -69,19 +73,20 @@ endif() if (CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) - add_definitions(-DBOOST_ALL_NO_LIB) - - # Prima proviamo a trovare Boost::system (versioni classiche) find_package(Boost 1.66 QUIET COMPONENTS system) - if (NOT Boost_SYSTEM_FOUND) - message(STATUS "Boost.System non trovato: uso la modalità header-only") - add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) - add_definitions(-DBOOST_SYSTEM_NO_LIB) - - # Cerca solo le headers (funziona con homebrew >=1.86) - find_package(Boost 1.66 REQUIRED) + if (Boost_SYSTEM_FOUND) + message(STATUS "Found Boost.System: using compiled library") + target_link_libraries(cli INTERFACE Boost::system) + else() + message(STATUS "Boost.System not found: falling back to header-only") + target_compile_definitions(cli INTERFACE + BOOST_ERROR_CODE_HEADER_ONLY + BOOST_SYSTEM_NO_LIB + ) endif() + + target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED=1) endif() if (CLI_UseStandaloneAsio) @@ -91,11 +96,6 @@ endif() find_package(Threads REQUIRED) -# Add Library -add_library(cli INTERFACE) -# Add target alias -add_library(cli::cli ALIAS cli) - target_include_directories(cli INTERFACE $ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3c07efb..5073a6e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,26 +38,16 @@ add_definitions( -DBOOST_ALL_NO_LIB ) # for windows find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -if (NOT Boost_SYSTEM_FOUND) - message(STATUS "Boost.System mancante: uso header-only anche per i test") - add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) - add_definitions(-DBOOST_SYSTEM_NO_LIB) - - # cerca solo headers (unit_test_framework rimane comunque solo-header, ok) - find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework) -endif() -find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) - -if (NOT Boost_SYSTEM_FOUND) - message(STATUS "Boost.System mancante: uso header-only anche per i test") - add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY) - add_definitions(-DBOOST_SYSTEM_NO_LIB) - - # cerca solo headers (unit_test_framework rimane comunque solo-header, ok) - find_package(Boost 1.66 REQUIRED COMPONENTS unit_test_framework) +if (Boost_SYSTEM_FOUND) + message(STATUS "Using Boost.System library for tests") +else() + message(STATUS "Boost.System missing: using header-only mode for tests") + target_compile_definitions(test_suite PRIVATE + BOOST_ERROR_CODE_HEADER_ONLY + BOOST_SYSTEM_NO_LIB + ) endif() - # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) @@ -85,7 +75,15 @@ target_include_directories(test_suite SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) # indicates the shared library variant target_compile_definitions(test_suite PRIVATE "BOOST_TEST_DYN_LINK=1") # indicates the link paths -target_link_libraries(test_suite ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} Boost::system standalone_asio_test cli::cli) +target_link_libraries(test_suite + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + standalone_asio_test + cli::cli +) +# add it only if found +if (Boost_SYSTEM_FOUND) + target_link_libraries(test_suite Boost::system) +endif() # declares a test with our executable add_test(NAME cli_test COMMAND test_suite) From e24b3d6ef942a102aaa7303803d0dde7ca6b2994 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:21:42 +0100 Subject: [PATCH 160/223] Refactor Boost.System handling in test CMakeLists: streamline message logging and target linking --- test/CMakeLists.txt | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5073a6e..470a20f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,16 +38,6 @@ add_definitions( -DBOOST_ALL_NO_LIB ) # for windows find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -if (Boost_SYSTEM_FOUND) - message(STATUS "Using Boost.System library for tests") -else() - message(STATUS "Boost.System missing: using header-only mode for tests") - target_compile_definitions(test_suite PRIVATE - BOOST_ERROR_CODE_HEADER_ONLY - BOOST_SYSTEM_NO_LIB - ) -endif() - # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) @@ -80,9 +70,17 @@ target_link_libraries(test_suite standalone_asio_test cli::cli ) + # add it only if found if (Boost_SYSTEM_FOUND) - target_link_libraries(test_suite Boost::system) + message(STATUS "Using Boost.System library for tests") + target_link_libraries(test_suite Boost::system) +else() + message(STATUS "Boost.System missing: using header-only mode for tests") + target_compile_definitions(test_suite PRIVATE + BOOST_ERROR_CODE_HEADER_ONLY + BOOST_SYSTEM_NO_LIB + ) endif() # declares a test with our executable From 9b956f0b555c3ac7b111ae919ac60eccb1f4e31f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:36:49 +0100 Subject: [PATCH 161/223] Remove Boost.Asio dependency from CLI target in CMakeLists: simplify linking and configuration --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8da666a..a51781a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,10 +103,6 @@ target_include_directories(cli ) target_link_libraries(cli INTERFACE Threads::Threads) -if (CLI_UseBoostAsio) - target_link_libraries(cli INTERFACE Boost::system) - target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED=1) -endif() if (CLI_UseStandaloneAsio) add_library(standalone_asio INTERFACE IMPORTED) target_include_directories(standalone_asio SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) From 2e4fdf749eea29a72a7bad8599480341bbe09db2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:41:49 +0100 Subject: [PATCH 162/223] Add Boost include path for header-only usage in CLI target --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a51781a..0ff3cbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,9 @@ if (CLI_UseBoostAsio) BOOST_ERROR_CODE_HEADER_ONLY BOOST_SYSTEM_NO_LIB ) + # header-only needs comunque include + find_path(BOOST_INCLUDE_PATH "boost/version.hpp" HINTS /usr/local/include /opt/homebrew/include) + target_include_directories(cli INTERFACE ${BOOST_INCLUDE_PATH}) endif() target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED=1) From 00e19f171789a4b6d11f05a2cd154bea04d07449 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 10:55:19 +0100 Subject: [PATCH 163/223] Add CI workflow for testing across multiple platforms and compilers --- .github/workflows/{ci.yml.disabled => ci.yml} | 0 CMakeLists.txt | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{ci.yml.disabled => ci.yml} (100%) diff --git a/.github/workflows/ci.yml.disabled b/.github/workflows/ci.yml similarity index 100% rename from .github/workflows/ci.yml.disabled rename to .github/workflows/ci.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ff3cbd..1108dc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ if (CLI_UseBoostAsio) BOOST_SYSTEM_NO_LIB ) # header-only needs comunque include - find_path(BOOST_INCLUDE_PATH "boost/version.hpp" HINTS /usr/local/include /opt/homebrew/include) + find_path(BOOST_INCLUDE_PATH "boost/version.hpp") target_include_directories(cli INTERFACE ${BOOST_INCLUDE_PATH}) endif() From b11bd550a25d757af700048530a741da6662b5f1 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:23:46 +0100 Subject: [PATCH 164/223] Update CI workflow names and enhance CMakeLists for Boost and Asio support --- .github/workflows/ci.yml | 2 +- .github/workflows/macos_ci.yml | 2 +- CMakeLists.txt | 126 +++++++++++++++++---------------- 3 files changed, 66 insertions(+), 64 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38835f7..6d50f1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: CI linux and windows on: [push,pull_request] diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 219adaf..86b38c9 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -1,4 +1,4 @@ -name: CI +name: CI macOS on: [push,pull_request] diff --git a/CMakeLists.txt b/CMakeLists.txt index 1108dc6..ef8b347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,101 +38,110 @@ project( include(GNUInstallDirs) +# --------------------------------------------------------------- +# Options +# --------------------------------------------------------------- option(CLI_BuildExamples "Build the examples." OFF) option(CLI_BuildTests "Build the unit tests." OFF) -option(CLI_UseBoostAsio "Use the boost asio library." OFF) -option(CLI_UseStandaloneAsio "Use the standalone asio library." OFF) +option(CLI_UseBoostAsio "Use Boost.Asio library." OFF) +option(CLI_UseStandaloneAsio "Use standalone Asio library." OFF) -# Add Library +# --------------------------------------------------------------- +# Library +# --------------------------------------------------------------- add_library(cli INTERFACE) # Add target alias add_library(cli::cli ALIAS cli) -if(WIN32) - macro(get_WIN32_WINNT version) - if(CMAKE_SYSTEM_VERSION) - set(ver ${CMAKE_SYSTEM_VERSION}) - string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver}) - string(REGEX MATCH "^([0-9]+)" verMajor ${ver}) - # Check for Windows 10, b/c we'll need to convert to hex 'A'. - if("${verMajor}" MATCHES "10") - set(verMajor "A") - string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver}) - endif() - # Remove all remaining '.' characters. - string(REPLACE "." "" ver ${ver}) - # Prepend each digit with a zero. - string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver}) - set(${version} "0x${ver}") - endif() - endmacro() +target_include_directories(cli + INTERFACE + $ + $ +) - get_WIN32_WINNT(ver) - add_definitions(-D_WIN32_WINNT=${ver}) -endif() +find_package(Threads REQUIRED) +target_link_libraries(cli INTERFACE Threads::Threads) -if (CLI_UseBoostAsio) +# --------------------------------------------------------------- +# Boost.Asio support +# --------------------------------------------------------------- +if(CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.66 QUIET COMPONENTS system) + find_package(Boost 1.66 QUIET COMPONENTS system date_time) - if (Boost_SYSTEM_FOUND) - message(STATUS "Found Boost.System: using compiled library") - target_link_libraries(cli INTERFACE Boost::system) + if(Boost_FOUND) + message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") + target_include_directories(cli INTERFACE ${Boost_INCLUDE_DIRS}) + target_link_libraries(cli INTERFACE Boost::system Boost::date_time) else() - message(STATUS "Boost.System not found: falling back to header-only") + message(STATUS "Boost libraries not found. Falling back to header-only mode.") target_compile_definitions(cli INTERFACE BOOST_ERROR_CODE_HEADER_ONLY BOOST_SYSTEM_NO_LIB ) - # header-only needs comunque include + + # find headers (default locations) find_path(BOOST_INCLUDE_PATH "boost/version.hpp") + if(NOT BOOST_INCLUDE_PATH) + message(FATAL_ERROR "Boost headers not found for header-only fallback!") + endif() target_include_directories(cli INTERFACE ${BOOST_INCLUDE_PATH}) endif() target_compile_definitions(cli INTERFACE BOOST_ASIO_NO_DEPRECATED=1) endif() -if (CLI_UseStandaloneAsio) - find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) - mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) -endif() - -find_package(Threads REQUIRED) - -target_include_directories(cli - INTERFACE - $ - $ -) +# --------------------------------------------------------------- +# Standalone Asio support +# --------------------------------------------------------------- +if(CLI_UseStandaloneAsio) + find_path(STANDALONE_ASIO_INCLUDE_PATH "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) + if(NOT STANDALONE_ASIO_INCLUDE_PATH) + message(FATAL_ERROR "Standalone Asio headers not found") + endif() -target_link_libraries(cli INTERFACE Threads::Threads) -if (CLI_UseStandaloneAsio) - add_library(standalone_asio INTERFACE IMPORTED) - target_include_directories(standalone_asio SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) - target_link_libraries(standalone_asio INTERFACE Threads::Threads) + add_library(standalone_asio INTERFACE IMPORTED) + target_include_directories(standalone_asio SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) + target_link_libraries(standalone_asio INTERFACE Threads::Threads) target_link_libraries(cli INTERFACE standalone_asio) - - # alternative way: - # target_include_directories(cli SYSTEM INTERFACE ${STANDALONE_ASIO_INCLUDE_PATH}) endif() +# --------------------------------------------------------------- +# C++ standard +# --------------------------------------------------------------- if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() target_compile_features(cli INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) +# --------------------------------------------------------------- +# Windows specific +# --------------------------------------------------------------- +if(WIN32) + # Set _WIN32_WINNT for Windows 10+ + if(NOT DEFINED _WIN32_WINNT) + add_definitions(-D_WIN32_WINNT=0x0A00) + endif() +endif() + +# --------------------------------------------------------------- # Examples -if (CLI_BuildExamples) +# --------------------------------------------------------------- +if(CLI_BuildExamples) add_subdirectory(examples) endif() +# --------------------------------------------------------------- # Tests -if (CLI_BuildTests) +# --------------------------------------------------------------- +if(CLI_BuildTests) enable_testing() add_subdirectory(test) endif() +# --------------------------------------------------------------- # Install +# --------------------------------------------------------------- if(NOT CMAKE_SKIP_INSTALL_RULES) install(DIRECTORY include/cli DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) @@ -156,13 +165,6 @@ if(NOT CMAKE_SKIP_INSTALL_RULES) install(TARGETS cli EXPORT cliTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(EXPORT cliTargets FILE cliTargets.cmake NAMESPACE cli:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/cli) - - install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli" - ) - install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cli.pc" - DESTINATION ${PKGCONFIG_INSTALL_DIR} - ) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cliConfig.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/cli") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cli.pc" DESTINATION ${PKGCONFIG_INSTALL_DIR}) endif() From 52b534d60a50d4c54218cafd7b9fdff81e5d9792 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 16:17:42 +0100 Subject: [PATCH 165/223] Add definition to disable automatic Boost library linking for Windows --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef8b347..b204391 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ target_link_libraries(cli INTERFACE Threads::Threads) if(CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) + add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") From 2d1e72c17b95fe2a2f0e84f187d74438e7e0b0b8 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:14:47 +0100 Subject: [PATCH 166/223] Update macOS CI workflow to support additional OS versions and C++ standards --- .github/workflows/macos_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 86b38c9..77309bd 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -9,9 +9,9 @@ jobs: fail-fast: false matrix: - os: [macos-14] + os: [macos-14, macos-15, macos-26] compiler: [llvm-17.0.2, clang++-15] - standard: [14, 17, 20, 23] + standard: [14, 17, 20, 23, 26] build_type: [Release, Debug] steps: From b200e723c95038eac1b74af7f5981749527e8364 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:40:32 +0100 Subject: [PATCH 167/223] Enhance CI workflows for Windows and macOS: update ASIO path handling and compiler versions --- .github/workflows/ci.yml | 20 ++++++++++++++++++-- .github/workflows/macos_ci.yml | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d50f1f..f018f84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,8 +90,24 @@ jobs: # windows need asio library path if: runner.os == 'Windows' run: | - cmake -S . -B ./build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include - + Start-Sleep -Seconds 2 + + # Correctly constructs the path for Windows + $AsioPath = Join-Path $env:GITHUB_WORKSPACE "asio/asio/include" + # Converts to forward slash (CMake handles them better) + $AsioPath = $AsioPath -replace "\\", "/" + + echo "ASIO path: $AsioPath" + dir $AsioPath + + cmake -S . -B ./build ` + -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` + -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` + -DCLI_BuildTests=ON ` + -DCLI_BuildExamples=ON ` + -DCLI_UseBoostAsio=ON ` + -DASIO_INCLUDEDIR="$AsioPath" + - name: Build run: | # cd /home/runner/work/cli/cli/build diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 77309bd..6d41112 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -10,7 +10,7 @@ jobs: matrix: os: [macos-14, macos-15, macos-26] - compiler: [llvm-17.0.2, clang++-15] + compiler: [apple-clang, llvm-18, llvm-19] standard: [14, 17, 20, 23, 26] build_type: [Release, Debug] From 08799000333c1802e5ef68900d715a9437ff778b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:21:27 +0100 Subject: [PATCH 168/223] Refactor CI workflows: disable Windows test execution and update macOS versions --- .github/workflows/ci.yml | 2 +- .github/workflows/macos_ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f018f84..b76ec15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,7 @@ jobs: - name: run tests # on windows test_suite throws an exception, but only on the CI environment! - if: runner.os != 'Windows' + # if: runner.os != 'Windows' # working-directory: ./build/test/${{matrix.build_type}} working-directory: ./build run: | diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 6d41112..6cf0a6c 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -9,7 +9,7 @@ jobs: fail-fast: false matrix: - os: [macos-14, macos-15, macos-26] + os: [macos-15, macos-26] compiler: [apple-clang, llvm-18, llvm-19] standard: [14, 17, 20, 23, 26] build_type: [Release, Debug] From be142a7fd65b613ea3ad3ccf731f715d5db96d94 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:03:55 +0100 Subject: [PATCH 169/223] Add boost dll path to the CI yml file --- .github/workflows/ci.yml | 44 +++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b76ec15..111bef2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,6 @@ jobs: fail-fast: false matrix: - # os: [ubuntu-22.04, macos-14, windows-2022, windows-2025] os: [ubuntu-22.04, windows-2022, windows-2025] compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] @@ -18,21 +17,16 @@ jobs: # Exclude msvc on non-Windows platforms - os: ubuntu-22.04 compiler: msvc - - os: macos-14 - compiler: msvc # Exclude gcc on Windows platforms - os: windows-2022 compiler: gcc-11 - os: windows-2025 compiler: gcc-11 - # Exclude gcc on mac platforms - - os: macos-14 - compiler: gcc-11 # Exclude llvm on Windows platforms - os: windows-2022 compiler: llvm-17.0.2 - os: windows-2025 - compiler: llvm-17.0.2 + compiler: llvm-17.0.2 steps: - uses: actions/checkout@v4 @@ -63,20 +57,13 @@ jobs: run: | sudo apt-get -y update sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev - - - name: setup dependencies - macOS - if: runner.os == 'macOS' - run: | - brew install ninja - brew install boost - brew install asio - + - name: setup dependencies - Windows if: runner.os == 'Windows' run: | choco install ninja choco install boost-msvc-14.1 - # # Download and extract Asio + # Download and extract Asio curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip move asio-asio-1-18-2 asio @@ -91,15 +78,15 @@ jobs: if: runner.os == 'Windows' run: | Start-Sleep -Seconds 2 - + # Correctly constructs the path for Windows $AsioPath = Join-Path $env:GITHUB_WORKSPACE "asio/asio/include" # Converts to forward slash (CMake handles them better) $AsioPath = $AsioPath -replace "\\", "/" - + echo "ASIO path: $AsioPath" dir $AsioPath - + cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` @@ -107,7 +94,22 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" - + + - name: Set Boost DLL Path - Windows + if: runner.os == 'Windows' + run: | + # Find the directory of Boost DLLs installed by choco (usually in 'lib' under the root) + $boostPath = "C:\ProgramData\chocolatey\lib\boost-msvc-14.1.*\lib" + $boostDllDir = Get-ChildItem -Path $boostPath -Directory | Select-Object -First 1 + + if ($null -ne $boostDllDir) { + echo "Adding the path of Boost DLLs: $($boostDllDir.FullName)" + # Adds the path to the PATH environment variable for subsequent steps + echo "$($boostDllDir.FullName)" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append + } else { + echo "WARNING: Boost DLL path not found." + } + - name: Build run: | # cd /home/runner/work/cli/cli/build @@ -116,7 +118,7 @@ jobs: - name: run tests # on windows test_suite throws an exception, but only on the CI environment! - # if: runner.os != 'Windows' + if: runner.os != 'Windows' # working-directory: ./build/test/${{matrix.build_type}} working-directory: ./build run: | From 06c5a94dfac5f4da10a72fe732eca85f2fd1a7ff Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 28 Nov 2025 19:45:27 +0100 Subject: [PATCH 170/223] Remove Windows CI workflow and simplify test execution in CI configuration --- .github/workflows/ci.yml | 7 +--- .github/workflows/win_ci.yml.disabled | 48 --------------------------- 2 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 .github/workflows/win_ci.yml.disabled diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 111bef2..29bf721 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,16 +112,11 @@ jobs: - name: Build run: | - # cd /home/runner/work/cli/cli/build - # make all cmake --build ./build --config ${{matrix.build_type}} - name: run tests # on windows test_suite throws an exception, but only on the CI environment! - if: runner.os != 'Windows' - # working-directory: ./build/test/${{matrix.build_type}} + # if: runner.os != 'Windows' working-directory: ./build run: | - # cd /home/runner/work/cli/cli/build/test/ - # ./test_suite ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/win_ci.yml.disabled b/.github/workflows/win_ci.yml.disabled deleted file mode 100644 index 59c525f..0000000 --- a/.github/workflows/win_ci.yml.disabled +++ /dev/null @@ -1,48 +0,0 @@ -name: Windows CI - -on: [push, pull_request] - -jobs: - Test: - # runs-on: windows-latest - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - - matrix: - os: - - windows-2022 - - windows-2019 - build_type: - - Release - - Debug - standard: [14, 17, 20, 23] - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Set up MSVC - uses: ilammy/msvc-dev-cmd@v1 - - - name: Install Boost - run: choco install boost-msvc-14.1 - - - name: Install ASIO standalone - run: | - curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip - tar -xf asio.zip - move asio-asio-1-18-2 asio - - - name: Configure CMake - run: cmake -S . -B build -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DASIO_INCLUDEDIR=${{ github.workspace }}/asio/asio/include -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON -DCMAKE_CXX_STANDARD=${{matrix.standard}} - - - name: Build - run: cmake --build build --config ${{matrix.build_type}} - -# - name: Run tests - # working-directory: build/test/${{matrix.build_type}} - # run: ./test_suite -l all -# working-directory: build -# run: ctest -C ${{matrix.build_type}} --output-on-failure --debug - From 5206b778f6eac6b1fd233cf3ba0147f881d985a9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:06:48 +0100 Subject: [PATCH 171/223] Minimal CI for win --- .github/workflows/{ci.yml => ci.yml.disabled} | 0 .github/workflows/ci_minimal.yml | 106 ++++++++++++++++++ .../{macos_ci.yml => macos_ci.yml.disabled} | 0 3 files changed, 106 insertions(+) rename .github/workflows/{ci.yml => ci.yml.disabled} (100%) create mode 100644 .github/workflows/ci_minimal.yml rename .github/workflows/{macos_ci.yml => macos_ci.yml.disabled} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml.disabled similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/ci.yml.disabled diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml new file mode 100644 index 0000000..b93c5c6 --- /dev/null +++ b/.github/workflows/ci_minimal.yml @@ -0,0 +1,106 @@ +name: CI windows + +on: [push,pull_request] + +jobs: + Test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + + matrix: + os: [windows-2025] + compiler: [msvc] + standard: [23] + build_type: [Release] + + steps: + - uses: actions/checkout@v4 + + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + compiler: ${{ matrix.compiler }} + vcvarsall: ${{ contains(matrix.os, 'windows' )}} + + cmake: true + ninja: true + vcpkg: false + ccache: true + clangtidy: true + + cppcheck: true + + gcovr: true + opencppcoverage: true + + - name: setup dependencies - Windows + run: | + choco install ninja + choco install boost-msvc-14.1 + # Download and extract Asio + curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip + tar -xf asio.zip + move asio-asio-1-18-2 asio + + - name: Configure CMake - Windows + # windows need asio library path + run: | + Start-Sleep -Seconds 2 + + # Correctly constructs the path for Windows + $AsioPath = Join-Path $env:GITHUB_WORKSPACE "asio/asio/include" + # Converts to forward slash (CMake handles them better) + $AsioPath = $AsioPath -replace "\\", "/" + + echo "ASIO path: $AsioPath" + dir $AsioPath + + cmake -S . -B ./build ` + -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` + -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` + -DCLI_BuildTests=ON ` + -DCLI_BuildExamples=ON ` + -DCLI_UseBoostAsio=ON ` + -DASIO_INCLUDEDIR="$AsioPath" + + - name: Set Boost DLL Path - Windows 🚀 (Fix) + if: runner.os == 'Windows' + run: | + # 1. Trova la directory root di Boost installata da Chocolatey (es. C:\...\boost-msvc-14.1.1.72.0) + $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1.*" -Directory | Select-Object -First 1 + + if ($null -eq $boostRoot) { + Write-Warning "AVVISO: Directory root di Boost non trovata." + exit 1 # Fallisce lo step se Boost non è installato + } + + # 2. Cerca la cartella delle DLL (spesso chiamata 'lib' o specifica per l'architettura, come 'lib-vc141-mt-x64') + # Ricerca della cartella che contiene i file .dll di Boost + $boostDllDir = Get-ChildItem -Path "$($boostRoot.FullName)\lib" -Directory -ErrorAction SilentlyContinue | Select-Object -First 1 + + # Se non si trova la sottocartella 'lib', controlla se le DLL sono direttamente nella root + if ($null -eq $boostDllDir) { + # Se non trova la sottocartella 'lib', cerca direttamente i file .dll nella root di Boost + $boostDllDir = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 | Select-Object -ExpandProperty Directory | Select-Object -First 1 + } + + # 3. Aggiungi il percorso PATH, se trovato + if ($null -ne $boostDllDir) { + $dllPath = $boostDllDir.FullName + echo "Aggiungo il percorso delle DLL di Boost: $dllPath" + # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step + echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append + } else { + Write-Error "ERRORE CRITICO: La directory delle DLL di Boost non è stata trovata dopo l'installazione." + exit 1 + } + + - name: Build + run: | + cmake --build ./build --config ${{matrix.build_type}} + + - name: run tests + working-directory: ./build + run: | + ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml.disabled similarity index 100% rename from .github/workflows/macos_ci.yml rename to .github/workflows/macos_ci.yml.disabled From bd649af20a0638034bfb131ae215af1dfdf4c5ae Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 28 Nov 2025 22:35:31 +0100 Subject: [PATCH 172/223] Improve Boost DLL path handling in Windows CI workflow --- .github/workflows/ci_minimal.yml | 45 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index b93c5c6..b11f29b 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -38,6 +38,11 @@ jobs: run: | choco install ninja choco install boost-msvc-14.1 + + # Stampa la directory 'lib' di choco per debug + echo "Contenuto di C:\ProgramData\chocolatey\lib:" + dir C:\ProgramData\chocolatey\lib + # Download and extract Asio curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip @@ -64,38 +69,34 @@ jobs: -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" - - name: Set Boost DLL Path - Windows 🚀 (Fix) + - name: Set Boost DLL Path - Windows 💡 (Versione Migliorata) if: runner.os == 'Windows' run: | - # 1. Trova la directory root di Boost installata da Chocolatey (es. C:\...\boost-msvc-14.1.1.72.0) - $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1.*" -Directory | Select-Object -First 1 + # 1. Trova la directory root di Boost (es. C:\...\boost-msvc-14.1.1.72.0) + # Ricerca meno specifica per la versione choco. + $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1*" -Directory | Select-Object -First 1 if ($null -eq $boostRoot) { - Write-Warning "AVVISO: Directory root di Boost non trovata." - exit 1 # Fallisce lo step se Boost non è installato + Write-Error "ERRORE: Directory root di Boost (boost-msvc-14.1*) non trovata. Controlla il nome del pacchetto Chocolatey." + exit 1 } - # 2. Cerca la cartella delle DLL (spesso chiamata 'lib' o specifica per l'architettura, come 'lib-vc141-mt-x64') - # Ricerca della cartella che contiene i file .dll di Boost - $boostDllDir = Get-ChildItem -Path "$($boostRoot.FullName)\lib" -Directory -ErrorAction SilentlyContinue | Select-Object -First 1 + # 2. Ricerca Ricorsiva Aggressiva delle DLL. + # Spesso le DLL sono in sottocartelle come 'lib', 'lib\x64', 'lib-vc142-x64'. + # Cerchiamo qualsiasi file .dll sotto la root di Boost. + $boostDllFile = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 - # Se non si trova la sottocartella 'lib', controlla se le DLL sono direttamente nella root - if ($null -eq $boostDllDir) { - # Se non trova la sottocartella 'lib', cerca direttamente i file .dll nella root di Boost - $boostDllDir = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 | Select-Object -ExpandProperty Directory | Select-Object -First 1 - } - - # 3. Aggiungi il percorso PATH, se trovato - if ($null -ne $boostDllDir) { - $dllPath = $boostDllDir.FullName - echo "Aggiungo il percorso delle DLL di Boost: $dllPath" - # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step - echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append - } else { - Write-Error "ERRORE CRITICO: La directory delle DLL di Boost non è stata trovata dopo l'installazione." + if ($null -eq $boostDllFile) { + Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" exit 1 } + # 3. Aggiungi il percorso PATH + $dllPath = $boostDllFile.Directory.FullName + echo "Aggiungo il percorso delle DLL di Boost: $dllPath" + # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step + echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append + - name: Build run: | cmake --build ./build --config ${{matrix.build_type}} From abbbb58bb971305d36734838fde9ab71e3776fbf Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 28 Nov 2025 23:00:44 +0100 Subject: [PATCH 173/223] Refine Boost DLL path detection in Windows CI workflow --- .github/workflows/ci_minimal.yml | 47 +++++++++++++++----------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index b11f29b..533920c 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -69,33 +69,30 @@ jobs: -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" - - name: Set Boost DLL Path - Windows 💡 (Versione Migliorata) + - name: Set Boost DLL Path - Windows ✨ (Fix finale) if: runner.os == 'Windows' run: | - # 1. Trova la directory root di Boost (es. C:\...\boost-msvc-14.1.1.72.0) - # Ricerca meno specifica per la versione choco. - $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1*" -Directory | Select-Object -First 1 - - if ($null -eq $boostRoot) { - Write-Error "ERRORE: Directory root di Boost (boost-msvc-14.1*) non trovata. Controlla il nome del pacchetto Chocolatey." - exit 1 - } - - # 2. Ricerca Ricorsiva Aggressiva delle DLL. - # Spesso le DLL sono in sottocartelle come 'lib', 'lib\x64', 'lib-vc142-x64'. - # Cerchiamo qualsiasi file .dll sotto la root di Boost. - $boostDllFile = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 - - if ($null -eq $boostDllFile) { - Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" - exit 1 - } - - # 3. Aggiungi il percorso PATH - $dllPath = $boostDllFile.Directory.FullName - echo "Aggiungo il percorso delle DLL di Boost: $dllPath" - # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step - echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append + # 1. Trova la directory root di Boost (usando il nome esatto del pacchetto da Chocolatey) + $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1" -Directory -ErrorAction Stop + + # 2. Ricerca Ricorsiva Aggressiva delle DLL. + # Le DLL Boost sono spesso in una sottocartella che riflette il toolset MSVC, es. 'lib\x64' o 'lib-vc141-mt-x64'. + # Cerchiamo qualsiasi file .dll sotto la root di Boost. + $boostDllFile = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 + + if ($null -eq $boostDllFile) { + Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" + # Aggiungiamo un debug per vedere cosa c'è nella cartella root di Boost + Write-Host "Contenuto della cartella Boost:" + Get-ChildItem -Path "$($boostRoot.FullName)" -Recurse + exit 1 + } + + # 3. Aggiungi il percorso PATH + $dllPath = $boostDllFile.Directory.FullName + echo "Aggiungo il percorso delle DLL di Boost: $dllPath" + # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step + echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append - name: Build run: | From ea528d63198011000d5637c200ad459e7f0e6314 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 09:56:38 +0100 Subject: [PATCH 174/223] Update test directory for CTest execution in CI workflow --- .github/workflows/ci_minimal.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 533920c..b936bf5 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -101,4 +101,4 @@ jobs: - name: run tests working-directory: ./build run: | - ctest -C ${{matrix.build_type}} --output-on-failure + ctest -C ${{matrix.build_type}} --output-on-failure --test-dir . From 337581c157bcca6a20a1f87b99f9009a9fb38920 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:50:11 +0100 Subject: [PATCH 175/223] Remove critical error message for missing Boost DLL and add debug output for Boost directory contents --- .github/workflows/ci_minimal.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index b936bf5..087e7c1 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -81,7 +81,7 @@ jobs: $boostDllFile = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 if ($null -eq $boostDllFile) { - Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" + # Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" # Aggiungiamo un debug per vedere cosa c'è nella cartella root di Boost Write-Host "Contenuto della cartella Boost:" Get-ChildItem -Path "$($boostRoot.FullName)" -Recurse @@ -101,4 +101,4 @@ jobs: - name: run tests working-directory: ./build run: | - ctest -C ${{matrix.build_type}} --output-on-failure --test-dir . + ctest -C ${{matrix.build_type}} --output-on-failure From 2cd1d079b957b03fbe9a3e7e37c6784999c2b281 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:04:22 +0100 Subject: [PATCH 176/223] Add debug output for Boost and Chocolatey lib directories in CI workflow --- .github/workflows/ci_minimal.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 087e7c1..348eaa4 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -85,6 +85,13 @@ jobs: # Aggiungiamo un debug per vedere cosa c'è nella cartella root di Boost Write-Host "Contenuto della cartella Boost:" Get-ChildItem -Path "$($boostRoot.FullName)" -Recurse + + Write-Host "Contenuto della cartella lib:" + Get-ChildItem -Path "C:\ProgramData\chocolatey\lib" -Recurse + + Write-Host "Contenuto della cartella lib\boost-msvc-14.1:" + Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1" -Recurse + exit 1 } From 20e558b00c46a697ae6570f13a8d9c84b6e7249a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:41:15 +0100 Subject: [PATCH 177/223] Enhance CI workflow for Windows: improve step descriptions, add Boost setup, and refine CMake configuration --- .github/workflows/ci_minimal.yml | 81 +++++++++++--------------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 348eaa4..9c5f557 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -1,9 +1,10 @@ name: CI windows -on: [push,pull_request] +on: [push, pull_request] jobs: Test: + # Esegue il job su un ambiente Windows (windows-2025 al momento dell'uso) runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -15,52 +16,57 @@ jobs: build_type: [Release] steps: - - uses: actions/checkout@v4 + - name: 🔄 Checkout Repository + uses: actions/checkout@v4 - - name: Setup Cpp + - name: 🛠️ Setup Cpp Tools uses: aminya/setup-cpp@v1 with: + # Configura MSVC e le variabili d'ambiente (vcvarsall) compiler: ${{ matrix.compiler }} vcvarsall: ${{ contains(matrix.os, 'windows' )}} - + # Richiede l'installazione di CMake e Ninja cmake: true ninja: true vcpkg: false ccache: true + # Installazione di strumenti di analisi/copertura clangtidy: true - cppcheck: true - gcovr: true opencppcoverage: true - - name: setup dependencies - Windows + - name: 📦 Download and Build Boost (system, unit_test_framework) + uses: actions-toolkit/boost-build@v1.0.3 + with: + # Puoi specificare la versione desiderata, ad esempio 1.84.0 + boost_version: '1.84.0' + # msvc-14.3 è il toolset tipico per VS 2022 (Windows-2025) + toolset: msvc-14.3 + # Compila solo le librerie necessarie (riduce il tempo di build) + with_libraries: 'system,unit_test_framework' + + - name: 🔗 Setup Other Dependencies (Asio) run: | - choco install ninja - choco install boost-msvc-14.1 - - # Stampa la directory 'lib' di choco per debug - echo "Contenuto di C:\ProgramData\chocolatey\lib:" - dir C:\ProgramData\chocolatey\lib - # Download and extract Asio curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip tar -xf asio.zip move asio-asio-1-18-2 asio - - name: Configure CMake - Windows - # windows need asio library path + - name: ⚙️ Configure CMake - Windows + shell: powershell run: | Start-Sleep -Seconds 2 - # Correctly constructs the path for Windows + # Costruisce il percorso assoluto della directory include di Asio $AsioPath = Join-Path $env:GITHUB_WORKSPACE "asio/asio/include" - # Converts to forward slash (CMake handles them better) $AsioPath = $AsioPath -replace "\\", "/" echo "ASIO path: $AsioPath" dir $AsioPath + # Esegue la configurazione CMake + # Le variabili BOOST_ROOT e BOOST_LIBRARYDIR sono impostate dallo step precedente cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` @@ -69,43 +75,12 @@ jobs: -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" - - name: Set Boost DLL Path - Windows ✨ (Fix finale) - if: runner.os == 'Windows' - run: | - # 1. Trova la directory root di Boost (usando il nome esatto del pacchetto da Chocolatey) - $boostRoot = Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1" -Directory -ErrorAction Stop - - # 2. Ricerca Ricorsiva Aggressiva delle DLL. - # Le DLL Boost sono spesso in una sottocartella che riflette il toolset MSVC, es. 'lib\x64' o 'lib-vc141-mt-x64'. - # Cerchiamo qualsiasi file .dll sotto la root di Boost. - $boostDllFile = Get-ChildItem -Path "$($boostRoot.FullName)" -Filter "*.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 - - if ($null -eq $boostDllFile) { - # Write-Error "ERRORE CRITICO: Nessun file DLL di Boost trovato sotto la directory: $($boostRoot.FullName)" - # Aggiungiamo un debug per vedere cosa c'è nella cartella root di Boost - Write-Host "Contenuto della cartella Boost:" - Get-ChildItem -Path "$($boostRoot.FullName)" -Recurse - - Write-Host "Contenuto della cartella lib:" - Get-ChildItem -Path "C:\ProgramData\chocolatey\lib" -Recurse - - Write-Host "Contenuto della cartella lib\boost-msvc-14.1:" - Get-ChildItem -Path "C:\ProgramData\chocolatey\lib\boost-msvc-14.1" -Recurse - - exit 1 - } - - # 3. Aggiungi il percorso PATH - $dllPath = $boostDllFile.Directory.FullName - echo "Aggiungo il percorso delle DLL di Boost: $dllPath" - # Aggiunge il percorso alla variabile d'ambiente PATH per i successivi step - echo "$dllPath" | Out-File -FilePath $env:GITHUB_PATH -Encoding UTF8 -Append - - - name: Build + - name: 🔨 Build Project run: | cmake --build ./build --config ${{matrix.build_type}} - - name: run tests + - name: ✅ Run Tests working-directory: ./build run: | - ctest -C ${{matrix.build_type}} --output-on-failure + # Usa CTest per eseguire i test, compresi quelli basati su Boost Unit Test Framework + ctest -C ${{matrix.build_type}} --output-on-failure \ No newline at end of file From 3d9758b9fd3f8bc11404ea2d713a046c270e7752 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 12:50:51 +0100 Subject: [PATCH 178/223] Update Boost build action in CI workflow: switch to new action and add output paths display --- .github/workflows/ci_minimal.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 9c5f557..a3c4af0 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -37,14 +37,17 @@ jobs: opencppcoverage: true - name: 📦 Download and Build Boost (system, unit_test_framework) - uses: actions-toolkit/boost-build@v1.0.3 + id: boost + uses: egor-tensin/build-boost@v1 with: - # Puoi specificare la versione desiderata, ad esempio 1.84.0 - boost_version: '1.84.0' - # msvc-14.3 è il toolset tipico per VS 2022 (Windows-2025) - toolset: msvc-14.3 - # Compila solo le librerie necessarie (riduce il tempo di build) - with_libraries: 'system,unit_test_framework' + version: '1.84.0' + libraries: 'system,unit_test_framework' + + - name: Show paths + run: | + printf 'Boost has been unpacked to: %s\n' '${{ steps.boost.outputs.root }}' + printf 'Libraries can be found here: %s\n' '${{ steps.boost.outputs.librarydir }}' + shell: bash - name: 🔗 Setup Other Dependencies (Asio) run: | From 86f3ee586aac847fd3b40783c60da54c8e8612c7 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:00:43 +0100 Subject: [PATCH 179/223] Add step to create Boost build directory in CI workflow --- .github/workflows/ci_minimal.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index a3c4af0..3494cce 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -36,6 +36,10 @@ jobs: gcovr: true opencppcoverage: true + - name: Create Build Directory + run: | + mkdir boost + - name: 📦 Download and Build Boost (system, unit_test_framework) id: boost uses: egor-tensin/build-boost@v1 From 56ffa791fca3e40cc663f39e5baceb6bd52f01fc Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:08:19 +0100 Subject: [PATCH 180/223] Remove redundant build directory creation step and update Boost action version --- .github/workflows/ci_minimal.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 3494cce..c95778b 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -36,13 +36,9 @@ jobs: gcovr: true opencppcoverage: true - - name: Create Build Directory - run: | - mkdir boost - - name: 📦 Download and Build Boost (system, unit_test_framework) id: boost - uses: egor-tensin/build-boost@v1 + uses: egor-tensin/build-boost@v1.4 with: version: '1.84.0' libraries: 'system,unit_test_framework' From 563f8d7597ff392c031dc8d1077ce09aaf8cc411 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:19:09 +0100 Subject: [PATCH 181/223] Update CI workflow to install Boost using new action and specify version --- .github/workflows/ci_minimal.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index c95778b..94e3e65 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -36,18 +36,14 @@ jobs: gcovr: true opencppcoverage: true - - name: 📦 Download and Build Boost (system, unit_test_framework) - id: boost - uses: egor-tensin/build-boost@v1.4 + - name: Install boost + uses: MarkusJx/install-boost@v2 + id: install-boost with: - version: '1.84.0' - libraries: 'system,unit_test_framework' - - - name: Show paths - run: | - printf 'Boost has been unpacked to: %s\n' '${{ steps.boost.outputs.root }}' - printf 'Libraries can be found here: %s\n' '${{ steps.boost.outputs.librarydir }}' - shell: bash + # REQUIRED: Specify the required boost version + # A list of supported versions can be found here: + # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json + boost_version: 1.89.0 - name: 🔗 Setup Other Dependencies (Asio) run: | @@ -77,6 +73,8 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - name: 🔨 Build Project run: | @@ -86,4 +84,6 @@ jobs: working-directory: ./build run: | # Usa CTest per eseguire i test, compresi quelli basati su Boost Unit Test Framework - ctest -C ${{matrix.build_type}} --output-on-failure \ No newline at end of file + ctest -C ${{matrix.build_type}} --output-on-failure + env: + PATH: ${{ steps.install-boost.outputs.BOOST_ROOT }} \ No newline at end of file From f9b5818af49e52325273a2662a4625efd6352e35 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:30:20 +0100 Subject: [PATCH 182/223] Add BOOST path output and update CMake configuration for Boost integration --- .github/workflows/ci_minimal.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 94e3e65..c4fdb8e 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -64,6 +64,9 @@ jobs: echo "ASIO path: $AsioPath" dir $AsioPath + echo "BOOST path: ${{ steps.install-boost.outputs.BOOST_ROOT }}" + dir ${{ steps.install-boost.outputs.BOOST_ROOT }} + # Esegue la configurazione CMake # Le variabili BOOST_ROOT e BOOST_LIBRARYDIR sono impostate dallo step precedente cmake -S . -B ./build ` @@ -72,7 +75,9 @@ jobs: -DCLI_BuildTests=ON ` -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` - -DASIO_INCLUDEDIR="$AsioPath" + -DASIO_INCLUDEDIR="$AsioPath" ` + -DBOOST_INCLUDEDIR="${{ steps.install-boost.outputs.BOOST_ROOT }}/include/" ` + -DBOOST_LIBRARYDIR="${{ steps.install-boost.outputs.BOOST_ROOT }}/lib/" env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} From 361f9d20b7bc6b6c0cf82578f895eeb0b014285e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:46:58 +0100 Subject: [PATCH 183/223] Simplify Boost configuration by consolidating include and library directory variables into BOOST_ROOT --- .github/workflows/ci_minimal.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index c4fdb8e..815b704 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -76,8 +76,7 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DBOOST_INCLUDEDIR="${{ steps.install-boost.outputs.BOOST_ROOT }}/include/" ` - -DBOOST_LIBRARYDIR="${{ steps.install-boost.outputs.BOOST_ROOT }}/lib/" + -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}" env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} From 0352ae19a09187b065109cc9756dd81a25892231 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 13:53:00 +0100 Subject: [PATCH 184/223] Update Boost configuration in CI workflow to use staged directory for BOOST_ROOT --- .github/workflows/ci_minimal.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 815b704..81d037f 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -76,9 +76,9 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}" + -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}/stage" env: - BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage - name: 🔨 Build Project run: | @@ -90,4 +90,4 @@ jobs: # Usa CTest per eseguire i test, compresi quelli basati su Boost Unit Test Framework ctest -C ${{matrix.build_type}} --output-on-failure env: - PATH: ${{ steps.install-boost.outputs.BOOST_ROOT }} \ No newline at end of file + PATH: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage/lib:$PATH \ No newline at end of file From 4edd042da58f425fc87fb7c23fbb07c49899d1b2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 15:00:15 +0100 Subject: [PATCH 185/223] Refactor CI workflow to improve Boost path handling and debugging output --- .github/workflows/ci_minimal.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 81d037f..0d03019 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -64,8 +64,17 @@ jobs: echo "ASIO path: $AsioPath" dir $AsioPath - echo "BOOST path: ${{ steps.install-boost.outputs.BOOST_ROOT }}" - dir ${{ steps.install-boost.outputs.BOOST_ROOT }} + # Variabili esportate dall'azione MarkusJx/install-boost + $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}" + $BoostLibDir = "${{ steps.install-boost.outputs.BOOST_LIBRARYDIR }}" + + echo "ASIO path: $AsioPath" + echo "BOOST_ROOT path: $BoostRoot" + echo "BOOST_LIBRARYDIR path: $BoostLibDir" + + # DEBUG: Verifica se i percorsi esistono + dir $BoostRoot + dir $BoostLibDir # Esegue la configurazione CMake # Le variabili BOOST_ROOT e BOOST_LIBRARYDIR sono impostate dallo step precedente @@ -76,9 +85,11 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}/stage" + -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}" ` + -DBoost_ROOT="$BoostRoot" ` # Specifica la radice (per gli header) + -DBoost_LIBRARYDIR="$BoostLibDir" # Specifica la directory delle librerie (cruciale per il linking) env: - BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - name: 🔨 Build Project run: | @@ -90,4 +101,4 @@ jobs: # Usa CTest per eseguire i test, compresi quelli basati su Boost Unit Test Framework ctest -C ${{matrix.build_type}} --output-on-failure env: - PATH: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage/lib:$PATH \ No newline at end of file + PATH: ${{ steps.install-boost.outputs.BOOST_LIBRARYDIR }}:$PATH \ No newline at end of file From 407552edf8de24536f7a407894ecdd0a6320b852 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 1 Dec 2025 19:38:19 +0100 Subject: [PATCH 186/223] Update CI workflow to use staged Boost directory and enhance debug output --- .github/workflows/ci_minimal.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 0d03019..b52ec3d 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -65,19 +65,22 @@ jobs: dir $AsioPath # Variabili esportate dall'azione MarkusJx/install-boost - $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}" - $BoostLibDir = "${{ steps.install-boost.outputs.BOOST_LIBRARYDIR }}" + $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}/stage" echo "ASIO path: $AsioPath" echo "BOOST_ROOT path: $BoostRoot" - echo "BOOST_LIBRARYDIR path: $BoostLibDir" # DEBUG: Verifica se i percorsi esistono + echo "Contents of BOOST_ROOT:" dir $BoostRoot - dir $BoostLibDir + + echo "Contents of BOOST_ROOT/include:" + dir $BoostRoot/include + + echo "Contents of BOOST_ROOT/lib:" + dir $BoostRoot/lib # Esegue la configurazione CMake - # Le variabili BOOST_ROOT e BOOST_LIBRARYDIR sono impostate dallo step precedente cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` @@ -85,11 +88,9 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DBOOST_ROOT="${{ steps.install-boost.outputs.BOOST_ROOT }}" ` - -DBoost_ROOT="$BoostRoot" ` # Specifica la radice (per gli header) - -DBoost_LIBRARYDIR="$BoostLibDir" # Specifica la directory delle librerie (cruciale per il linking) + -DBOOST_ROOT="$BoostRoot" env: - BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage - name: 🔨 Build Project run: | @@ -101,4 +102,4 @@ jobs: # Usa CTest per eseguire i test, compresi quelli basati su Boost Unit Test Framework ctest -C ${{matrix.build_type}} --output-on-failure env: - PATH: ${{ steps.install-boost.outputs.BOOST_LIBRARYDIR }}:$PATH \ No newline at end of file + PATH: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage/lib/:$PATH \ No newline at end of file From ab1789a41ef646aaacab26ab6e42f5b48cd95b6e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 10:43:56 +0100 Subject: [PATCH 187/223] Remove redundant output for BOOST_ROOT include directory in CI workflow --- .github/workflows/ci_minimal.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index b52ec3d..925f0d2 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -74,9 +74,6 @@ jobs: echo "Contents of BOOST_ROOT:" dir $BoostRoot - echo "Contents of BOOST_ROOT/include:" - dir $BoostRoot/include - echo "Contents of BOOST_ROOT/lib:" dir $BoostRoot/lib From b90d88d5b6cb5365f17c40b6df34bbf007cc9e5e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:48:35 +0100 Subject: [PATCH 188/223] Update Boost configuration in CI workflow and CMake files for improved compatibility --- .github/workflows/ci_minimal.yml | 4 ++-- CMakeLists.txt | 6 ++++++ test/CMakeLists.txt | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 925f0d2..c830454 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -65,7 +65,7 @@ jobs: dir $AsioPath # Variabili esportate dall'azione MarkusJx/install-boost - $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}/stage" + $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}" echo "ASIO path: $AsioPath" echo "BOOST_ROOT path: $BoostRoot" @@ -87,7 +87,7 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBOOST_ROOT="$BoostRoot" env: - BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }}/stage + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - name: 🔨 Build Project run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index b204391..8b27e76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,12 @@ target_link_libraries(cli INTERFACE Threads::Threads) # Boost.Asio support # --------------------------------------------------------------- if(CLI_UseBoostAsio) + # Enable modern search for *_ROOT variables + cmake_policy(SET CMP0074 NEW) + + # Keep FindBoost enabled for compatibility + cmake_policy(SET CMP0167 OLD) + set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) add_definitions(-DBOOST_ALL_NO_LIB) # for windows diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 470a20f..56201df 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,6 +36,12 @@ set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows +# Enable modern search for *_ROOT variables +cmake_policy(SET CMP0074 NEW) + +# Keep FindBoost enabled for compatibility +cmake_policy(SET CMP0167 OLD) + find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise From 1f609d432512e4afe9d88a0dc0433a5fb568ca19 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:02:48 +0100 Subject: [PATCH 189/223] Update CMake policies for Boost integration and set BOOST_ROOT variable in CI workflow --- .github/workflows/ci_minimal.yml | 1 + CMakeLists.txt | 8 +++----- test/CMakeLists.txt | 8 +++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index c830454..3c74388 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -85,6 +85,7 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` + -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b27e76..73154f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,11 +66,9 @@ target_link_libraries(cli INTERFACE Threads::Threads) # Boost.Asio support # --------------------------------------------------------------- if(CLI_UseBoostAsio) - # Enable modern search for *_ROOT variables - cmake_policy(SET CMP0074 NEW) - - # Keep FindBoost enabled for compatibility - cmake_policy(SET CMP0167 OLD) + cmake_policy(SET CMP0074 NEW) # abilita _ROOT + cmake_policy(SET CMP0144 NEW) # abilita variabili maiuscole tipo BOOST_ROOT + cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 56201df..9be9e9e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,11 +36,9 @@ set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows -# Enable modern search for *_ROOT variables -cmake_policy(SET CMP0074 NEW) - -# Keep FindBoost enabled for compatibility -cmake_policy(SET CMP0167 OLD) +cmake_policy(SET CMP0074 NEW) # enable _ROOT +cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT +cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) From 06dd4b7dffaa030b8668454578e022f71081dad3 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:13:37 +0100 Subject: [PATCH 190/223] Update Boost package finding to use CONFIG mode for improved compatibility --- CMakeLists.txt | 3 ++- test/CMakeLists.txt | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73154f2..8f4d167 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,8 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.66 QUIET COMPONENTS system date_time) + ### find_package(Boost 1.66 QUIET COMPONENTS system date_time) + find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9be9e9e..7eb9dea 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,7 +40,9 @@ cmake_policy(SET CMP0074 NEW) # enable _ROOT cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions -find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) +### find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) +find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) + # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From 690fd4abfaa82b5fc55f3b13cd5fa7efd41a9b44 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:24:12 +0100 Subject: [PATCH 191/223] Refactor Boost package finding to use version-specific configuration and streamline CMake policies --- .github/workflows/ci_minimal.yml | 1 + CMakeLists.txt | 4 +--- test/CMakeLists.txt | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 3c74388..d49b3cf 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -89,6 +89,7 @@ jobs: -DBOOST_ROOT="$BoostRoot" env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + Boost_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - name: 🔨 Build Project run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f4d167..5684fd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,9 +71,7 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti set(Boost_NO_BOOST_CMAKE ON) - ### find_package(Boost 1.66 QUIET COMPONENTS system date_time) - find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) - add_definitions(-DBOOST_ALL_NO_LIB) # for windows + find_package(Boost 1.66 QUIET COMPONENTS system date_time) if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7eb9dea..e7d9112 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -40,8 +40,7 @@ cmake_policy(SET CMP0074 NEW) # enable _ROOT cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions -### find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) +find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise From 3a7889786a1f72895ed1ead88fb41822fb8af5a9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:25:43 +0100 Subject: [PATCH 192/223] Remove redundant Boost_ROOT environment variable in CI workflow --- .github/workflows/ci_minimal.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index d49b3cf..3c74388 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -89,7 +89,6 @@ jobs: -DBOOST_ROOT="$BoostRoot" env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - Boost_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} - name: 🔨 Build Project run: | From 073338ca33846d0d79fb2805a1ff1136f51f1b3d Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:37:35 +0100 Subject: [PATCH 193/223] Remove commented-out Boost CONFIG package finding and add definition for Windows compatibility --- CMakeLists.txt | 2 ++ test/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5684fd6..a69c2e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,8 @@ if(CLI_UseBoostAsio) set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) + ### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) + add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e7d9112..e14c66e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,7 +41,7 @@ cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) - +### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From 621bcaf339d84f8a560ae8fbccac2203298d53c5 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:58:42 +0100 Subject: [PATCH 194/223] Update Boost package finding to use CONFIG mode and clean up CMakeLists --- CMakeLists.txt | 6 +++--- test/CMakeLists.txt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a69c2e0..4d7d82f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,9 +70,9 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0144 NEW) # abilita variabili maiuscole tipo BOOST_ROOT cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti - set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.66 QUIET COMPONENTS system date_time) - ### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) + ### set(Boost_NO_BOOST_CMAKE ON) + ### find_package(Boost 1.66 QUIET COMPONENTS system date_time) + find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e14c66e..838b6c8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,15 +33,15 @@ enable_testing() set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") -set(Boost_NO_BOOST_CMAKE ON) +### set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows cmake_policy(SET CMP0074 NEW) # enable _ROOT cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions -find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) +### find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) +find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From baa36a97854229440e91493a4e9ed9d6a55d2c26 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:20:34 +0100 Subject: [PATCH 195/223] Enhance CI workflow by adding directory listings for Boost CMake files and updating CMAKE_PREFIX_PATH for boost_system --- .github/workflows/ci_minimal.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 3c74388..a7b889e 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -77,6 +77,12 @@ jobs: echo "Contents of BOOST_ROOT/lib:" dir $BoostRoot/lib + echo "Contents of BOOST_ROOT/lib/cmake:" + dir $BoostRoot/lib/cmake + + echo "Contents of BOOST_ROOT/lib/cmake/boost_system-1.89.0:" + dir $BoostRoot/lib/cmake/boost_system-1.89.0 + # Esegue la configurazione CMake cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` @@ -85,6 +91,7 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` + -DCMAKE_PREFIX_PATH="$BoostRoot/lib/cmake/boost_system-1.89.0" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" env: From 1d7b371d6aef153611ad86c425bb33ab5d21edee Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:31:58 +0100 Subject: [PATCH 196/223] Fix Boost directory references in CI workflow for consistency and accuracy --- .github/workflows/ci_minimal.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index a7b889e..90d6302 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -80,8 +80,8 @@ jobs: echo "Contents of BOOST_ROOT/lib/cmake:" dir $BoostRoot/lib/cmake - echo "Contents of BOOST_ROOT/lib/cmake/boost_system-1.89.0:" - dir $BoostRoot/lib/cmake/boost_system-1.89.0 + echo "Contents of BOOST_ROOT/lib/cmake/Boost-1.89.0:" + dir $BoostRoot/lib/cmake/Boost-1.89.0 # Esegue la configurazione CMake cmake -S . -B ./build ` @@ -91,7 +91,7 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DCMAKE_PREFIX_PATH="$BoostRoot/lib/cmake/boost_system-1.89.0" ` + -DCMAKE_PREFIX_PATH="$BoostRoot/lib/cmake/Boost-1.89.0" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" env: From efe769becc597ff51a1b75f76724c87570abf920 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:43:42 +0100 Subject: [PATCH 197/223] Refactor Boost package finding in CMake to improve compatibility and remove unnecessary configurations --- .github/workflows/ci_minimal.yml | 10 ++-------- CMakeLists.txt | 6 +++--- test/CMakeLists.txt | 6 +++--- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 90d6302..49b1f45 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -77,12 +77,6 @@ jobs: echo "Contents of BOOST_ROOT/lib:" dir $BoostRoot/lib - echo "Contents of BOOST_ROOT/lib/cmake:" - dir $BoostRoot/lib/cmake - - echo "Contents of BOOST_ROOT/lib/cmake/Boost-1.89.0:" - dir $BoostRoot/lib/cmake/Boost-1.89.0 - # Esegue la configurazione CMake cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` @@ -91,9 +85,9 @@ jobs: -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=ON ` -DASIO_INCLUDEDIR="$AsioPath" ` - -DCMAKE_PREFIX_PATH="$BoostRoot/lib/cmake/Boost-1.89.0" ` -DBoost_ROOT="$BoostRoot" ` - -DBOOST_ROOT="$BoostRoot" + -DBOOST_ROOT="$BoostRoot" ` + -DBoost_DEBUG=ON env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d7d82f..8f440fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,9 +70,9 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0144 NEW) # abilita variabili maiuscole tipo BOOST_ROOT cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti - ### set(Boost_NO_BOOST_CMAKE ON) - ### find_package(Boost 1.66 QUIET COMPONENTS system date_time) - find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) + set(Boost_NO_BOOST_CMAKE ON) + find_package(Boost 1.66 QUIET COMPONENTS system date_time) + # find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 838b6c8..e14c66e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,15 +33,15 @@ enable_testing() set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") -### set(Boost_NO_BOOST_CMAKE ON) +set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows cmake_policy(SET CMP0074 NEW) # enable _ROOT cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions -### find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) +find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) +### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From 9c352125d8d19b719247437f07c2e7ef41eaddff Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 15:52:33 +0100 Subject: [PATCH 198/223] Enable static library usage for Boost in CI workflow --- .github/workflows/ci_minimal.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 49b1f45..e95d9b2 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -87,6 +87,7 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" ` + -DBoost_USE_STATIC_LIBS=ON ` -DBoost_DEBUG=ON env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} From 39b882b95a890d27c9aec16880d896680d5dddb7 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:10:58 +0100 Subject: [PATCH 199/223] Update CI workflow to disable static Boost libraries and adjust include/library paths --- .github/workflows/ci_minimal.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index e95d9b2..32506dc 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -87,7 +87,11 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" ` - -DBoost_USE_STATIC_LIBS=ON ` + -DBoost_INCLUDE_DIR="$BoostRoot" ` + -DBoost_LIBRARY_DIR="$BoostRoot/lib" ` + -DCMAKE_PREFIX_PATH="$BoostRoot" ` + -DBoost_USE_STATIC_LIBS=OFF ` + -DBoost_USE_STATIC_RUNTIME=OFF ` -DBoost_DEBUG=ON env: BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} From 5898488660e6a62db93395f406acc7d1087c385c Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 16:55:27 +0100 Subject: [PATCH 200/223] Add boost_install_dir variable to CI workflow for improved Boost installation path --- .github/workflows/ci_minimal.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 32506dc..9470ad3 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -44,6 +44,7 @@ jobs: # A list of supported versions can be found here: # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json boost_version: 1.89.0 + boost_install_dir: ${{ runner.temp }}/boost - name: 🔗 Setup Other Dependencies (Asio) run: | From 8827dfc0f4d72c99dfdcc7525d3a7fc21e5841d2 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:25:05 +0100 Subject: [PATCH 201/223] Update Boost installation directory in CI workflow for consistency --- .github/workflows/ci_minimal.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 9470ad3..5e5148d 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -44,7 +44,7 @@ jobs: # A list of supported versions can be found here: # https://github.com/MarkusJx/prebuilt-boost/blob/main/versions-manifest.json boost_version: 1.89.0 - boost_install_dir: ${{ runner.temp }}/boost + boost_install_dir: ${{ runner.temp }} - name: 🔗 Setup Other Dependencies (Asio) run: | @@ -88,8 +88,6 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" ` - -DBoost_INCLUDE_DIR="$BoostRoot" ` - -DBoost_LIBRARY_DIR="$BoostRoot/lib" ` -DCMAKE_PREFIX_PATH="$BoostRoot" ` -DBoost_USE_STATIC_LIBS=OFF ` -DBoost_USE_STATIC_RUNTIME=OFF ` From 98fc2758194c395831efb738ef85f3133637dea8 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 17:36:40 +0100 Subject: [PATCH 202/223] Add Boost include and library directory variables to CI workflow --- .github/workflows/ci_minimal.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 5e5148d..61ec6a2 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -88,6 +88,8 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" ` + -DBoost_INCLUDE_DIR="$BoostRoot"/include ` + -DBoost_LIBRARY_DIR="$BoostRoot/lib" ` -DCMAKE_PREFIX_PATH="$BoostRoot" ` -DBoost_USE_STATIC_LIBS=OFF ` -DBoost_USE_STATIC_RUNTIME=OFF ` From 8512da14435238160f3dbb29d2b9202b2f35ae71 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 18:04:36 +0100 Subject: [PATCH 203/223] Normalize BoostRoot path separators in CI workflow --- .github/workflows/ci_minimal.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 61ec6a2..733af10 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -67,6 +67,7 @@ jobs: # Variabili esportate dall'azione MarkusJx/install-boost $BoostRoot = "${{ steps.install-boost.outputs.BOOST_ROOT }}" + $BoostRoot = $BoostRoot -replace "\\", "/" echo "ASIO path: $AsioPath" echo "BOOST_ROOT path: $BoostRoot" From 2aba5bf713a23b06a3a78f83eee21f9836f02c62 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 2 Dec 2025 18:42:24 +0100 Subject: [PATCH 204/223] Fix Boost_INCLUDE_DIR path in CI workflow for correct directory reference --- .github/workflows/ci_minimal.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml index 733af10..d22b7b3 100644 --- a/.github/workflows/ci_minimal.yml +++ b/.github/workflows/ci_minimal.yml @@ -89,7 +89,7 @@ jobs: -DASIO_INCLUDEDIR="$AsioPath" ` -DBoost_ROOT="$BoostRoot" ` -DBOOST_ROOT="$BoostRoot" ` - -DBoost_INCLUDE_DIR="$BoostRoot"/include ` + -DBoost_INCLUDE_DIR="$BoostRoot" ` -DBoost_LIBRARY_DIR="$BoostRoot/lib" ` -DCMAKE_PREFIX_PATH="$BoostRoot" ` -DBoost_USE_STATIC_LIBS=OFF ` From faf3371574173f6e140fd03d0dd24996807139a9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:18:20 +0100 Subject: [PATCH 205/223] Restore old CI scripts and disable win test execution --- .github/workflows/{ci.yml.disabled => ci.yml} | 4 ++-- .github/workflows/{ci_minimal.yml => ci_minimal.yml.disabled} | 0 .github/workflows/{macos_ci.yml.disabled => macos_ci.yml} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{ci.yml.disabled => ci.yml} (96%) rename .github/workflows/{ci_minimal.yml => ci_minimal.yml.disabled} (100%) rename .github/workflows/{macos_ci.yml.disabled => macos_ci.yml} (100%) diff --git a/.github/workflows/ci.yml.disabled b/.github/workflows/ci.yml similarity index 96% rename from .github/workflows/ci.yml.disabled rename to .github/workflows/ci.yml index 29bf721..4144611 100644 --- a/.github/workflows/ci.yml.disabled +++ b/.github/workflows/ci.yml @@ -115,8 +115,8 @@ jobs: cmake --build ./build --config ${{matrix.build_type}} - name: run tests - # on windows test_suite throws an exception, but only on the CI environment! - # if: runner.os != 'Windows' + # on windows test_suite throws an exception because it cannot find boost libraries path :-( + if: runner.os != 'Windows' working-directory: ./build run: | ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/ci_minimal.yml b/.github/workflows/ci_minimal.yml.disabled similarity index 100% rename from .github/workflows/ci_minimal.yml rename to .github/workflows/ci_minimal.yml.disabled diff --git a/.github/workflows/macos_ci.yml.disabled b/.github/workflows/macos_ci.yml similarity index 100% rename from .github/workflows/macos_ci.yml.disabled rename to .github/workflows/macos_ci.yml From 9928da8203e10f53b36153a8fac5002d4c300e03 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 16 Dec 2025 17:52:08 +0100 Subject: [PATCH 206/223] Use target_compile_definitions instead of add_definitions for _WIN32_WINNT define --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f440fe..53b7a00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,7 +126,8 @@ target_compile_features(cli INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) if(WIN32) # Set _WIN32_WINNT for Windows 10+ if(NOT DEFINED _WIN32_WINNT) - add_definitions(-D_WIN32_WINNT=0x0A00) + # add_definitions(-D_WIN32_WINNT=0x0A00) + target_compile_definitions(cli PRIVATE _WIN32_WINNT=0x0A00) endif() endif() From a4f4a5931d224aa1d97e99f537081e345f8a1927 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Tue, 16 Dec 2025 18:18:45 +0100 Subject: [PATCH 207/223] Add mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) --- CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53b7a00..e013f11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,9 +66,9 @@ target_link_libraries(cli INTERFACE Threads::Threads) # Boost.Asio support # --------------------------------------------------------------- if(CLI_UseBoostAsio) - cmake_policy(SET CMP0074 NEW) # abilita _ROOT - cmake_policy(SET CMP0144 NEW) # abilita variabili maiuscole tipo BOOST_ROOT - cmake_policy(SET CMP0167 OLD) # riattiva FindBoost per CMake recenti + cmake_policy(SET CMP0074 NEW) # enable _ROOT + cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT + cmake_policy(SET CMP0167 OLD) # restore FindBoost for newest CMake set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) @@ -101,9 +101,10 @@ endif() # Standalone Asio support # --------------------------------------------------------------- if(CLI_UseStandaloneAsio) - find_path(STANDALONE_ASIO_INCLUDE_PATH "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) + find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) + mark_as_advanced(STANDALONE_ASIO_INCLUDE_PATH) if(NOT STANDALONE_ASIO_INCLUDE_PATH) - message(FATAL_ERROR "Standalone Asio headers not found") + message(FATAL_ERROR "Standalone Asio headers not found. Set ASIO_INCLUDEDIR or STANDALONE_ASIO_INCLUDE_PATH.") endif() add_library(standalone_asio INTERFACE IMPORTED) @@ -126,8 +127,7 @@ target_compile_features(cli INTERFACE cxx_std_${CMAKE_CXX_STANDARD}) if(WIN32) # Set _WIN32_WINNT for Windows 10+ if(NOT DEFINED _WIN32_WINNT) - # add_definitions(-D_WIN32_WINNT=0x0A00) - target_compile_definitions(cli PRIVATE _WIN32_WINNT=0x0A00) + add_definitions(-D_WIN32_WINNT=0x0A00) endif() endif() From c4faf436ddc442d68e9044360a0e73ac73aba59a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 10:58:06 +0100 Subject: [PATCH 208/223] Comment out target_include_directories for Boost_INCLUDE_DIRS in CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e013f11..3f286f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ if(CLI_UseBoostAsio) if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") - target_include_directories(cli INTERFACE ${Boost_INCLUDE_DIRS}) + # target_include_directories(cli INTERFACE ${Boost_INCLUDE_DIRS}) target_link_libraries(cli INTERFACE Boost::system Boost::date_time) else() message(STATUS "Boost libraries not found. Falling back to header-only mode.") From 023e7b7926f4a0e8198e7e6690d384d94ebbdb3e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:39:20 +0100 Subject: [PATCH 209/223] Remove boost datetime from build --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f286f2..03525d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,14 +71,13 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0167 OLD) # restore FindBoost for newest CMake set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.66 QUIET COMPONENTS system date_time) - # find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system date_time) + find_package(Boost 1.66 QUIET COMPONENTS system) + # find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system) add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") - # target_include_directories(cli INTERFACE ${Boost_INCLUDE_DIRS}) - target_link_libraries(cli INTERFACE Boost::system Boost::date_time) + target_link_libraries(cli INTERFACE Boost::system Boost) else() message(STATUS "Boost libraries not found. Falling back to header-only mode.") target_compile_definitions(cli INTERFACE From e3381d9add16b99cd24bf97756ea978efa4ef81f Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:54:05 +0100 Subject: [PATCH 210/223] Update macOS CI workflow and CMakeLists to include Boost date_time component --- .github/workflows/macos_ci.yml | 1 - CMakeLists.txt | 5 ++--- test/CMakeLists.txt | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 6cf0a6c..1b8990c 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -38,7 +38,6 @@ jobs: - name: setup dependencies run: | brew update - brew install ninja brew install boost brew install asio diff --git a/CMakeLists.txt b/CMakeLists.txt index 03525d2..743b739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,13 +71,12 @@ if(CLI_UseBoostAsio) cmake_policy(SET CMP0167 OLD) # restore FindBoost for newest CMake set(Boost_NO_BOOST_CMAKE ON) - find_package(Boost 1.66 QUIET COMPONENTS system) - # find_package(Boost CONFIG REQUIRED QUIET COMPONENTS system) + find_package(Boost 1.66 QUIET COMPONENTS system date_time) add_definitions(-DBOOST_ALL_NO_LIB) # for windows if(Boost_FOUND) message(STATUS "Using compiled Boost libraries on ${CMAKE_SYSTEM_NAME}") - target_link_libraries(cli INTERFACE Boost::system Boost) + target_link_libraries(cli INTERFACE Boost::system Boost::date_time) else() message(STATUS "Boost libraries not found. Falling back to header-only mode.") target_compile_definitions(cli INTERFACE diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e14c66e..9be9e9e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -41,7 +41,6 @@ cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system) -### find_package(Boost CONFIG REQUIRED QUIET COMPONENTS unit_test_framework system) # finds standalone asio, triggers an error otherwise find_path(STANDALONE_ASIO_INCLUDE_PATH NAMES "asio.hpp" HINTS ${ASIO_INCLUDEDIR}) From cdaa93f6045759eed164ca3db5e55f3381c4ea93 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 13:46:01 +0100 Subject: [PATCH 211/223] Add use standalone asio variant in CI matrix --- .github/workflows/ci.yml | 3 ++- .github/workflows/macos_ci.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4144611..fc54763 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,7 @@ jobs: compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] + use_boost_asio: [ON, OFF] exclude: # Exclude msvc on non-Windows platforms - os: ubuntu-22.04 @@ -92,7 +93,7 @@ jobs: -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` -DCLI_BuildTests=ON ` -DCLI_BuildExamples=ON ` - -DCLI_UseBoostAsio=ON ` + -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} ` -DASIO_INCLUDEDIR="$AsioPath" - name: Set Boost DLL Path - Windows diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 1b8990c..bdeec2f 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -13,6 +13,7 @@ jobs: compiler: [apple-clang, llvm-18, llvm-19] standard: [14, 17, 20, 23, 26] build_type: [Release, Debug] + use_boost_asio: [ON, OFF] steps: - name: Checkout repository @@ -50,7 +51,7 @@ jobs: -DCMAKE_CXX_FLAGS="-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_LIB" \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=ON + -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} ` - name: Build run: | From a126d78b692a39c156e4443385c393f48ce1f530 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:20:14 +0100 Subject: [PATCH 212/223] Add use standalone asio variant in CI matrix --- .github/workflows/ci.yml | 10 +++++++++- .github/workflows/macos_ci.yml | 3 ++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc54763..abb3e1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,14 @@ jobs: - name: Configure CMake - Unix if: runner.os != 'Windows' run: | - cmake -S . -B ./build -G "Ninja Multi-Config" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DCMAKE_CXX_STANDARD=${{matrix.standard}} -DCLI_BuildTests=ON -DCLI_BuildExamples=ON -DCLI_UseBoostAsio=ON + cmake -S . -B ./build \ + -G "Ninja Multi-Config" \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") - name: Configure CMake - Windows # windows need asio library path @@ -94,6 +101,7 @@ jobs: -DCLI_BuildTests=ON ` -DCLI_BuildExamples=ON ` -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} ` + -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") ` -DASIO_INCLUDEDIR="$AsioPath" - name: Set Boost DLL Path - Windows diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index bdeec2f..4515ace 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -51,7 +51,8 @@ jobs: -DCMAKE_CXX_FLAGS="-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_LIB" \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} ` + -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") - name: Build run: | From 6dd0e85dda08137e19f00f64d676a6087440c61a Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Wed, 17 Dec 2025 15:54:16 +0100 Subject: [PATCH 213/223] Add case loop scheduler to CI --- .github/workflows/ci.yml | 13 ++++++++----- .github/workflows/macos_ci.yml | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abb3e1e..77a76d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] - use_boost_asio: [ON, OFF] + asio_library: [boost, standalone, none] exclude: # Exclude msvc on non-Windows platforms - os: ubuntu-22.04 @@ -78,8 +78,8 @@ jobs: -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} \ - -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") + -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") - name: Configure CMake - Windows # windows need asio library path @@ -95,13 +95,16 @@ jobs: echo "ASIO path: $AsioPath" dir $AsioPath + $UseBoostAsio = if ("${{ matrix.asio_library }}" -eq "boost") { "ON" } else { "OFF" } + $UseStandaloneAsio = if ("${{ matrix.asio_library }}" -eq "standalone") { "ON" } else { "OFF" } + cmake -S . -B ./build ` -DCMAKE_BUILD_TYPE:STRING=${{ matrix.build_type }} ` -DCMAKE_CXX_STANDARD=${{ matrix.standard }} ` -DCLI_BuildTests=ON ` -DCLI_BuildExamples=ON ` - -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} ` - -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") ` + -DCLI_UseBoostAsio=$UseBoostAsio ` + -DCLI_UseStandaloneAsio=$UseStandaloneAsio ` -DASIO_INCLUDEDIR="$AsioPath" - name: Set Boost DLL Path - Windows diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 4515ace..1c9d27e 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -13,7 +13,7 @@ jobs: compiler: [apple-clang, llvm-18, llvm-19] standard: [14, 17, 20, 23, 26] build_type: [Release, Debug] - use_boost_asio: [ON, OFF] + asio_library: [boost, standalone, none] steps: - name: Checkout repository @@ -51,8 +51,8 @@ jobs: -DCMAKE_CXX_FLAGS="-DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_LIB" \ -DCLI_BuildTests=ON \ -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=${{ matrix.use_boost_asio }} \ - -DCLI_UseStandaloneAsio=$([ "${{ matrix.use_boost_asio }}" == "ON" ] && echo "OFF" || echo "ON") + -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") - name: Build run: | From 378d46c62307f53a0cdba0a7f708bfb05aa8d8a6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:58:56 +0100 Subject: [PATCH 214/223] Split CI scripts for win and ubuntu --- .github/workflows/ubuntu_ci.yml | 61 ++++++++++++++++++++++ .github/workflows/{ci.yml => win_ci.yml} | 64 +++++------------------- 2 files changed, 73 insertions(+), 52 deletions(-) create mode 100644 .github/workflows/ubuntu_ci.yml rename .github/workflows/{ci.yml => win_ci.yml} (56%) diff --git a/.github/workflows/ubuntu_ci.yml b/.github/workflows/ubuntu_ci.yml new file mode 100644 index 0000000..933e523 --- /dev/null +++ b/.github/workflows/ubuntu_ci.yml @@ -0,0 +1,61 @@ +name: CI linux + +on: [push,pull_request] + +jobs: + Test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + + matrix: + os: [ubuntu-22.04] + compiler: [llvm-17.0.2, clang++-15, gcc-11] + standard: [14, 17, 20, 23] + build_type: [Release, Debug] + asio_library: [boost, standalone, none] + + steps: + - uses: actions/checkout@v4 + + - name: Setup Cpp + uses: aminya/setup-cpp@v1 + with: + compiler: ${{ matrix.compiler }} + vcvarsall: false + + cmake: true + ninja: true + vcpkg: false + ccache: true + clangtidy: true + + cppcheck: true + + gcovr: true + opencppcoverage: true + + - name: setup dependencies + run: | + sudo apt-get -y update + sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev + + if: runner.os != 'Windows' + run: | + cmake -S . -B ./build \ + -G "Ninja Multi-Config" \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") + + - name: Build + run: | + cmake --build ./build --config ${{matrix.build_type}} + + - name: run tests + working-directory: ./build + run: | + ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/ci.yml b/.github/workflows/win_ci.yml similarity index 56% rename from .github/workflows/ci.yml rename to .github/workflows/win_ci.yml index 77a76d3..762009e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/win_ci.yml @@ -1,4 +1,4 @@ -name: CI linux and windows +name: CI windows on: [push,pull_request] @@ -9,38 +9,20 @@ jobs: fail-fast: false matrix: - os: [ubuntu-22.04, windows-2022, windows-2025] - compiler: [llvm-17.0.2, clang++-15, gcc-11, msvc] + os: [windows-2022, windows-2025] + compiler: [clang++-15, msvc] standard: [14, 17, 20, 23] build_type: [Release, Debug] asio_library: [boost, standalone, none] - exclude: - # Exclude msvc on non-Windows platforms - - os: ubuntu-22.04 - compiler: msvc - # Exclude gcc on Windows platforms - - os: windows-2022 - compiler: gcc-11 - - os: windows-2025 - compiler: gcc-11 - # Exclude llvm on Windows platforms - - os: windows-2022 - compiler: llvm-17.0.2 - - os: windows-2025 - compiler: llvm-17.0.2 steps: - uses: actions/checkout@v4 - # - name: Set up MSVC - # if: runner.os == 'Windows' - # uses: ilammy/msvc-dev-cmd@v1 - - name: Setup Cpp uses: aminya/setup-cpp@v1 with: compiler: ${{ matrix.compiler }} - vcvarsall: ${{ contains(matrix.os, 'windows' )}} + vcvarsall: true cmake: true ninja: true @@ -53,14 +35,7 @@ jobs: gcovr: true opencppcoverage: true - - name: setup dependencies - Unix - if: runner.os == 'Linux' - run: | - sudo apt-get -y update - sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev - - - name: setup dependencies - Windows - if: runner.os == 'Windows' + - name: setup dependencies run: | choco install ninja choco install boost-msvc-14.1 @@ -69,21 +44,8 @@ jobs: tar -xf asio.zip move asio-asio-1-18-2 asio - - name: Configure CMake - Unix - if: runner.os != 'Windows' - run: | - cmake -S . -B ./build \ - -G "Ninja Multi-Config" \ - -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ - -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ - -DCLI_BuildTests=ON \ - -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ - -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") - - - name: Configure CMake - Windows + - name: Configure CMake # windows need asio library path - if: runner.os == 'Windows' run: | Start-Sleep -Seconds 2 @@ -107,8 +69,7 @@ jobs: -DCLI_UseStandaloneAsio=$UseStandaloneAsio ` -DASIO_INCLUDEDIR="$AsioPath" - - name: Set Boost DLL Path - Windows - if: runner.os == 'Windows' + - name: Set Boost DLL Path run: | # Find the directory of Boost DLLs installed by choco (usually in 'lib' under the root) $boostPath = "C:\ProgramData\chocolatey\lib\boost-msvc-14.1.*\lib" @@ -126,9 +87,8 @@ jobs: run: | cmake --build ./build --config ${{matrix.build_type}} - - name: run tests - # on windows test_suite throws an exception because it cannot find boost libraries path :-( - if: runner.os != 'Windows' - working-directory: ./build - run: | - ctest -C ${{matrix.build_type}} --output-on-failure +# on windows test_suite throws an exception because it cannot find boost libraries path :-( +# - name: run tests +# working-directory: ./build +# run: | +# ctest -C ${{matrix.build_type}} --output-on-failure From 08dcef4ef2edf3bf343ef1daec12bbfda26a4226 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Thu, 18 Dec 2025 23:02:33 +0100 Subject: [PATCH 215/223] Fix CI ubuntu --- .github/workflows/ubuntu_ci.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/ubuntu_ci.yml b/.github/workflows/ubuntu_ci.yml index 933e523..aeb6729 100644 --- a/.github/workflows/ubuntu_ci.yml +++ b/.github/workflows/ubuntu_ci.yml @@ -40,17 +40,6 @@ jobs: sudo apt-get -y update sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev - if: runner.os != 'Windows' - run: | - cmake -S . -B ./build \ - -G "Ninja Multi-Config" \ - -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ - -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ - -DCLI_BuildTests=ON \ - -DCLI_BuildExamples=ON \ - -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ - -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") - - name: Build run: | cmake --build ./build --config ${{matrix.build_type}} From 2a3ad0af004b6483d1187d31b26c63846930320b Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:28:40 +0100 Subject: [PATCH 216/223] Fix ubuntu CI --- .github/workflows/ubuntu_ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/ubuntu_ci.yml b/.github/workflows/ubuntu_ci.yml index aeb6729..43d937e 100644 --- a/.github/workflows/ubuntu_ci.yml +++ b/.github/workflows/ubuntu_ci.yml @@ -40,6 +40,17 @@ jobs: sudo apt-get -y update sudo apt-get -y install -y ninja-build libboost-all-dev libasio-dev + - name: Configure CMake + run: | + cmake -S . -B ./build \ + -G "Ninja Multi-Config" \ + -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.standard}} \ + -DCLI_BuildTests=ON \ + -DCLI_BuildExamples=ON \ + -DCLI_UseBoostAsio=$([ "${{ matrix.asio_library }}" == "boost" ] && echo "ON" || echo "OFF") \ + -DCLI_UseStandaloneAsio=$([ "${{ matrix.asio_library }}" == "standalone" ] && echo "ON" || echo "OFF") + - name: Build run: | cmake --build ./build --config ${{matrix.build_type}} From e13a470a00efa16b85d5eb66ac8e72b61e5ce7cb Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Fri, 19 Dec 2025 12:24:09 +0100 Subject: [PATCH 217/223] Improve cmake_minimum_required --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 743b739..3aa0e2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.8...3.31) project( cli diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9be9e9e..c00e1a5 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.8...3.31) project(cli_test) enable_testing() From 74029f1f2d41e7c0a7231981d2a02024a0dba0c9 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 20 Dec 2025 11:36:32 +0100 Subject: [PATCH 218/223] cmake minimum set to interval 3.8 ... 3.27 --- CMakeLists.txt | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea38b70..c3a1cb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -cmake_minimum_required(VERSION 3.8...3.31) +cmake_minimum_required(VERSION 3.8...3.27) project( cli diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c00e1a5..fcd631d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -27,7 +27,7 @@ # DEALINGS IN THE SOFTWARE. ################################################################################ -cmake_minimum_required(VERSION 3.8...3.31) +cmake_minimum_required(VERSION 3.8...3.27) project(cli_test) enable_testing() From dcd2dd428f7194276d248c13fedc3e38822a6acf Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Sat, 20 Dec 2025 18:37:01 +0100 Subject: [PATCH 219/223] Refactor Windows CI workflow to use Invoke-WebRequest for Asio download --- .github/workflows/win_ci.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 762009e..6eaa33e 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -37,15 +37,17 @@ jobs: - name: setup dependencies run: | - choco install ninja - choco install boost-msvc-14.1 - # Download and extract Asio - curl -L -o asio.zip https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip - tar -xf asio.zip - move asio-asio-1-18-2 asio + choco install boost-msvc-14.1 + + Invoke-WebRequest ` + -Uri https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip ` + -OutFile asio.zip + + tar -xf asio.zip + move asio-asio-1-18-2 asio + - name: Configure CMake - # windows need asio library path run: | Start-Sleep -Seconds 2 From 8dfbc33f4ec12a050a9ba2add8bdce5d8fadd4bb Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 22 Dec 2025 09:59:18 +0100 Subject: [PATCH 220/223] Add cache to boost download in win CI --- .github/workflows/win_ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 6eaa33e..56f5773 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -18,6 +18,12 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Cache Boost + uses: actions/cache@v4 + with: + path: C:\ProgramData\chocolatey\lib\boost-msvc-14.1* + key: boost-msvc-14.1 + - name: Setup Cpp uses: aminya/setup-cpp@v1 with: @@ -37,7 +43,7 @@ jobs: - name: setup dependencies run: | - choco install boost-msvc-14.1 + choco install boost-msvc-14.1 --no-progress --limit-output Invoke-WebRequest ` -Uri https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip ` @@ -49,8 +55,6 @@ jobs: - name: Configure CMake run: | - Start-Sleep -Seconds 2 - # Correctly constructs the path for Windows $AsioPath = Join-Path $env:GITHUB_WORKSPACE "asio/asio/include" # Converts to forward slash (CMake handles them better) From 020b6c0e07112f0ff79970a473eaa40a8d15f7a6 Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:38:21 +0100 Subject: [PATCH 221/223] Remove cache to boost download in win CI and simplify matrix. --- .github/workflows/macos_ci.yml | 2 +- .github/workflows/ubuntu_ci.yml | 2 +- .github/workflows/win_ci.yml | 8 +------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/macos_ci.yml b/.github/workflows/macos_ci.yml index 1c9d27e..ee9801f 100644 --- a/.github/workflows/macos_ci.yml +++ b/.github/workflows/macos_ci.yml @@ -11,7 +11,7 @@ jobs: matrix: os: [macos-15, macos-26] compiler: [apple-clang, llvm-18, llvm-19] - standard: [14, 17, 20, 23, 26] + standard: [14, 26] build_type: [Release, Debug] asio_library: [boost, standalone, none] diff --git a/.github/workflows/ubuntu_ci.yml b/.github/workflows/ubuntu_ci.yml index 43d937e..39ede18 100644 --- a/.github/workflows/ubuntu_ci.yml +++ b/.github/workflows/ubuntu_ci.yml @@ -11,7 +11,7 @@ jobs: matrix: os: [ubuntu-22.04] compiler: [llvm-17.0.2, clang++-15, gcc-11] - standard: [14, 17, 20, 23] + standard: [14, 23] build_type: [Release, Debug] asio_library: [boost, standalone, none] diff --git a/.github/workflows/win_ci.yml b/.github/workflows/win_ci.yml index 56f5773..a253435 100644 --- a/.github/workflows/win_ci.yml +++ b/.github/workflows/win_ci.yml @@ -11,19 +11,13 @@ jobs: matrix: os: [windows-2022, windows-2025] compiler: [clang++-15, msvc] - standard: [14, 17, 20, 23] + standard: [14, 23] build_type: [Release, Debug] asio_library: [boost, standalone, none] steps: - uses: actions/checkout@v4 - - name: Cache Boost - uses: actions/cache@v4 - with: - path: C:\ProgramData\chocolatey\lib\boost-msvc-14.1* - key: boost-msvc-14.1 - - name: Setup Cpp uses: aminya/setup-cpp@v1 with: From f2117987fc2a46250d39125e2184310ca9dbc62e Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 22 Dec 2025 12:02:37 +0100 Subject: [PATCH 222/223] Fix README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 46e8926..113096c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -[![CI of Cli](https://github.com/daniele77/cli/actions/workflows/ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/ci.yml) +[![ubuntu CI of Cli](https://github.com/daniele77/cli/actions/workflows/ubuntu_ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/ubuntu_ci.yml) +[![win CI of Cli](https://github.com/daniele77/cli/actions/workflows/win_ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/win_ci.yml) +[![macos CI of Cli](https://github.com/daniele77/cli/actions/workflows/macos_ci.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/macos_ci.yml) [![CodeQL](https://github.com/daniele77/cli/actions/workflows/codeql.yml/badge.svg)](https://github.com/daniele77/cli/actions/workflows/codeql.yml) [:heart: Sponsor](https://github.com/sponsors/daniele77) From 769c5fa060b94b39e43e1d6554775af7e73928cc Mon Sep 17 00:00:00 2001 From: Daniele Pallastrelli <5451767+daniele77@users.noreply.github.com> Date: Mon, 22 Dec 2025 19:51:46 +0100 Subject: [PATCH 223/223] Fix policies for old versions of cmake --- CMakeLists.txt | 15 ++++++++++++--- test/CMakeLists.txt | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3a1cb6..7afe32a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,9 +65,18 @@ target_link_libraries(cli INTERFACE Threads::Threads) # Boost.Asio support # --------------------------------------------------------------- if(CLI_UseBoostAsio) - cmake_policy(SET CMP0074 NEW) # enable _ROOT - cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT - cmake_policy(SET CMP0167 OLD) # restore FindBoost for newest CMake + if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) # _ROOT + endif() + + if(POLICY CMP0144) + cmake_policy(SET CMP0144 NEW) # uppercase variables like BOOST_ROOT + endif() + + if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) # re-enable FindBoost + endif() + set(Boost_NO_BOOST_CMAKE ON) find_package(Boost 1.66 QUIET COMPONENTS system date_time) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fcd631d..36e64a7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,9 +36,18 @@ set(Boost_ADDITIONAL_VERSIONS "1.66" "1.66.0") set(Boost_NO_BOOST_CMAKE ON) add_definitions( -DBOOST_ALL_NO_LIB ) # for windows -cmake_policy(SET CMP0074 NEW) # enable _ROOT -cmake_policy(SET CMP0144 NEW) # enable uppercase variables like BOOST_ROOT -cmake_policy(SET CMP0167 OLD) # re-enable FindBoost for recent CMake versions +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) # _ROOT +endif() + +if(POLICY CMP0144) + cmake_policy(SET CMP0144 NEW) # uppercase variables like BOOST_ROOT +endif() + +if(POLICY CMP0167) + cmake_policy(SET CMP0167 OLD) # re-enable FindBoost +endif() + find_package(Boost 1.66 QUIET COMPONENTS unit_test_framework system)