2 Commits

Author SHA1 Message Date
ArthurSonzogni
9c19331935 Add a task system. 2025-08-16 17:30:50 +02:00
tattwamasi
994915dbb9 Add ftxui convenience/umbrella module to cmake rules to fix #1083 (#1085)
Some checks failed
Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (cl, cl, windows-latest) (push) Has been cancelled
Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (clang, clang++, macos-latest) (push) Has been cancelled
Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (clang, clang++, ubuntu-latest) (push) Has been cancelled
Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (gcc, g++, macos-latest) (push) Has been cancelled
Build / Bazel, ${{ matrix.cxx }}, ${{ matrix.os }} (gcc, g++, ubuntu-latest) (push) Has been cancelled
Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (cl, Windows MSVC, windows-latest) (push) Has been cancelled
Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (gcc, Linux GCC, ubuntu-latest) (push) Has been cancelled
Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (llvm, llvm-cov gcov, Linux Clang, ubuntu-latest) (push) Has been cancelled
Build / CMake, ${{ matrix.compiler }}, ${{ matrix.os }} (llvm, llvm-cov gcov, MacOS clang, macos-latest) (push) Has been cancelled
Build / Test modules (llvm, ubuntu-latest) (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
* Add the umbrella module ftxui to the cmake module build.

* Update cpp20 modules documentation.
2025-07-27 11:39:46 +02:00
14 changed files with 85 additions and 69 deletions

View File

@@ -158,19 +158,17 @@ ftxui_cc_library(
"src/ftxui/component/resizable_split.cpp",
"src/ftxui/component/screen_interactive.cpp",
"src/ftxui/component/slider.cpp",
"src/ftxui/component/task.cpp",
"src/ftxui/component/task_internal.hpp",
"src/ftxui/component/task_queue.cpp",
"src/ftxui/component/task_queue.hpp",
"src/ftxui/component/task_runner.cpp",
"src/ftxui/component/task_runner.hpp",
"src/ftxui/component/terminal_input_parser.cpp",
"src/ftxui/component/terminal_input_parser.hpp",
"src/ftxui/component/util.cpp",
"src/ftxui/component/window.cpp",
# Core
"src/ftxui/core/task.cpp",
"src/ftxui/core/task.hpp",
"src/ftxui/core/task_queue.cpp",
"src/ftxui/core/task_queue.hpp",
"src/ftxui/core/task_runner.cpp",
"src/ftxui/core/task_runner.hpp",
# Private header from ftxui:dom.
"src/ftxui/dom/node_decorator.hpp",

View File

@@ -24,6 +24,7 @@ Next
import ftxui.util;
```
Thanks @mikomikotaishi for PR #1015.
- Remove dependency on 'pthread'.
### Component
- Fix ScreenInteractive::FixedSize screen stomps on the preceding terminal

View File

@@ -144,16 +144,16 @@ add_library(component
src/ftxui/component/resizable_split.cpp
src/ftxui/component/screen_interactive.cpp
src/ftxui/component/slider.cpp
src/ftxui/component/task.cpp
src/ftxui/component/task_internal.hpp
src/ftxui/component/task_queue.cpp
src/ftxui/component/task_queue.hpp
src/ftxui/component/task_runner.cpp
src/ftxui/component/task_runner.hpp
src/ftxui/component/terminal_input_parser.cpp
src/ftxui/component/terminal_input_parser.hpp
src/ftxui/component/util.cpp
src/ftxui/component/window.cpp
src/ftxui/core/task.cpp
src/ftxui/core/task.hpp
src/ftxui/core/task_queue.cpp
src/ftxui/core/task_queue.hpp
src/ftxui/core/task_runner.cpp
src/ftxui/core/task_runner.hpp
)
target_link_libraries(dom PUBLIC screen)

View File

@@ -6,6 +6,7 @@ add_library(ftxui-modules)
target_sources(ftxui-modules
PUBLIC FILE_SET CXX_MODULES FILES
src/ftxui/ftxui.cppm
src/ftxui/component.cppm
src/ftxui/component/animation.cppm
src/ftxui/component/captured_mouse.cppm

View File

@@ -22,9 +22,9 @@ add_executable(ftxui-tests
src/ftxui/component/resizable_split_test.cpp
src/ftxui/component/screen_interactive_test.cpp
src/ftxui/component/slider_test.cpp
src/ftxui/component/task_test.cpp
src/ftxui/component/terminal_input_parser_test.cpp
src/ftxui/component/toggle_test.cpp
src/ftxui/core/task_test.cpp
src/ftxui/dom/blink_test.cpp
src/ftxui/dom/bold_test.cpp
src/ftxui/dom/border_test.cpp

View File

@@ -12,8 +12,24 @@ FTXUI experimentally supports
compilation times and improve code organization. Each header has a
corresponding module.
**Example with CMake and Ninja**
Use the FTXUI_BUILD_MODULES option to build the FTXUI project itself to provide C++ 20 modules,
for example with CMake and Ninja:
```sh
cmake \
-DCMAKE_GENERATOR=Ninja \
-DFTXUI_BUILD_MODULES=ON \
..
ninja
```
> [!NOTE]
> To use modules, you need a C++20 compatible compiler, CMake version 3.20 or
> higher, and use a compatible generator like Ninja. Note that Makefile
> generators **do not support modules**.
Then, in your own code you can consume the modules and code as normal:
```cpp
import ftxui;
@@ -26,23 +42,30 @@ int main() {
}
```
```sh
cmake \
-DCMAKE_GENERATOR=Ninja \
-DFTXUI_BUILD_MODULES=ON \
..
Note, the `ftxui` convenience module which simply pulls together all the modules:
ninja
```cpp
export import ftxui.component;
export import ftxui.dom;
export import ftxui.screen;
export import ftxui.util;
```
You can instead import only the module(s) you need if desired.
To properly find and link the modules with CMake, use `target_link_libraries` to get the right
compiler, linker, etc. flags.
```cmake
target_link_libraries(my_executable
#...whatever...
PRIVATE ftxui::modules
)
```
> [!NOTE]
> To use modules, you need a C++20 compatible compiler, CMake version 3.20 or
> higher, and use a compatible generator like Ninja. Note that Makefile
> generators **do not support modules**.
### Module list
The modules directly reference the corresponding header, or a group of related
headers to provide a more convenient interface. The following modules
headers to provide a more convenient interface. The following modules
are available:
- `ftxui`

View File

@@ -4,7 +4,6 @@
#include "ftxui/component/screen_interactive.hpp"
#include <algorithm> // for copy, max, min
#include <array> // for array
#include <array>
#include <atomic>
#include <chrono> // for operator-, milliseconds, operator>=, duration, common_type<>::type, time_point
#include <csignal> // for signal, SIGTSTP, SIGABRT, SIGWINCH, raise, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, __sighandler_t, size_t
@@ -18,27 +17,22 @@
#include <memory>
#include <stack> // for stack
#include <string>
#include <thread> // for thread, sleep_for
#include <thread> // for thread, sleep_for
#include <tuple> // for _Swallow_assign, ignore
#include <type_traits> // for decay_t
#include <utility> // for move, swap
#include <variant> // for visit, variant
#include <vector> // for vector
#include <thread> // for thread, sleep_for
#include <tuple> // for _Swallow_assign, ignore
#include <utility> // for move, swap
#include <variant> // for visit, variant
#include <vector> // for vector
#include "ftxui/component/animation.hpp" // for TimePoint, Clock, Duration, Params, RequestAnimationFrame
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/event.hpp" // for Event
#include "ftxui/component/loop.hpp" // for Loop
#include "ftxui/component/receiver.hpp" // for ReceiverImpl, Sender, MakeReceiver, SenderImpl, Receiver
#include "ftxui/component/task_runner.hpp"
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputParser
#include "ftxui/core/task_runner.hpp"
#include "ftxui/dom/node.hpp" // for Node, Render
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/pixel.hpp" // for Pixel
#include "ftxui/screen/terminal.hpp" // for Dimensions, Size
#include "ftxui/screen/util.hpp" // for util::clamp
#include "ftxui/util/autoreset.hpp" // for AutoReset
#include "ftxui/dom/node.hpp" // for Node, Render
#include "ftxui/screen/terminal.hpp" // for Dimensions, Size
#include "ftxui/screen/util.hpp" // for util::clamp
#include "ftxui/util/autoreset.hpp" // for AutoReset
#if defined(_WIN32)
#define DEFINE_CONSOLEV2_PROPERTIES
@@ -584,15 +578,15 @@ void ScreenInteractive::Install() {
SetConsoleMode(stdin_handle, in_mode);
SetConsoleMode(stdout_handle, out_mode);
#else // POSIX (Linux & Mac)
//#if defined(__EMSCRIPTEN__)
#else // POSIX (Linux & Mac)
// #if defined(__EMSCRIPTEN__)
//// Reading stdin isn't blocking.
//int flags = fcntl(0, F_GETFL, 0);
//fcntl(0, F_SETFL, flags | O_NONBLOCK);
// int flags = fcntl(0, F_GETFL, 0);
// fcntl(0, F_SETFL, flags | O_NONBLOCK);
//// Restore the terminal configuration on exit.
//on_exit_functions.emplace([flags] { fcntl(0, F_SETFL, flags); });
//#endif
// on_exit_functions.emplace([flags] { fcntl(0, F_SETFL, flags); });
// #endif
for (const int signal : {SIGWINCH, SIGTSTP}) {
InstallSignalHandler(signal);
}
@@ -685,8 +679,8 @@ void ScreenInteractive::RunOnceBlocking(Component component) {
size_t executed_task = internal_->task_runner.ExecutedTasks();
// Wait for at least one task to execute.
while(executed_task == internal_->task_runner.ExecutedTasks() &&
!HasQuitted()) {
while (executed_task == internal_->task_runner.ExecutedTasks() &&
!HasQuitted()) {
RunOnce(component);
const auto now = std::chrono::steady_clock::now();
@@ -733,7 +727,7 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
[&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
// clang-format off
// clang-format off
// Handle Event.
if constexpr (std::is_same_v<T, Event>) {
@@ -1022,7 +1016,7 @@ void ScreenInteractive::Signal(int signal) {
void ScreenInteractive::FetchTerminalEvents() {
#if defined(_WIN32)
auto get_input_records = [&] () -> std::vector<INPUT_RECORD> {
auto get_input_records = [&]() -> std::vector<INPUT_RECORD> {
// Check if there is input in the console.
auto console = GetStdHandle(STD_INPUT_HANDLE);
DWORD number_of_events = 0;
@@ -1049,7 +1043,7 @@ void ScreenInteractive::FetchTerminalEvents() {
const auto timeout =
std::chrono::steady_clock::now() - internal_->last_char_time;
const size_t timeout_microseconds =
std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
internal_->terminal_input_parser.Timeout(timeout_microseconds);
return;
}
@@ -1090,17 +1084,17 @@ void ScreenInteractive::FetchTerminalEvents() {
const auto timeout =
std::chrono::steady_clock::now() - internal_->last_char_time;
const size_t timeout_microseconds =
std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
std::chrono::duration_cast<std::chrono::microseconds>(timeout).count();
internal_->terminal_input_parser.Timeout(timeout_microseconds);
return;
}
internal_->last_char_time = std::chrono::steady_clock::now();
// Convert the chars to events.
for(size_t i = 0; i < l; ++i) {
for (size_t i = 0; i < l; ++i) {
internal_->terminal_input_parser.Add(out[i]);
}
#else // POSIX (Linux & Mac)
#else // POSIX (Linux & Mac)
if (!CheckStdinReady()) {
const auto timeout =
std::chrono::steady_clock::now() - internal_->last_char_time;
@@ -1116,7 +1110,7 @@ void ScreenInteractive::FetchTerminalEvents() {
size_t l = read(fileno(stdin), out.data(), out.size());
// Convert the chars to events.
for(size_t i = 0; i < l; ++i) {
for (size_t i = 0; i < l; ++i) {
internal_->terminal_input_parser.Add(out[i]);
}
#endif
@@ -1127,8 +1121,8 @@ void ScreenInteractive::PostAnimationTask() {
// Repeat the animation task every 15ms. This correspond to a frame rate
// of around 66fps.
internal_->task_runner.PostDelayedTask(
[this] { PostAnimationTask(); }, std::chrono::milliseconds(15));
internal_->task_runner.PostDelayedTask([this] { PostAnimationTask(); },
std::chrono::milliseconds(15));
}
bool ScreenInteractive::SelectionData::operator==(

View File

@@ -1,7 +1,7 @@
// Copyright 2024 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 "task.hpp"
#include "ftxui/component/task_internal.hpp"
namespace ftxui::task {
bool PendingTask::operator<(const PendingTask& other) const {

View File

@@ -1,7 +1,7 @@
// Copyright 2024 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 "task_queue.hpp"
#include "ftxui/component/task_queue.hpp"
namespace ftxui::task {

View File

@@ -7,7 +7,7 @@
#include <queue>
#include <variant>
#include "task.hpp"
#include "ftxui/component/task_internal.hpp" // for PendingTask, Task
namespace ftxui::task {

View File

@@ -1,7 +1,7 @@
// Copyright 2024 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 "task_runner.hpp"
#include "ftxui/component/task_runner.hpp"
#include <cassert>
#include <thread>

View File

@@ -4,8 +4,8 @@
#ifndef TASK_RUNNER_HPP
#define TASK_RUNNER_HPP
#include "task.hpp"
#include "task_queue.hpp"
#include "ftxui/component/task_internal.hpp"
#include "ftxui/component/task_queue.hpp"
namespace ftxui::task {

View File

@@ -4,12 +4,12 @@
// Copyright 2024 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 "task.hpp"
#include "ftxui/component/task_internal.hpp"
#include <gtest/gtest.h>
#include <thread> // for sleep_for
#include "task_runner.hpp"
#include "ftxui/component/task_runner.hpp"
namespace ftxui::task {
@@ -92,4 +92,3 @@ TEST(TaskTest, RunDelayedTask) {
}
} // namespace ftxui::task