diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f9149b74..5b972bb4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -120,6 +120,38 @@ jobs: name: ${{ runner.os }}-coverage files: ./build/coverage.xml + test_modules: + name: "Test modules" + runs-on: ubuntu-latest + steps: + - name: "Checkout repository" + uses: actions/checkout@v3 + + - name: "Install cmake" + uses: lukka/get-cmake@latest + + - name: "Install ninja" + run: sudo apt-get install ninja-build + + - name: "Generate ./examples_modules" + run: > + ./tools/generate_examples_modules.sh + + - name: "Build modules" + run: > + mkdir build; + cd build; + cmake .. + -DCMAKE_GENERATOR=Ninja + -DCMAKE_BUILD_TYPE=Debug + -DFTXUI_BUILD_DOCS=OFF + -DFTXUI_BUILD_EXAMPLES=ON + -DFTXUI_BUILD_TESTS=OFF + -DFTXUI_BUILD_TESTS_FUZZER=OFF + -DFTXUI_ENABLE_INSTALL=ON + -DFTXUI_DEV_WARNINGS=ON ; + cmake --build . + # Create a release on new v* tags release: needs: test diff --git a/CMakeLists.txt b/CMakeLists.txt index 6845d38b..c9a9edc6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.28) project(ftxui LANGUAGES CXX @@ -6,16 +6,16 @@ project(ftxui DESCRIPTION "C++ Functional Terminal User Interface." ) -option(FTXUI_QUIET "Set to ON for FTXUI to be quiet" OFF) -option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" OFF) option(FTXUI_BUILD_DOCS "Set to ON to build docs" OFF) +option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" OFF) +option(FTXUI_BUILD_MODULES "Build the C++20 modules" OFF) option(FTXUI_BUILD_TESTS "Set to ON to build tests" OFF) option(FTXUI_BUILD_TESTS_FUZZER "Set to ON to enable fuzzing" OFF) -option(FTXUI_ENABLE_INSTALL "Generate the install target" ON) option(FTXUI_CLANG_TIDY "Execute clang-tidy" OFF) -option(FTXUI_ENABLE_COVERAGE "Execute code coverage" OFF) option(FTXUI_DEV_WARNINGS "Enable more compiler warnings and warnings as errors" OFF) -option(FTXUI_BUILD_MODULES "Build the C++20 modules" OFF) +option(FTXUI_ENABLE_COVERAGE "Execute code coverage" OFF) +option(FTXUI_ENABLE_INSTALL "Generate the install target" ON) +option(FTXUI_QUIET "Set to ON for FTXUI to be quiet" OFF) set(FTXUI_MICROSOFT_TERMINAL_FALLBACK_HELP_TEXT "On windows, assume the \ terminal used will be one of Microsoft and use a set of reasonnable fallback \ @@ -179,5 +179,11 @@ include(cmake/ftxui_install.cmake) include(cmake/ftxui_package.cmake) include(cmake/ftxui_modules.cmake) -add_subdirectory(examples) add_subdirectory(doc) +add_subdirectory(examples) + +# You can generate ./examples_modules/ by running +# ./tools/generate_examples_modules.sh +if(EXISTS "examples_modules") + add_subdirectory(examples_modules) +endif() diff --git a/cmake/ftxui_message.cmake b/cmake/ftxui_message.cmake index 28ca5b4e..5f25f1ac 100644 --- a/cmake/ftxui_message.cmake +++ b/cmake/ftxui_message.cmake @@ -5,14 +5,14 @@ function(ftxui_message msg) endfunction() ftxui_message("┌─ FTXUI options ─────────────────────") -ftxui_message("│ FTXUI_ENABLE_INSTALL : ${FTXUI_ENABLE_INSTALL}") -ftxui_message("│ FTXUI_BUILD_EXAMPLES : ${FTXUI_BUILD_EXAMPLES}") -ftxui_message("│ FTXUI_QUIET : ${FTXUI_QUIET}") ftxui_message("│ FTXUI_BUILD_DOCS : ${FTXUI_BUILD_DOCS}") +ftxui_message("│ FTXUI_BUILD_EXAMPLES : ${FTXUI_BUILD_EXAMPLES}") +ftxui_message("│ FTXUI_BUILD_MODULES : ${FTXUI_BUILD_MODULES}") ftxui_message("│ FTXUI_BUILD_TESTS : ${FTXUI_BUILD_TESTS}") ftxui_message("│ FTXUI_BUILD_TESTS_FUZZER : ${FTXUI_BUILD_TESTS_FUZZER}") -ftxui_message("│ FTXUI_ENABLE_COVERAGE : ${FTXUI_ENABLE_COVERAGE}") -ftxui_message("│ FTXUI_DEV_WARNINGS : ${FTXUI_DEV_WARNINGS}") ftxui_message("│ FTXUI_CLANG_TIDY : ${FTXUI_CLANG_TIDY}") -ftxui_message("│ FTXUI_BUILD_MODULES : ${FTXUI_BUILD_MODULES}") +ftxui_message("│ FTXUI_DEV_WARNINGS : ${FTXUI_DEV_WARNINGS}") +ftxui_message("│ FTXUI_ENABLE_COVERAGE : ${FTXUI_ENABLE_COVERAGE}") +ftxui_message("│ FTXUI_ENABLE_INSTALL : ${FTXUI_ENABLE_INSTALL}") +ftxui_message("│ FTXUI_QUIET : ${FTXUI_QUIET}") ftxui_message("└─────────────────────────────────────") diff --git a/cmake/ftxui_modules.cmake b/cmake/ftxui_modules.cmake index 5f07998c..0c017479 100644 --- a/cmake/ftxui_modules.cmake +++ b/cmake/ftxui_modules.cmake @@ -2,37 +2,6 @@ if (NOT FTXUI_BUILD_MODULES) return() endif() -# CMake 3.28+ supports the new CMake C++ module system. -if(CMAKE_VERSION VERSION_LESS 3.28) - message(FATAL_ERROR - "FTXUI_BUILD_MODULES requires CMake 3.28 or higher. " - ) - return() -endif() - -# Not all compilers support the C++ module system yet. -if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU|MSVC") - message(FATAL_ERROR - "FTXUI_BUILD_MODULES requires a compiler that supports C++20 modules. " - "Currently, only Clang, GCC, and MSVC support this feature." - ) - return() -endif() - -# The list of generators which support scanning sources for C++ modules include: -# - Ninja -# - Ninja Multi-Config -# - Visual Studio 17 2022 -if (NOT (CMAKE_GENERATOR MATCHES "Ninja") AND - NOT (CMAKE_GENERATOR MATCHES "Visual Studio" AND - CMAKE_GENERATOR_VERSION VERSION_GREATER_EQUAL 17)) - message(FATAL_ERROR - "FTXUI_BUILD_MODULES requires a generator that supports C++20 modules. - Please use Ninja or Visual Studio 17 2022 or higher." - ) - return() -endif() - cmake_minimum_required(VERSION 3.28) add_library(ftxui-modules) diff --git a/examples/component/button.cpp b/examples/component/button.cpp index 25813849..dda9dd3e 100644 --- a/examples/component/button.cpp +++ b/examples/component/button.cpp @@ -1,30 +1,65 @@ -#include // for shared_ptr, allocator, __shared_ptr_access - -#include "ftxui/component/component.hpp" // for Renderer, ResizableSplitBottom, ResizableSplitLeft, ResizableSplitRight, ResizableSplitTop +// Copyright 2020 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. +#include // for shared_ptr, __shared_ptr_access +#include // for operator+, to_string + +#include "ftxui/component/captured_mouse.hpp" // for ftxui +#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer #include "ftxui/component/component_base.hpp" // for ComponentBase #include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive -#include "ftxui/dom/elements.hpp" // for Element, operator|, text, center, border - +#include "ftxui/dom/elements.hpp" // for separator, gauge, text, Element, operator|, vbox, border + using namespace ftxui; - -int main() { - auto screen = ScreenInteractive::Fullscreen(); - std::string a = "aa"; - - auto component = Renderer([a] { - - std::vector elements; - - for (auto i = 0; i < 10; ++i) { - elements.push_back(window(text(a), paragraph(a))); +// This is a helper function to create a button with a custom style. +// The style is defined by a lambda function that takes an EntryState and +// returns an Element. +// We are using `center` to center the text inside the button, then `border` to +// add a border around the button, and finally `flex` to make the button fill +// the available space. +ButtonOption ButtonStyle() { + auto option = ButtonOption::Animated(); + option.transform = [](const EntryState& s) { + auto element = text(s.label); + if (s.focused) { + element |= bold; } - - return vbox(elements); - }); - - auto renderer = - Renderer(component, [&] { return component->Render() | border; }); - - screen.Loop(renderer); + return element | center | borderEmpty | flex; + }; + return option; +} + +int main() { + int value = 50; + + // The tree of components. This defines how to navigate using the keyboard. + auto buttons = Container::Vertical({ + Container::Horizontal({ + Button( + "-1", [&] { value--; }, ButtonStyle()), + Button( + "+1", [&] { value++; }, ButtonStyle()), + }) | flex, + Container::Horizontal({ + Button( + "-10", [&] { value -= 10; }, ButtonStyle()), + Button( + "+10", [&] { value += 10; }, ButtonStyle()), + }) | flex, + }); + + // Modify the way to render them on screen: + auto component = Renderer(buttons, [&] { + return vbox({ + text("value = " + std::to_string(value)), + separator(), + buttons->Render() | flex, + }) | + flex | border; + }); + + auto screen = ScreenInteractive::Fullscreen(); + screen.Loop(component); + return 0; } diff --git a/tools/generate_examples_modules.sh b/tools/generate_examples_modules.sh new file mode 100755 index 00000000..aa6a5165 --- /dev/null +++ b/tools/generate_examples_modules.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Generate ./examples_modules from ./examples to using C++20 modules instead of +# #includes for ftxui. +# This is useful for testing ftxui with modules. This ensures we don't forget +# to update the FTXUI modules when adding new features to FTXUI. + +echo "Generating ./examples_modules" +rm -rf ./examples_modules +cp -r ./examples ./examples_modules + +for file in ./examples_modules/**/*.cpp; do + echo "Generating $file" + + sed -i '/#include "ftxui/d' "$file" + sed -i '/#include