2 Commits

Author SHA1 Message Date
ArthurSonzogni
f128c442cc Support Bazel
BUG:https://github.com/ArthurSonzogni/FTXUI/issues/1032
2025-04-23 19:58:34 +02:00
Arthur Sonzogni
07fd3e685a Bugfix: Avoid crash with ResizeableSplit. (#1025)
Component
---------
- Bugfix: Fix a crash with ResizeableSplit. See #1023.
  - Clamp screen size to terminal size.
  - Disallow `ResizeableSplit` with negative size.

Dom
---
- Bugfix: Disallow specifying a negative size constraint. See #1023.

Bug: https://github.com/ArthurSonzogni/FTXUI/issues/1023
2025-03-31 18:19:48 +02:00
12 changed files with 308 additions and 14 deletions

3
.bazelrc Normal file
View File

@@ -0,0 +1,3 @@
build --cxxopt=-std=c++20
build --cxxopt=-Wall
build --cxxopt=-Werror

4
.gitignore vendored
View File

@@ -20,6 +20,10 @@ out/
!flake.nix !flake.nix
!ftxui.pc.in !ftxui.pc.in
!iwyu.imp !iwyu.imp
!WORKSPACE
!BUILD.bazel
!MODULE.bazel
!.bazelrc
# .github directory: # .github directory:
!.github/**/*.yaml !.github/**/*.yaml

258
BUILD.bazel Normal file
View File

@@ -0,0 +1,258 @@
load(
"@rules_cc//cc:defs.bzl",
"cc_library",
"cc_test",
"cc_binary",
)
package(default_visibility = ["//visibility:public"])
cc_library(
name = "screen",
srcs = [
"src/ftxui/screen/box.cpp",
"src/ftxui/screen/color.cpp",
"src/ftxui/screen/color_info.cpp",
"src/ftxui/screen/image.cpp",
"src/ftxui/screen/screen.cpp",
"src/ftxui/screen/string.cpp",
"src/ftxui/screen/string_internal.hpp",
"src/ftxui/screen/terminal.cpp",
"src/ftxui/screen/util.hpp",
],
hdrs = [
"include/ftxui/screen/box.hpp",
"include/ftxui/screen/color.hpp",
"include/ftxui/screen/color_info.hpp",
"include/ftxui/screen/deprecated.hpp",
"include/ftxui/screen/image.hpp",
"include/ftxui/screen/pixel.hpp",
"include/ftxui/screen/screen.hpp",
"include/ftxui/screen/string.hpp",
"include/ftxui/screen/terminal.hpp",
"include/ftxui/util/autoreset.hpp",
"include/ftxui/util/ref.hpp",
],
includes = ["include", "src"],
strip_include_prefix = "",
copts = ["-std=c++17"],
)
cc_test(
name = "screen_test",
srcs = [
"src/ftxui/screen/string_test.cpp",
"src/ftxui/screen/color_test.cpp",
],
deps = [
"//:screen",
"@googletest//:gtest_main",
],
includes = ["include", "src"],
copts = ["-std=c++20"],
testonly = True,
)
cc_library(
name = "dom",
srcs = [
"src/ftxui/dom/automerge.cpp",
"src/ftxui/dom/blink.cpp",
"src/ftxui/dom/bold.cpp",
"src/ftxui/dom/border.cpp",
"src/ftxui/dom/box_helper.cpp",
"src/ftxui/dom/box_helper.hpp",
"src/ftxui/dom/canvas.cpp",
"src/ftxui/dom/clear_under.cpp",
"src/ftxui/dom/color.cpp",
"src/ftxui/dom/composite_decorator.cpp",
"src/ftxui/dom/dbox.cpp",
"src/ftxui/dom/dim.cpp",
"src/ftxui/dom/flex.cpp",
"src/ftxui/dom/flexbox.cpp",
"src/ftxui/dom/flexbox_config.cpp",
"src/ftxui/dom/flexbox_helper.cpp",
"src/ftxui/dom/flexbox_helper.hpp",
"src/ftxui/dom/focus.cpp",
"src/ftxui/dom/frame.cpp",
"src/ftxui/dom/gauge.cpp",
"src/ftxui/dom/graph.cpp",
"src/ftxui/dom/gridbox.cpp",
"src/ftxui/dom/hbox.cpp",
"src/ftxui/dom/hyperlink.cpp",
"src/ftxui/dom/inverted.cpp",
"src/ftxui/dom/italic.cpp",
"src/ftxui/dom/linear_gradient.cpp",
"src/ftxui/dom/node.cpp",
"src/ftxui/dom/node_decorator.cpp",
"src/ftxui/dom/node_decorator.hpp",
"src/ftxui/dom/paragraph.cpp",
"src/ftxui/dom/reflect.cpp",
"src/ftxui/dom/scroll_indicator.cpp",
"src/ftxui/dom/selection.cpp",
"src/ftxui/dom/selection_style.cpp",
"src/ftxui/dom/separator.cpp",
"src/ftxui/dom/size.cpp",
"src/ftxui/dom/spinner.cpp",
"src/ftxui/dom/strikethrough.cpp",
"src/ftxui/dom/table.cpp",
"src/ftxui/dom/text.cpp",
"src/ftxui/dom/underlined.cpp",
"src/ftxui/dom/underlined_double.cpp",
"src/ftxui/dom/util.cpp",
"src/ftxui/dom/vbox.cpp",
],
hdrs = [
"include/ftxui/dom/canvas.hpp",
"include/ftxui/dom/deprecated.hpp",
"include/ftxui/dom/direction.hpp",
"include/ftxui/dom/elements.hpp",
"include/ftxui/dom/flexbox_config.hpp",
"include/ftxui/dom/linear_gradient.hpp",
"include/ftxui/dom/node.hpp",
"include/ftxui/dom/requirement.hpp",
"include/ftxui/dom/selection.hpp",
"include/ftxui/dom/table.hpp",
"include/ftxui/dom/take_any_args.hpp",
],
includes = ["include", "src"],
deps = [":screen"],
)
cc_test(
name = "dom_test",
srcs = [
"src/ftxui/dom/blink_test.cpp",
"src/ftxui/dom/bold_test.cpp",
"src/ftxui/dom/border_test.cpp",
"src/ftxui/dom/canvas_test.cpp",
"src/ftxui/dom/color_test.cpp",
"src/ftxui/dom/dbox_test.cpp",
"src/ftxui/dom/dim_test.cpp",
"src/ftxui/dom/flexbox_helper_test.cpp",
"src/ftxui/dom/flexbox_test.cpp",
"src/ftxui/dom/gauge_test.cpp",
"src/ftxui/dom/gridbox_test.cpp",
"src/ftxui/dom/hbox_test.cpp",
"src/ftxui/dom/hyperlink_test.cpp",
"src/ftxui/dom/italic_test.cpp",
"src/ftxui/dom/linear_gradient_test.cpp",
"src/ftxui/dom/scroll_indicator_test.cpp",
"src/ftxui/dom/separator_test.cpp",
"src/ftxui/dom/spinner_test.cpp",
"src/ftxui/dom/table_test.cpp",
"src/ftxui/dom/text_test.cpp",
"src/ftxui/dom/underlined_test.cpp",
"src/ftxui/dom/vbox_test.cpp",
],
deps = [
"//:dom",
"@googletest//:gtest_main",
],
includes = ["include", "src"],
copts = ["-std=c++20"],
testonly = True,
)
#"src/ftxui/dom/benchmark_test.cpp",
cc_library(
name = "component",
srcs = [
"src/ftxui/component/maybe.cpp",
"src/ftxui/component/hoverable.cpp",
"src/ftxui/component/collapsible.cpp",
"src/ftxui/component/screen_interactive.cpp",
"src/ftxui/component/modal.cpp",
"src/ftxui/component/util.cpp",
"src/ftxui/component/animation.cpp",
"src/ftxui/component/button.cpp",
"src/ftxui/component/dropdown.cpp",
"src/ftxui/component/loop.cpp",
"src/ftxui/component/slider.cpp",
"src/ftxui/component/container.cpp",
"src/ftxui/component/renderer.cpp",
"src/ftxui/component/terminal_input_parser.cpp",
"src/ftxui/component/component_options.cpp",
"src/ftxui/component/resizable_split.cpp",
"src/ftxui/component/component.cpp",
"src/ftxui/component/event.cpp",
"src/ftxui/component/catch_event.cpp",
"src/ftxui/component/input.cpp",
"src/ftxui/component/menu.cpp",
"src/ftxui/component/window.cpp",
"src/ftxui/component/checkbox.cpp",
"src/ftxui/component/radiobox.cpp",
"src/ftxui/component/terminal_input_parser.hpp",
],
hdrs = [
"include/ftxui/component/animation.hpp",
"include/ftxui/component/captured_mouse.hpp",
"include/ftxui/component/component.hpp",
"include/ftxui/component/component_base.hpp",
"include/ftxui/component/component_options.hpp",
"include/ftxui/component/event.hpp",
"include/ftxui/component/loop.hpp",
"include/ftxui/component/mouse.hpp",
"include/ftxui/component/receiver.hpp",
"include/ftxui/component/screen_interactive.hpp",
"include/ftxui/component/task.hpp",
],
includes = [
"include",
"src",
],
strip_include_prefix = "",
include_prefix = "",
deps = [":dom"],
linkopts = ["-lpthread"],
)
#"src/ftxui/component/component_fuzzer.cpp",
#"src/ftxui/component/terminal_input_parser_test_fuzzer.cpp",
#"src/ftxui/component/hoverable_test.cpp",
#"src/ftxui/component/collapsible_test.cpp",
#"src/ftxui/component/toggle_test.cpp",
#"src/ftxui/component/screen_interactive_test.cpp",
#"src/ftxui/component/modal_test.cpp",
#"src/ftxui/component/animation_test.cpp",
#"src/ftxui/component/★ selection_test.cpp",
#"src/ftxui/component/button_test.cpp",
#"src/ftxui/component/dropdown_test.cpp",
#"src/ftxui/component/slider_test.cpp",
#"src/ftxui/component/container_test.cpp",
#"src/ftxui/component/terminal_input_parser_test.cpp",
#"src/ftxui/component/receiver_test.cpp",
#"src/ftxui/component/resizable_split_test.cpp",
#"src/ftxui/component/component_test.cpp",
#"src/ftxui/component/input_test.cpp",
#"src/ftxui/component/menu_test.cpp",
#"src/ftxui/component/radiobox_test.cpp",
cc_test(
name = "component_test",
srcs = [
"src/ftxui/component/animation_test.cpp",
"src/ftxui/component/button_test.cpp",
"src/ftxui/component/collapsible_test.cpp",
"src/ftxui/component/component_test.cpp",
"src/ftxui/component/container_test.cpp",
"src/ftxui/component/dropdown_test.cpp",
"src/ftxui/component/hoverable_test.cpp",
"src/ftxui/component/input_test.cpp",
"src/ftxui/component/menu_test.cpp",
"src/ftxui/component/modal_test.cpp",
"src/ftxui/component/radiobox_test.cpp",
"src/ftxui/component/resizable_split_test.cpp",
"src/ftxui/component/screen_interactive_test.cpp",
"src/ftxui/component/selection_test.cpp",
"src/ftxui/component/slider_test.cpp",
"src/ftxui/component/toggle_test.cpp",
],
deps = [
"//:component",
"@googletest//:gtest_main",
],
includes = ["include", "src"],
copts = ["-std=c++20"],
testonly = True,
)

View File

@@ -1,6 +1,17 @@
Changelog Changelog
========= =========
Development
-----------
### Component
- Bugfix: Fix a crash with ResizeableSplit. See #1023.
- Clamp screen size to terminal size.
- Disallow `ResizeableSplit` with negative size.
### Dom
- Bugfix: Disallow specifying a negative size constraint. See #1023.
6.0.2 (2025-03-30) 6.0.2 (2025-03-30)
----- -----

18
MODULE.bazel Normal file
View File

@@ -0,0 +1,18 @@
# Module.
module(
name = "ftxui",
version = "6.0.2",
)
# Build deps.
bazel_dep(name = "rules_cc", version = "0.0.17")
# Test deps.
bazel_dep(name = "googletest", version = "1.15.2")
# Toolchain deps.
cc_configure = use_extension(
"@rules_cc//bzlmod:extensions.bzl",
"cc_configure",
)
use_repo(cc_configure, "local_config_cc_toolchains")

1
WORKSPACE Normal file
View File

@@ -0,0 +1 @@
workspace(name = "ftxui")

View File

@@ -19,10 +19,10 @@ add_executable(ftxui-tests
src/ftxui/component/menu_test.cpp src/ftxui/component/menu_test.cpp
src/ftxui/component/modal_test.cpp src/ftxui/component/modal_test.cpp
src/ftxui/component/radiobox_test.cpp src/ftxui/component/radiobox_test.cpp
src/ftxui/util/ref_test.cpp
src/ftxui/component/receiver_test.cpp src/ftxui/component/receiver_test.cpp
src/ftxui/component/resizable_split_test.cpp src/ftxui/component/resizable_split_test.cpp
src/ftxui/component/screen_interactive_test.cpp src/ftxui/component/screen_interactive_test.cpp
src/ftxui/component/selection_test.cpp
src/ftxui/component/slider_test.cpp src/ftxui/component/slider_test.cpp
src/ftxui/component/terminal_input_parser_test.cpp src/ftxui/component/terminal_input_parser_test.cpp
src/ftxui/component/toggle_test.cpp src/ftxui/component/toggle_test.cpp
@@ -42,7 +42,7 @@ add_executable(ftxui-tests
src/ftxui/dom/italic_test.cpp src/ftxui/dom/italic_test.cpp
src/ftxui/dom/linear_gradient_test.cpp src/ftxui/dom/linear_gradient_test.cpp
src/ftxui/dom/scroll_indicator_test.cpp src/ftxui/dom/scroll_indicator_test.cpp
src/ftxui/dom/selection_test.cpp src/ftxui/util/ref_test.cpp
src/ftxui/dom/separator_test.cpp src/ftxui/dom/separator_test.cpp
src/ftxui/dom/spinner_test.cpp src/ftxui/dom/spinner_test.cpp
src/ftxui/dom/table_test.cpp src/ftxui/dom/table_test.cpp

View File

@@ -42,8 +42,8 @@ class ComponentBase {
// Component hierarchy: // Component hierarchy:
ComponentBase* Parent() const; ComponentBase* Parent() const;
Component& ChildAt(size_t i); Component& ChildAt(int i);
size_t ChildCount() const; int ChildCount() const;
int Index() const; int Index() const;
void Add(Component children); void Add(Component children);
void Detach(); void Detach();

View File

@@ -77,16 +77,16 @@ class ResizableSplitBase : public ComponentBase {
switch (options_->direction()) { switch (options_->direction()) {
case Direction::Left: case Direction::Left:
options_->main_size() = event.mouse().x - box_.x_min; options_->main_size() = std::max(0, event.mouse().x - box_.x_min);
return true; return true;
case Direction::Right: case Direction::Right:
options_->main_size() = box_.x_max - event.mouse().x; options_->main_size() = std::max(0, box_.x_max - event.mouse().x);
return true; return true;
case Direction::Up: case Direction::Up:
options_->main_size() = event.mouse().y - box_.y_min; options_->main_size() = std::max(0, event.mouse().y - box_.y_min);
return true; return true;
case Direction::Down: case Direction::Down:
options_->main_size() = box_.y_max - event.mouse().y; options_->main_size() = std::max(0, box_.y_max - event.mouse().y);
return true; return true;
} }

View File

@@ -34,6 +34,7 @@
#include "ftxui/dom/requirement.hpp" // for Requirement #include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/pixel.hpp" // for Pixel #include "ftxui/screen/pixel.hpp" // for Pixel
#include "ftxui/screen/terminal.hpp" // for Dimensions, Size #include "ftxui/screen/terminal.hpp" // for Dimensions, Size
#include "ftxui/screen/util.hpp" // for util::clamp
#if defined(_WIN32) #if defined(_WIN32)
#define DEFINE_CONSOLEV2_PROPERTIES #define DEFINE_CONSOLEV2_PROPERTIES
@@ -917,15 +918,15 @@ void ScreenInteractive::Draw(Component component) {
break; break;
case Dimension::TerminalOutput: case Dimension::TerminalOutput:
dimx = terminal.dimx; dimx = terminal.dimx;
dimy = document->requirement().min_y; dimy = util::clamp(document->requirement().min_y, 0, terminal.dimy);
break; break;
case Dimension::Fullscreen: case Dimension::Fullscreen:
dimx = terminal.dimx; dimx = terminal.dimx;
dimy = terminal.dimy; dimy = terminal.dimy;
break; break;
case Dimension::FitComponent: case Dimension::FitComponent:
dimx = std::min(document->requirement().min_x, terminal.dimx); dimx = util::clamp(document->requirement().min_x, 0, terminal.dimx);
dimy = std::min(document->requirement().min_y, terminal.dimy); dimy = util::clamp(document->requirement().min_y, 0, terminal.dimy);
break; break;
} }

View File

@@ -127,8 +127,6 @@ TEST(SelectionTest, SelectionOnChangeSquashedEvents) {
} }
TEST(SelectionTest, StyleSelection) { TEST(SelectionTest, StyleSelection) {
int selectionChangeCounter = 0;
auto element = hbox({ auto element = hbox({
text("Lorem "), text("Lorem "),
text("ipsum") | selectionColor(Color::Red), text("ipsum") | selectionColor(Color::Red),

View File

@@ -19,7 +19,7 @@ class Size : public Node {
: Node(unpack(std::move(child))), : Node(unpack(std::move(child))),
direction_(direction), direction_(direction),
constraint_(constraint), constraint_(constraint),
value_(value) {} value_(std::max(0, value)) {}
void ComputeRequirement() override { void ComputeRequirement() override {
Node::ComputeRequirement(); Node::ComputeRequirement();