Add clang-tidy. (#368)

This commit is contained in:
Arthur Sonzogni
2022-03-31 02:17:43 +02:00
committed by GitHub
parent 62fb6298be
commit aebde94352
80 changed files with 1958 additions and 1376 deletions

View File

@@ -1,14 +1,18 @@
#define _USE_MATH_DEFINES
#include <cmath> // for sin, pow, sqrt, M_PI_2, M_PI, cos
#include <cmath>
#include <ratio> // for ratio
#include <utility> // for move
#include "ftxui/component/animation.hpp"
#include <ratio> // for ratio
namespace ftxui {
namespace animation {
namespace ftxui::animation {
namespace easing {
namespace {
constexpr float kPi = 3.14159265358979323846F;
constexpr float kPi2 = kPi / 2.F;
} // namespace
// Easing function have been taken out of:
// https://github.com/warrenm/AHEasing/blob/master/AHEasing/easing.c
//
@@ -40,7 +44,7 @@ float QuadraticOut(float p) {
// y = (1/2)((2x)^2) ; [0, 0.5)
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
float QuadraticInOut(float p) {
if (p < 0.5) {
if (p < 0.5F) { // NOLINT
return 2 * p * p;
} else {
return (-2 * p * p) + (4 * p) - 1;
@@ -62,11 +66,11 @@ float CubicOut(float p) {
// y = (1/2)((2x)^3) ; [0, 0.5)
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
float CubicInOut(float p) {
if (p < 0.5) {
if (p < 0.5F) { // NOLINT
return 4 * p * p * p;
} else {
float f = ((2 * p) - 2);
return 0.5 * f * f * f + 1;
return 0.5F * f * f * f + 1; // NOLINT
}
}
@@ -85,11 +89,11 @@ float QuarticOut(float p) {
// y = (1/2)((2x)^4) ; [0, 0.5)
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
float QuarticInOut(float p) {
if (p < 0.5) {
return 8 * p * p * p * p;
if (p < 0.5F) { // NOLINT
return 8 * p * p * p * p; // NOLINT
} else {
float f = (p - 1);
return -8 * f * f * f * f + 1;
return -8 * f * f * f * f + 1; // NOLINT
}
}
@@ -108,119 +112,122 @@ float QuinticOut(float p) {
// y = (1/2)((2x)^5) ; [0, 0.5)
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
float QuinticInOut(float p) {
if (p < 0.5) {
return 16 * p * p * p * p * p;
} else {
float f = ((2 * p) - 2);
return 0.5 * f * f * f * f * f + 1;
if (p < 0.5F) { // NOLINT
return 16 * p * p * p * p * p; // NOLINT
} else { // NOLINT
float f = ((2 * p) - 2); // NOLINT
return 0.5 * f * f * f * f * f + 1; // NOLINT
}
}
// Modeled after quarter-cycle of sine wave
float SineIn(float p) {
return sin((p - 1) * M_PI_2) + 1;
return std::sin((p - 1) * kPi2) + 1;
}
// Modeled after quarter-cycle of sine wave (different phase)
float SineOut(float p) {
return sin(p * M_PI_2);
return std::sin(p * kPi2);
}
// Modeled after half sine wave
float SineInOut(float p) {
return 0.5 * (1 - cos(p * M_PI));
return 0.5F * (1 - std::cos(p * kPi)); // NOLINT
}
// Modeled after shifted quadrant IV of unit circle
float CircularIn(float p) {
return 1 - sqrt(1 - (p * p));
return 1 - std::sqrt(1 - (p * p));
}
// Modeled after shifted quadrant II of unit circle
float CircularOut(float p) {
return sqrt((2 - p) * p);
return std::sqrt((2 - p) * p);
}
// Modeled after the piecewise circular function
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
float CircularInOut(float p) {
if (p < 0.5) {
return 0.5 * (1 - sqrt(1 - 4 * (p * p)));
if (p < 0.5F) { // NOLINT
return 0.5F * (1 - std::sqrt(1 - 4 * (p * p))); // NOLINT
} else {
return 0.5 * (sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1);
return 0.5F * (std::sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1); // NOLINT
}
}
// Modeled after the exponential function y = 2^(10(x - 1))
float ExponentialIn(float p) {
return (p == 0.0) ? p : pow(2, 10 * (p - 1));
return (p == 0.0) ? p : std::pow(2, 10 * (p - 1)); // NOLINT
}
// Modeled after the exponential function y = -2^(-10x) + 1
float ExponentialOut(float p) {
return (p == 1.0) ? p : 1 - pow(2, -10 * p);
return (p == 1.0) ? p : 1 - std::pow(2, -10 * p); // NOLINT
}
// Modeled after the piecewise exponential
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
float ExponentialInOut(float p) {
if (p == 0.0 || p == 1.0)
if (p == 0.0 || p == 1.F) {
return p;
}
if (p < 0.5) {
return 0.5 * pow(2, (20 * p) - 10);
} else {
return -0.5 * pow(2, (-20 * p) + 10) + 1;
if (p < 0.5F) { // NOLINT
return 0.5 * std::pow(2, (20 * p) - 10); // NOLINT
} else { // NOLINT
return -0.5 * std::pow(2, (-20 * p) + 10) + 1; // NOLINT
}
}
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
float ElasticIn(float p) {
return sin(13 * M_PI_2 * p) * pow(2, 10 * (p - 1));
return std::sin(13.F * kPi2 * p) * std::pow(2.F, 10.F * (p - 1)); // NOLINT
}
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) +
// 1
float ElasticOut(float p) {
return sin(-13 * M_PI_2 * (p + 1)) * pow(2, -10 * p) + 1;
return std::sin(-13.F * kPi2 * (p + 1)) * std::pow(2.F, -10.F * p) +
1; // NOLINT
}
// Modeled after the piecewise exponentially-damped sine wave:
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
float ElasticInOut(float p) {
if (p < 0.5) {
return 0.5 * sin(13 * M_PI_2 * (2 * p)) * pow(2, 10 * ((2 * p) - 1));
} else {
return 0.5 *
(sin(-13 * M_PI_2 * ((2 * p - 1) + 1)) * pow(2, -10 * (2 * p - 1)) +
2);
if (p < 0.5F) { // NOLINT
return 0.5 * std::sin(13.F * kPi2 * (2 * p)) * // NOLINT
std::pow(2, 10 * ((2 * p) - 1)); // NOLINT
} else { // NOLINT
return 0.5 * (std::sin(-13.F * kPi2 * ((2 * p - 1) + 1)) * // NOLINT
std::pow(2, -10 * (2 * p - 1)) + // NOLINT
2); // NOLINT
}
}
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
float BackIn(float p) {
return p * p * p - p * sin(p * M_PI);
return p * p * p - p * std::sin(p * kPi);
}
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
float BackOut(float p) {
float f = (1 - p);
return 1 - (f * f * f - f * sin(f * M_PI));
return 1 - (f * f * f - f * std::sin(f * kPi));
}
// Modeled after the piecewise overshooting cubic function:
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
float BackInOut(float p) {
if (p < 0.5) {
if (p < 0.5F) { // NOLINT
float f = 2 * p;
return 0.5 * (f * f * f - f * sin(f * M_PI));
return 0.5F * (f * f * f - f * std::sin(f * kPi)); // NOLINT
} else {
float f = (1 - (2 * p - 1));
return 0.5 * (1 - (f * f * f - f * sin(f * M_PI))) + 0.5;
float f = (1 - (2 * p - 1)); // NOLINT
return 0.5F * (1 - (f * f * f - f * std::sin(f * kPi))) + 0.5; // NOLINT
}
}
@@ -229,22 +236,23 @@ float BounceIn(float p) {
}
float BounceOut(float p) {
if (p < 4 / 11.0) {
return (121 * p * p) / 16.0;
} else if (p < 8 / 11.0) {
return (363 / 40.0 * p * p) - (99 / 10.0 * p) + 17 / 5.0;
} else if (p < 9 / 10.0) {
return (4356 / 361.0 * p * p) - (35442 / 1805.0 * p) + 16061 / 1805.0;
} else {
return (54 / 5.0 * p * p) - (513 / 25.0 * p) + 268 / 25.0;
if (p < 4 / 11.0) { // NOLINT
return (121 * p * p) / 16.0; // NOLINT
} else if (p < 8 / 11.0) { // NOLINT
return (363 / 40.0 * p * p) - (99 / 10.0 * p) + 17 / 5.0; // NOLINT
} else if (p < 9 / 10.0) { // NOLINT
return (4356 / 361.0 * p * p) - (35442 / 1805.0 * p) + // NOLINT
16061 / 1805.0; // NOLINT
} else { // NOLINT
return (54 / 5.0 * p * p) - (513 / 25.0 * p) + 268 / 25.0; // NOLINT
}
}
float BounceInOut(float p) {
if (p < 0.5) {
return 0.5 * BounceIn(p * 2);
} else {
return 0.5 * BounceOut(p * 2 - 1) + 0.5;
float BounceInOut(float p) { // NOLINT
if (p < 0.5F) { // NOLINT
return 0.5F * BounceIn(p * 2); // NOLINT
} else { // NOLINT
return 0.5F * BounceOut(p * 2 - 1) + 0.5F; // NOLINT
}
}
@@ -259,7 +267,7 @@ Animator::Animator(float* from,
from_(*from),
to_(to),
duration_(duration),
easing_function_(easing_function),
easing_function_(std::move(easing_function)),
current_(-delay) {
RequestAnimationFrame();
}
@@ -275,11 +283,11 @@ void Animator::OnAnimation(Params& params) {
if (current_ <= Duration()) {
*value_ = from_;
} else {
*value_ = from_ + (to_ - from_) * easing_function_(current_ / duration_);
*value_ = from_ +
(to_ - from_) * easing_function_(current_ / duration_); // NOLINT
}
RequestAnimationFrame();
}
} // namespace animation
} // namespace ftxui
} // namespace ftxui::animation

View File

@@ -1,17 +1,16 @@
#include <functional> // for function
#include <memory> // for shared_ptr
#include <string> // for string
#include <utility> // for move
#include "ftxui/component/animation.hpp" // for Animator, Params (ptr only)
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Button
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for ButtonOption, AnimatedColorOption, AnimatedColorsOption
#include "ftxui/component/component_options.hpp" // for ButtonOption, AnimatedColorOption, AnimatedColorsOption, EntryState
#include "ftxui/component/event.hpp" // for Event, Event::Return
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
#include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" // for operator|, Decorator, Element, bgcolor, color, operator|=, reflect, text, border, inverted, nothing
#include "ftxui/dom/elements.hpp" // for operator|, Decorator, Element, operator|=, bgcolor, color, reflect, text, bold, border, inverted, nothing
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/color.hpp" // for Color
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
@@ -20,12 +19,14 @@ namespace ftxui {
namespace {
Element DefaultTransform(EntryState params) {
Element DefaultTransform(EntryState params) { // NOLINT
auto element = text(params.label) | border;
if (params.active)
if (params.active) {
element |= bold;
if (params.focused)
}
if (params.focused) {
element |= inverted;
}
return element;
}
@@ -62,13 +63,16 @@ Component Button(ConstStringRef label,
Impl(ConstStringRef label,
std::function<void()> on_click,
Ref<ButtonOption> option)
: label_(label), on_click_(on_click), option_(std::move(option)) {}
: label_(std::move(label)),
on_click_(std::move(on_click)),
option_(std::move(option)) {}
// Component implementation:
Element Render() override {
float target = Focused() ? 1.0 : 0.f;
if (target != animator_background_.to())
float target = Focused() ? 1.F : 0.F; // NOLINT
if (target != animator_background_.to()) {
SetAnimationTarget(target);
}
EntryState state = {
*label_,
@@ -122,14 +126,15 @@ Component Button(ConstStringRef label,
void OnClick() {
on_click_();
animation_background_ = 0.5f;
animation_foreground_ = 0.5f;
SetAnimationTarget(1.f);
animation_background_ = 0.5F; // NOLINT
animation_foreground_ = 0.5F; // NOLINT
SetAnimationTarget(1.F); // NOLINT
}
bool OnEvent(Event event) override {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (event == Event::Return) {
OnClick();
@@ -142,8 +147,9 @@ Component Button(ConstStringRef label,
mouse_hover_ =
box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
if (!mouse_hover_)
if (!mouse_hover_) {
return false;
}
TakeFocus();
@@ -172,7 +178,7 @@ Component Button(ConstStringRef label,
animation::Animator(&animation_foreground_);
};
return Make<Impl>(label, std::move(on_click), std::move(option));
return Make<Impl>(std::move(label), std::move(on_click), std::move(option));
}
} // namespace ftxui

View File

@@ -11,15 +11,16 @@ namespace ftxui {
class CatchEventBase : public ComponentBase {
public:
// Constructor.
CatchEventBase(std::function<bool(Event)> on_event)
explicit CatchEventBase(std::function<bool(Event)> on_event)
: on_event_(std::move(on_event)) {}
// Component implementation.
bool OnEvent(Event event) override {
if (on_event_(event))
if (on_event_(event)) {
return true;
else
} else {
return ComponentBase::OnEvent(event);
}
}
protected:
@@ -76,8 +77,8 @@ Component CatchEvent(Component child,
/// ```
ComponentDecorator CatchEvent(std::function<bool(Event)> on_event) {
return [on_event = std::move(on_event)](Component child) {
return CatchEvent(child, [on_event = std::move(on_event)](Event event) {
return on_event(event);
return CatchEvent(std::move(child), [on_event = on_event](Event event) {
return on_event(std::move(event));
});
};
}

View File

@@ -18,7 +18,7 @@ namespace {
class CheckboxBase : public ComponentBase {
public:
CheckboxBase(ConstStringRef label, bool* state, Ref<CheckboxOption> option)
: label_(label), state_(state), option_(std::move(option)) {}
: label_(std::move(label)), state_(state), option_(std::move(option)) {}
private:
// Component implementation.
@@ -32,18 +32,20 @@ class CheckboxBase : public ComponentBase {
is_active,
is_focused || hovered_,
};
auto element = (option_->transform
? option_->transform
: CheckboxOption::Simple().transform)(std::move(state));
auto element =
(option_->transform ? option_->transform
: CheckboxOption::Simple().transform)(state);
return element | focus_management | reflect(box_);
}
bool OnEvent(Event event) override {
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
hovered_ = false;
if (event == Event::Character(' ') || event == Event::Return) {
@@ -58,11 +60,13 @@ class CheckboxBase : public ComponentBase {
bool OnMouseEvent(Event event) {
hovered_ = box_.Contain(event.mouse().x, event.mouse().y);
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (!hovered_)
if (!hovered_) {
return false;
}
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Pressed) {
@@ -109,7 +113,7 @@ class CheckboxBase : public ComponentBase {
Component Checkbox(ConstStringRef label,
bool* checked,
Ref<CheckboxOption> option) {
return Make<CheckboxBase>(label, checked, std::move(option));
return Make<CheckboxBase>(std::move(label), checked, std::move(option));
}
} // namespace ftxui

View File

@@ -1,10 +1,12 @@
#include <string> // for string
#include <utility> // for move
#include <functional> // for function
#include <memory> // for shared_ptr, allocator
#include <utility> // for move
#include "ftxui/component/component.hpp" // for Checkbox, Maybe, Make, Vertical, Collapsible
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
#include "ftxui/component/component_options.hpp" // for CheckboxOption, EntryState
#include "ftxui/dom/elements.hpp" // for operator|=, text, hbox, Element, bold, inverted
#include "ftxui/util/ref.hpp" // for Ref, ConstStringRef
namespace ftxui {
@@ -28,27 +30,28 @@ namespace ftxui {
Component Collapsible(ConstStringRef label, Component child, Ref<bool> show) {
class Impl : public ComponentBase {
public:
Impl(ConstStringRef label, Component child, Ref<bool> show)
: show_(std::move(show)) {
Impl(ConstStringRef label, Component child, Ref<bool> show) : show_(show) {
CheckboxOption opt;
opt.transform = [](EntryState s) {
auto prefix = text(s.state ? "" : "");
opt.transform = [](EntryState s) { // NOLINT
auto prefix = text(s.state ? "" : ""); // NOLINT
auto t = text(s.label);
if (s.active)
if (s.active) {
t |= bold;
if (s.focused)
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
Add(Container::Vertical({
Checkbox(label, show_.operator->(), opt),
Checkbox(std::move(label), show_.operator->(), opt),
Maybe(std::move(child), show_.operator->()),
}));
}
Ref<bool> show_;
};
return Make<Impl>(label, std::move(child), std::move(show));
return Make<Impl>(std::move(label), std::move(child), show);
}
} // namespace ftxui

View File

@@ -1,6 +1,6 @@
#include <stddef.h> // for size_t
#include <algorithm> // for find_if
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <iterator> // for begin, end
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -37,7 +37,7 @@ ComponentBase* ComponentBase::Parent() const {
/// @brief Access the child at index `i`.
/// @ingroup component
Component& ComponentBase::ChildAt(size_t i) {
assert(i < ChildCount());
assert(i < ChildCount()); // NOLINT
return children_[i];
}
@@ -61,8 +61,9 @@ void ComponentBase::Add(Component child) {
/// @see Parent
/// @ingroup component
void ComponentBase::Detach() {
if (!parent_)
if (parent_ == nullptr) {
return;
}
auto it = std::find_if(std::begin(parent_->children_), //
std::end(parent_->children_), //
[this](const Component& that) { //
@@ -76,8 +77,9 @@ void ComponentBase::Detach() {
/// @brief Remove all children.
/// @ingroup component
void ComponentBase::DetachAllChildren() {
while (!children_.empty())
while (!children_.empty()) {
children_[0]->Detach();
}
}
/// @brief Draw the component.
@@ -85,8 +87,9 @@ void ComponentBase::DetachAllChildren() {
/// ftxui::ComponentBase.
/// @ingroup component
Element ComponentBase::Render() {
if (children_.size() == 1)
if (children_.size() == 1) {
return children_.front()->Render();
}
return text("Not implemented component");
}
@@ -97,10 +100,11 @@ Element ComponentBase::Render() {
/// The default implementation called OnEvent on every child until one return
/// true. If none returns true, return false.
/// @ingroup component
bool ComponentBase::OnEvent(Event event) {
for (Component& child : children_) {
if (child->OnEvent(event))
bool ComponentBase::OnEvent(Event event) { // NOLINT
for (Component& child : children_) { // NOLINT
if (child->OnEvent(event)) {
return true;
}
}
return false;
}
@@ -110,8 +114,9 @@ bool ComponentBase::OnEvent(Event event) {
/// The default implementation dispatch the event to every child.
/// @ingroup component
void ComponentBase::OnAnimation(animation::Params& params) {
for (Component& child : children_)
for (Component& child : children_) {
child->OnAnimation(params);
}
}
/// @brief Return the currently Active child.
@@ -119,8 +124,9 @@ void ComponentBase::OnAnimation(animation::Params& params) {
/// @ingroup component
Component ComponentBase::ActiveChild() {
for (auto& child : children_) {
if (child->Focusable())
if (child->Focusable()) {
return child;
}
}
return nullptr;
}
@@ -130,9 +136,10 @@ Component ComponentBase::ActiveChild() {
/// keyboard.
/// @ingroup component
bool ComponentBase::Focusable() const {
for (const Component& child : children_) {
if (child->Focusable())
for (const Component& child : children_) { // NOLINT
if (child->Focusable()) {
return true;
}
}
return false;
}
@@ -140,7 +147,7 @@ bool ComponentBase::Focusable() const {
/// @brief Returns if the element if the currently active child of its parent.
/// @ingroup component
bool ComponentBase::Active() const {
return !parent_ || parent_->ActiveChild().get() == this;
return parent_ == nullptr || parent_->ActiveChild().get() == this;
}
/// @brief Returns if the elements if focused by the user.
@@ -149,7 +156,7 @@ bool ComponentBase::Active() const {
/// Focusable().
/// @ingroup component
bool ComponentBase::Focused() const {
auto current = this;
const auto* current = this;
while (current && current->Active()) {
current = current->parent_;
}
@@ -159,12 +166,12 @@ bool ComponentBase::Focused() const {
/// @brief Make the |child| to be the "active" one.
/// @param child the child to become active.
/// @ingroup component
void ComponentBase::SetActiveChild(ComponentBase*) {}
void ComponentBase::SetActiveChild(ComponentBase* /*child*/) {}
/// @brief Make the |child| to be the "active" one.
/// @param child the child to become active.
/// @ingroup component
void ComponentBase::SetActiveChild(Component child) {
void ComponentBase::SetActiveChild(Component child) { // NOLINT
SetActiveChild(child.get());
}
@@ -182,9 +189,10 @@ void ComponentBase::TakeFocus() {
/// them. It represents a component taking priority over others.
/// @param event
/// @ingroup component
CapturedMouse ComponentBase::CaptureMouse(const Event& event) {
if (event.screen_)
CapturedMouse ComponentBase::CaptureMouse(const Event& event) { // NOLINT
if (event.screen_) {
return event.screen_->CaptureMouse();
}
return std::make_unique<CaptureMouseImpl>();
}

View File

@@ -1,9 +1,10 @@
#include "ftxui/component/component_options.hpp"
#include <memory> // for allocator, shared_ptr
#include <memory> // for shared_ptr
#include <utility> // for move
#include "ftxui/component/animation.hpp" // for Function, Duration
#include "ftxui/dom/elements.hpp" // for Element, operator|, text, bold, dim, inverted, automerge
#include "ftxui/dom/elements.hpp" // for operator|=, text, Element, bold, inverted, operator|, dim, hbox, automerge, borderEmpty, borderLight
namespace ftxui {
@@ -15,13 +16,13 @@ void AnimatedColorOption::Set(Color a_inactive,
inactive = a_inactive;
active = a_active;
duration = a_duration;
function = a_function;
function = std::move(a_function);
}
void UnderlineOption::SetAnimation(animation::Duration d,
animation::easing::Function f) {
SetAnimationDuration(d);
SetAnimationFunction(f);
SetAnimationFunction(std::move(f));
}
void UnderlineOption::SetAnimationDuration(animation::Duration d) {
@@ -31,28 +32,31 @@ void UnderlineOption::SetAnimationDuration(animation::Duration d) {
void UnderlineOption::SetAnimationFunction(animation::easing::Function f) {
leader_function = f;
follower_function = f;
follower_function = std::move(f);
}
void UnderlineOption::SetAnimationFunction(
animation::easing::Function f_leader,
animation::easing::Function f_follower) {
leader_function = f_leader;
follower_function = f_follower;
leader_function = std::move(f_leader);
follower_function = std::move(f_follower);
}
// static
MenuOption MenuOption::Horizontal() {
MenuOption option;
option.direction = Direction::Right;
option.entries.transform = [](EntryState state) {
option.entries.transform = [](const EntryState& state) {
Element e = text(state.label);
if (state.focused)
if (state.focused) {
e |= inverted;
if (state.active)
}
if (state.active) {
e |= bold;
if (!state.focused && !state.active)
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
option.elements_infix = [] { return text(" "); };
@@ -70,19 +74,17 @@ MenuOption MenuOption::HorizontalAnimated() {
// static
MenuOption MenuOption::Vertical() {
MenuOption option;
option.entries.transform = [](EntryState state) {
if (state.active)
state.label = "> " + state.label;
else
state.label = " " + state.label;
Element e = text(state.label);
if (state.focused)
option.entries.transform = [](const EntryState& state) {
Element e = text((state.active ? "> " : " ") + state.label); // NOLINT
if (state.focused) {
e |= inverted;
if (state.active)
}
if (state.active) {
e |= bold;
if (!state.focused && !state.active)
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
return option;
@@ -91,14 +93,17 @@ MenuOption MenuOption::Vertical() {
// static
MenuOption MenuOption::VerticalAnimated() {
auto option = MenuOption::Vertical();
option.entries.transform = [](EntryState state) {
option.entries.transform = [](const EntryState& state) {
Element e = text(state.label);
if (state.focused)
if (state.focused) {
e |= inverted;
if (state.active)
}
if (state.active) {
e |= bold;
if (!state.focused && !state.active)
}
if (!state.focused && !state.active) {
e |= dim;
}
return e;
};
option.underline.enabled = true;
@@ -116,10 +121,10 @@ MenuOption MenuOption::Toggle() {
// static
ButtonOption ButtonOption::Ascii() {
ButtonOption option;
option.transform = [](EntryState s) {
s.label = s.focused ? "[" + s.label + "]" //
: " " + s.label + " ";
return text(s.label);
option.transform = [](const EntryState& s) {
std::string label = s.focused ? "[" + s.label + "]" //
: " " + s.label + " ";
return text(label);
};
return option;
}
@@ -128,10 +133,11 @@ ButtonOption ButtonOption::Ascii() {
// static
ButtonOption ButtonOption::Simple() {
ButtonOption option;
option.transform = [](EntryState s) {
option.transform = [](const EntryState& s) {
auto element = text(s.label) | borderLight;
if (s.focused)
if (s.focused) {
element |= inverted;
}
return element;
};
return option;
@@ -147,10 +153,11 @@ ButtonOption ButtonOption::Animated() {
/// @brief Create a ButtonOption, using animated colors.
// static
ButtonOption ButtonOption::Animated(Color color) {
return ButtonOption::Animated(Color::Interpolate(0.85f, color, Color::Black),
Color::Interpolate(0.10f, color, Color::White),
Color::Interpolate(0.10f, color, Color::Black),
Color::Interpolate(0.85f, color, Color::White));
return ButtonOption::Animated(
Color::Interpolate(0.85F, color, Color::Black), // NOLINT
Color::Interpolate(0.10F, color, Color::White), // NOLINT
Color::Interpolate(0.10F, color, Color::Black), // NOLINT
Color::Interpolate(0.85F, color, Color::White)); // NOLINT
}
/// @brief Create a ButtonOption, using animated colors.
@@ -163,17 +170,18 @@ ButtonOption ButtonOption::Animated(Color background, Color foreground) {
// static
ButtonOption ButtonOption::Animated(Color background,
Color foreground,
Color background_focused,
Color foreground_focused) {
Color background_active,
Color foreground_active) {
ButtonOption option;
option.transform = [](EntryState s) {
option.transform = [](const EntryState& s) {
auto element = text(s.label) | borderEmpty;
if (s.focused)
if (s.focused) {
element |= bold;
}
return element;
};
option.animated_colors.foreground.Set(foreground, foreground_focused);
option.animated_colors.background.Set(background, background_focused);
option.animated_colors.foreground.Set(foreground, foreground_active);
option.animated_colors.background.Set(background, background_active);
return option;
}
@@ -181,19 +189,21 @@ ButtonOption ButtonOption::Animated(Color background,
// static
CheckboxOption CheckboxOption::Simple() {
auto option = CheckboxOption();
option.transform = [](EntryState s) {
option.transform = [](const EntryState& s) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
auto prefix = text(s.state ? "[X] " : "[ ] ");
auto prefix = text(s.state ? "[X] " : "[ ] "); // NOLINT
#else
auto prefix = text(s.state ? "" : "");
auto prefix = text(s.state ? "" : ""); // NOLINT
#endif
auto t = text(s.label);
if (s.active)
if (s.active) {
t |= bold;
if (s.focused)
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
return option;
@@ -203,19 +213,21 @@ CheckboxOption CheckboxOption::Simple() {
// static
RadioboxOption RadioboxOption::Simple() {
auto option = RadioboxOption();
option.transform = [](EntryState s) {
option.transform = [](const EntryState& s) {
#if defined(FTXUI_MICROSOFT_TERMINAL_FALLBACK)
// Microsoft terminal do not use fonts able to render properly the default
// radiobox glyph.
auto prefix = text(s.state ? "(*) " : "( ) ");
auto prefix = text(s.state ? "(*) " : "( ) "); // NOLINT
#else
auto prefix = text(s.state ? "" : "");
auto prefix = text(s.state ? "" : ""); // NOLINT
#endif
auto t = text(s.label);
if (s.active)
if (s.active) {
t |= bold;
if (s.focused)
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
return option;

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <cstddef> // for size_t
#include <memory> // for make_shared, __shared_ptr_access, allocator, shared_ptr, allocator_traits<>::value_type
#include <utility> // for move
#include <vector> // for vector, __alloc_traits<>::value_type
@@ -17,27 +17,32 @@ class ContainerBase : public ComponentBase {
public:
ContainerBase(Components children, int* selector)
: selector_(selector ? selector : &selected_) {
for (Component& child : children)
for (Component& child : children) {
Add(std::move(child));
}
}
// Component override.
bool OnEvent(Event event) override {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (!Focused())
if (!Focused()) {
return false;
}
if (ActiveChild() && ActiveChild()->OnEvent(event))
if (ActiveChild() && ActiveChild()->OnEvent(event)) {
return true;
}
return EventHandler(event);
}
Component ActiveChild() override {
if (children_.size() == 0)
if (children_.empty()) {
return nullptr;
}
return children_[*selector_ % children_.size()];
}
@@ -45,7 +50,7 @@ class ContainerBase : public ComponentBase {
void SetActiveChild(ComponentBase* child) override {
for (size_t i = 0; i < children_.size(); ++i) {
if (children_[i].get() == child) {
*selector_ = i;
*selector_ = (int)i;
return;
}
}
@@ -53,10 +58,10 @@ class ContainerBase : public ComponentBase {
protected:
// Handlers
virtual bool EventHandler(Event) { return false; }
virtual bool EventHandler(Event /*unused*/) { return false; } // NOLINT
virtual bool OnMouseEvent(Event event) {
return ComponentBase::OnEvent(event);
return ComponentBase::OnEvent(std::move(event));
}
int selected_ = 0;
@@ -71,11 +76,16 @@ class ContainerBase : public ComponentBase {
}
}
}
void MoveSelectorWrap(int dir) {
if (children_.empty()) {
return;
}
for (size_t offset = 1; offset < children_.size(); ++offset) {
int i = (*selector_ + offset * dir + children_.size()) % children_.size();
size_t i = ((size_t(*selector_ + offset * dir + children_.size())) %
children_.size());
if (children_[i]->Focusable()) {
*selector_ = i;
*selector_ = (int)i;
return;
}
}
@@ -88,60 +98,74 @@ class VerticalContainer : public ContainerBase {
Element Render() override {
Elements elements;
for (auto& it : children_)
for (auto& it : children_) {
elements.push_back(it->Render());
if (elements.size() == 0)
}
if (elements.empty()) {
return text("Empty container") | reflect(box_);
}
return vbox(std::move(elements)) | reflect(box_);
}
bool EventHandler(Event event) override {
int old_selected = *selector_;
if (event == Event::ArrowUp || event == Event::Character('k'))
if (event == Event::ArrowUp || event == Event::Character('k')) {
MoveSelector(-1);
if (event == Event::ArrowDown || event == Event::Character('j'))
}
if (event == Event::ArrowDown || event == Event::Character('j')) {
MoveSelector(+1);
}
if (event == Event::PageUp) {
for (int i = 0; i < box_.y_max - box_.y_min; ++i)
for (int i = 0; i < box_.y_max - box_.y_min; ++i) {
MoveSelector(-1);
}
}
if (event == Event::PageDown) {
for (int i = 0; i < box_.y_max - box_.y_min; ++i)
for (int i = 0; i < box_.y_max - box_.y_min; ++i) {
MoveSelector(1);
}
}
if (event == Event::Home) {
for (size_t i = 0; i < children_.size(); ++i)
for (size_t i = 0; i < children_.size(); ++i) {
MoveSelector(-1);
}
}
if (event == Event::End) {
for (size_t i = 0; i < children_.size(); ++i)
for (size_t i = 0; i < children_.size(); ++i) {
MoveSelector(1);
}
}
if (event == Event::Tab && children_.size())
if (event == Event::Tab) {
MoveSelectorWrap(+1);
if (event == Event::TabReverse && children_.size())
}
if (event == Event::TabReverse) {
MoveSelectorWrap(-1);
}
*selector_ = std::max(0, std::min(int(children_.size()) - 1, *selector_));
return old_selected != *selector_;
}
bool OnMouseEvent(Event event) override {
if (ContainerBase::OnMouseEvent(event))
if (ContainerBase::OnMouseEvent(event)) {
return true;
}
if (event.mouse().button != Mouse::WheelUp &&
event.mouse().button != Mouse::WheelDown) {
return false;
}
if (!box_.Contain(event.mouse().x, event.mouse().y))
if (!box_.Contain(event.mouse().x, event.mouse().y)) {
return false;
}
if (event.mouse().button == Mouse::WheelUp)
if (event.mouse().button == Mouse::WheelUp) {
MoveSelector(-1);
if (event.mouse().button == Mouse::WheelDown)
}
if (event.mouse().button == Mouse::WheelDown) {
MoveSelector(+1);
}
*selector_ = std::max(0, std::min(int(children_.size()) - 1, *selector_));
return true;
@@ -156,23 +180,29 @@ class HorizontalContainer : public ContainerBase {
Element Render() override {
Elements elements;
for (auto& it : children_)
for (auto& it : children_) {
elements.push_back(it->Render());
if (elements.size() == 0)
}
if (elements.empty()) {
return text("Empty container");
}
return hbox(std::move(elements));
}
bool EventHandler(Event event) override {
int old_selected = *selector_;
if (event == Event::ArrowLeft || event == Event::Character('h'))
if (event == Event::ArrowLeft || event == Event::Character('h')) {
MoveSelector(-1);
if (event == Event::ArrowRight || event == Event::Character('l'))
}
if (event == Event::ArrowRight || event == Event::Character('l')) {
MoveSelector(+1);
if (event == Event::Tab && children_.size())
}
if (event == Event::Tab) {
MoveSelectorWrap(+1);
if (event == Event::TabReverse && children_.size())
}
if (event == Event::TabReverse) {
MoveSelectorWrap(-1);
}
*selector_ = std::max(0, std::min(int(children_.size()) - 1, *selector_));
return old_selected != *selector_;
@@ -185,14 +215,16 @@ class TabContainer : public ContainerBase {
Element Render() override {
Component active_child = ActiveChild();
if (active_child)
if (active_child) {
return active_child->Render();
}
return text("Empty container");
}
bool Focusable() const override {
if (children_.size() == 0)
if (children_.empty()) {
return false;
}
return children_[*selector_ % children_.size()]->Focusable();
}

View File

@@ -1,12 +1,12 @@
#include <algorithm> // for max, min
#include <memory> // for __shared_ptr_access
#include <string> // for string
#include <utility> // for move
#include <algorithm> // for max, min
#include <functional> // for function
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
#include <string> // for string
#include "ftxui/component/component.hpp" // for Maybe, Checkbox, Make, Radiobox, Vertical, Dropdown
#include "ftxui/component/component_base.hpp" // for Component, ComponentBase
#include "ftxui/component/component_options.hpp" // for CheckboxOption
#include "ftxui/dom/elements.hpp" // for operator|, Element, border, filler, separator, size, vbox, frame, vscroll_indicator, HEIGHT, LESS_THAN
#include "ftxui/component/component_options.hpp" // for CheckboxOption, EntryState
#include "ftxui/dom/elements.hpp" // for operator|, Element, border, filler, operator|=, separator, size, text, vbox, frame, vscroll_indicator, hbox, HEIGHT, LESS_THAN, bold, inverted
#include "ftxui/util/ref.hpp" // for ConstStringListRef
namespace ftxui {
@@ -15,15 +15,17 @@ Component Dropdown(ConstStringListRef entries, int* selected) {
class Impl : public ComponentBase {
public:
Impl(ConstStringListRef entries, int* selected)
: entries_(std::move(entries)), selected_(selected) {
: entries_(entries), selected_(selected) {
CheckboxOption option;
option.transform = [](EntryState s) {
auto prefix = text(s.state ? "" : "");
option.transform = [](const EntryState& s) {
auto prefix = text(s.state ? "" : ""); // NOLINT
auto t = text(s.label);
if (s.active)
if (s.active) {
t |= bold;
if (s.focused)
}
if (s.focused) {
t |= inverted;
}
return hbox({prefix, t});
};
checkbox_ = Checkbox(&title_, &show_, option),
@@ -39,11 +41,12 @@ Component Dropdown(ConstStringListRef entries, int* selected) {
*selected_ = std::min((int)entries_.size() - 1, std::max(0, *selected_));
title_ = entries_[*selected_];
if (show_) {
const int max_height = 12;
return vbox({
checkbox_->Render(),
separator(),
radiobox_->Render() | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, 12),
size(HEIGHT, LESS_THAN, max_height),
}) |
border;
}
@@ -63,7 +66,7 @@ Component Dropdown(ConstStringListRef entries, int* selected) {
Component radiobox_;
};
return Make<Impl>(std::move(entries), selected);
return Make<Impl>(entries, selected);
}
} // namespace ftxui

View File

@@ -29,7 +29,7 @@ Event Event::Mouse(std::string input, struct Mouse mouse) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::Mouse;
event.mouse_ = mouse;
event.mouse_ = mouse; // NOLINT
return event;
}
@@ -45,40 +45,39 @@ Event Event::CursorReporting(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::CursorReporting;
event.cursor_.x = x;
event.cursor_.y = y;
event.cursor_.x = x; // NOLINT
event.cursor_.y = y; // NOLINT
return event;
}
// --- Arrow ---
const Event Event::ArrowLeft = Event::Special("\x1B[D");
const Event Event::ArrowRight = Event::Special("\x1B[C");
const Event Event::ArrowUp = Event::Special("\x1B[A");
const Event Event::ArrowDown = Event::Special("\x1B[B");
const Event Event::Backspace = Event::Special({127});
const Event Event::Delete = Event::Special("\x1B[3~");
const Event Event::Escape = Event::Special("\x1B");
const Event Event::Return = Event::Special({10});
const Event Event::Tab = Event::Special({9});
const Event Event::TabReverse = Event::Special({27, 91, 90});
const Event Event::F1 = Event::Special("\x1B[OP");
const Event Event::F2 = Event::Special("\x1B[OQ");
const Event Event::F3 = Event::Special("\x1B[OR");
const Event Event::F4 = Event::Special("\x1B[OS");
const Event Event::F5 = Event::Special("\x1B[15~");
const Event Event::F6 = Event::Special("\x1B[17~");
const Event Event::F7 = Event::Special("\x1B[18~");
const Event Event::F8 = Event::Special("\x1B[19~");
const Event Event::F9 = Event::Special("\x1B[20~");
const Event Event::F10 = Event::Special("\x1B[21~");
const Event Event::F11 = Event::Special("\x1B[21~"); // Doesn't exist
const Event Event::F12 = Event::Special("\x1B[24~");
const Event Event::Home = Event::Special({27, 91, 72});
const Event Event::End = Event::Special({27, 91, 70});
const Event Event::PageUp = Event::Special({27, 91, 53, 126});
const Event Event::PageDown = Event::Special({27, 91, 54, 126});
Event Event::Custom = Event::Special({0});
const Event Event::ArrowLeft = Event::Special("\x1B[D"); // NOLINT
const Event Event::ArrowRight = Event::Special("\x1B[C"); // NOLINT
const Event Event::ArrowUp = Event::Special("\x1B[A"); // NOLINT
const Event Event::ArrowDown = Event::Special("\x1B[B"); // NOLINT
const Event Event::Backspace = Event::Special({127}); // NOLINT
const Event Event::Delete = Event::Special("\x1B[3~"); // NOLINT
const Event Event::Escape = Event::Special("\x1B"); // NOLINT
const Event Event::Return = Event::Special({10}); // NOLINT
const Event Event::Tab = Event::Special({9}); // NOLINT
const Event Event::TabReverse = Event::Special({27, 91, 90}); // NOLINT
const Event Event::F1 = Event::Special("\x1B[OP"); // NOLINT
const Event Event::F2 = Event::Special("\x1B[OQ"); // NOLINT
const Event Event::F3 = Event::Special("\x1B[OR"); // NOLINT
const Event Event::F4 = Event::Special("\x1B[OS"); // NOLINT
const Event Event::F5 = Event::Special("\x1B[15~"); // NOLINT
const Event Event::F6 = Event::Special("\x1B[17~"); // NOLINT
const Event Event::F7 = Event::Special("\x1B[18~"); // NOLINT
const Event Event::F8 = Event::Special("\x1B[19~"); // NOLINT
const Event Event::F9 = Event::Special("\x1B[20~"); // NOLINT
const Event Event::F10 = Event::Special("\x1B[21~"); // NOLINT
const Event Event::F11 = Event::Special("\x1B[21~"); // Doesn't exist // NOLINT
const Event Event::F12 = Event::Special("\x1B[24~"); // NOLINT
const Event Event::Home = Event::Special({27, 91, 72}); // NOLINT
const Event Event::End = Event::Special({27, 91, 70}); // NOLINT
const Event Event::PageUp = Event::Special({27, 91, 53, 126}); // NOLINT
const Event Event::PageDown = Event::Special({27, 91, 54, 126}); // NOLINT
const Event Event::Custom = Event::Special({0}); // NOLINT
} // namespace ftxui

View File

@@ -1,5 +1,5 @@
#include <stddef.h> // for size_t
#include <algorithm> // for max, min
#include <cstddef> // for size_t
#include <functional> // for function
#include <memory> // for shared_ptr, allocator
#include <string> // for string, wstring
@@ -24,11 +24,12 @@ namespace ftxui {
namespace {
std::string PasswordField(int size) {
std::string PasswordField(size_t size) {
std::string out;
out.reserve(2 * size);
while (size--)
while (size--) {
out += "";
}
return out;
}
@@ -38,21 +39,25 @@ class InputBase : public ComponentBase {
InputBase(StringRef content,
ConstStringRef placeholder,
Ref<InputOption> option)
: content_(content), placeholder_(placeholder), option_(option) {}
: content_(std::move(content)),
placeholder_(std::move(placeholder)),
option_(std::move(option)) {}
int cursor_position_internal_ = 0;
int& cursor_position() {
int& opt = option_->cursor_position();
if (opt != -1)
if (opt != -1) {
return opt;
}
return cursor_position_internal_;
}
// Component implementation:
Element Render() override {
std::string password_content;
if (option_->password())
if (option_->password()) {
password_content = PasswordField(content_->size());
}
std::string& content = option_->password() ? password_content : *content_;
int size = GlyphCount(content);
@@ -65,19 +70,22 @@ class InputBase : public ComponentBase {
if (size == 0) {
bool hovered = hovered_;
Decorator decorator = dim | main_decorator;
if (is_focused)
if (is_focused) {
decorator = decorator | focus;
if (hovered || is_focused)
}
if (hovered || is_focused) {
decorator = decorator | inverted;
}
return text(*placeholder_) | decorator | reflect(box_);
}
// Not focused.
if (!is_focused) {
if (hovered_)
if (hovered_) {
return text(content) | main_decorator | inverted | reflect(box_);
else
} else {
return text(content) | main_decorator | reflect(box_);
}
}
int index_before_cursor = GlyphPosition(content, cursor_position());
@@ -100,17 +108,19 @@ class InputBase : public ComponentBase {
bool OnEvent(Event event) override {
cursor_position() =
std::max(0, std::min<int>(content_->size(), cursor_position()));
std::max(0, std::min<int>((int)content_->size(), cursor_position()));
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
std::string c;
// Backspace.
if (event == Event::Backspace) {
if (cursor_position() == 0)
if (cursor_position() == 0) {
return false;
}
size_t start = GlyphPosition(*content_, cursor_position() - 1);
size_t end = GlyphPosition(*content_, cursor_position());
content_->erase(start, end - start);
@@ -121,8 +131,9 @@ class InputBase : public ComponentBase {
// Delete
if (event == Event::Delete) {
if (cursor_position() == int(content_->size()))
if (cursor_position() == int(content_->size())) {
return false;
}
size_t start = GlyphPosition(*content_, cursor_position());
size_t end = GlyphPosition(*content_, cursor_position() + 1);
content_->erase(start, end - start);
@@ -176,8 +187,9 @@ class InputBase : public ComponentBase {
bool OnMouseEvent(Event event) {
hovered_ =
box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event);
if (!hovered_)
if (!hovered_) {
return false;
}
if (event.mouse().button != Mouse::Left ||
event.mouse().motion != Mouse::Pressed) {
@@ -185,22 +197,24 @@ class InputBase : public ComponentBase {
}
TakeFocus();
if (content_->size() == 0)
if (content_->empty()) {
return true;
}
auto mapping = CellToGlyphIndex(*content_);
int original_glyph = cursor_position();
original_glyph = util::clamp(original_glyph, 0, int(mapping.size()));
int original_cell = 0;
size_t original_cell = 0;
for (size_t i = 0; i < mapping.size(); i++) {
if (mapping[i] == original_glyph) {
original_cell = i;
original_cell = (int)i;
break;
}
}
if (mapping[original_cell] != original_glyph)
if (mapping[original_cell] != original_glyph) {
original_cell = mapping.size();
int target_cell = original_cell + event.mouse().x - cursor_box_.x_min;
}
int target_cell = int(original_cell) + event.mouse().x - cursor_box_.x_min;
int target_glyph = target_cell < (int)mapping.size() ? mapping[target_cell]
: (int)mapping.size();
target_glyph = util::clamp(target_glyph, 0, GlyphCount(*content_));
@@ -279,7 +293,8 @@ class WideInputBase : public InputBase {
Component Input(StringRef content,
ConstStringRef placeholder,
Ref<InputOption> option) {
return Make<InputBase>(content, placeholder, std::move(option));
return Make<InputBase>(std::move(content), std::move(placeholder),
std::move(option));
}
/// @brief . An input box for editing text.
@@ -307,7 +322,8 @@ Component Input(StringRef content,
Component Input(WideStringRef content,
ConstStringRef placeholder,
Ref<InputOption> option) {
return Make<WideInputBase>(content, placeholder, std::move(option));
return Make<WideInputBase>(std::move(content), std::move(placeholder),
std::move(option));
}
} // namespace ftxui

View File

@@ -13,7 +13,7 @@ namespace ftxui {
Component Maybe(Component child, std::function<bool()> show) {
class Impl : public ComponentBase {
public:
Impl(std::function<bool()> show) : show_(std::move(show)) {}
explicit Impl(std::function<bool()> show) : show_(std::move(show)) {}
private:
Element Render() override {
@@ -48,7 +48,7 @@ Component Maybe(Component child, std::function<bool()> show) {
/// ```
ComponentDecorator Maybe(std::function<bool()> show) {
return [show = std::move(show)](Component child) mutable {
return Maybe(child, std::move(show));
return Maybe(std::move(child), std::move(show));
};
}
@@ -64,7 +64,7 @@ ComponentDecorator Maybe(std::function<bool()> show) {
/// auto maybe_component = Maybe(component, &show);
/// ```
Component Maybe(Component child, const bool* show) {
return Maybe(child, [show] { return *show; });
return Maybe(std::move(child), [show] { return *show; });
}
/// @brief Decorate a component. It is shown only when |show| is true.
@@ -78,7 +78,7 @@ Component Maybe(Component child, const bool* show) {
/// auto maybe_component = component | Maybe(&show);
/// ```
ComponentDecorator Maybe(const bool* show) {
return [show](Component child) { return Maybe(child, show); };
return [show](Component child) { return Maybe(std::move(child), show); };
}
} // namespace ftxui

View File

@@ -24,13 +24,15 @@ namespace ftxui {
namespace {
Element DefaultOptionTransform(EntryState state) {
state.label = (state.active ? "> " : " ") + state.label;
Element e = text(state.label);
if (state.focused)
Element DefaultOptionTransform(const EntryState& state) {
std::string label = (state.active ? "> " : " ") + state.label; // NOLINT
Element e = text(label);
if (state.focused) {
e = e | inverted;
if (state.active)
}
if (state.active) {
e = e | bold;
}
return e;
}
@@ -43,7 +45,7 @@ bool IsInverted(MenuOption::Direction direction) {
case MenuOption::Direction::Right:
return false;
}
return false; // NOT_REACHED()
return false; // NOT_REACHED()
}
bool IsHorizontal(MenuOption::Direction direction) {
@@ -55,7 +57,7 @@ bool IsHorizontal(MenuOption::Direction direction) {
case MenuOption::Direction::Up:
return false;
}
return false; // NOT_REACHED()
return false; // NOT_REACHED()
}
} // namespace
@@ -65,17 +67,19 @@ bool IsHorizontal(MenuOption::Direction direction) {
class MenuBase : public ComponentBase {
public:
MenuBase(ConstStringListRef entries, int* selected, Ref<MenuOption> option)
: entries_(entries), selected_(selected), option_(option) {}
: entries_(entries), selected_(selected), option_(std::move(option)) {}
bool IsHorizontal() { return ftxui::IsHorizontal(option_->direction); }
void OnChange() {
if (option_->on_change)
if (option_->on_change) {
option_->on_change();
}
}
void OnEnter() {
if (option_->on_enter)
if (option_->on_enter) {
option_->on_enter();
}
}
void Clamp() {
@@ -87,10 +91,12 @@ class MenuBase : public ComponentBase {
void OnAnimation(animation::Params& params) override {
animator_first_.OnAnimation(params);
animator_second_.OnAnimation(params);
for (auto& animator : animator_background_)
for (auto& animator : animator_background_) {
animator.OnAnimation(params);
for (auto& animator : animator_foreground_)
}
for (auto& animator : animator_foreground_) {
animator.OnAnimation(params);
}
}
Element Render() override {
@@ -99,11 +105,13 @@ class MenuBase : public ComponentBase {
Elements elements;
bool is_menu_focused = Focused();
if (option_->elements_prefix)
if (option_->elements_prefix) {
elements.push_back(option_->elements_prefix());
}
for (int i = 0; i < size(); ++i) {
if (i != 0 && option_->elements_infix)
if (i != 0 && option_->elements_infix) {
elements.push_back(option_->elements_infix());
}
bool is_focused = (focused_entry() == i) && is_menu_focused;
bool is_selected = (*selected_ == i);
@@ -120,21 +128,24 @@ class MenuBase : public ComponentBase {
Element element =
(option_->entries.transform ? option_->entries.transform
: DefaultOptionTransform) //
(std::move(state));
(state);
elements.push_back(element | AnimatedColorStyle(i) | reflect(boxes_[i]) |
focus_management);
}
if (option_->elements_postfix)
if (option_->elements_postfix) {
elements.push_back(option_->elements_postfix());
}
if (IsInverted(option_->direction))
if (IsInverted(option_->direction)) {
std::reverse(elements.begin(), elements.end());
}
Element bar =
IsHorizontal() ? hbox(std::move(elements)) : vbox(std::move(elements));
if (!option_->underline.enabled)
if (!option_->underline.enabled) {
return bar | reflect(box_);
}
if (IsHorizontal()) {
return vbox({
@@ -211,36 +222,49 @@ class MenuBase : public ComponentBase {
}
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
bool OnEvent(Event event) override {
Clamp();
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (Focused()) {
int old_selected = *selected_;
if (event == Event::ArrowUp || event == Event::Character('k'))
if (event == Event::ArrowUp || event == Event::Character('k')) {
OnUp();
if (event == Event::ArrowDown || event == Event::Character('j'))
}
if (event == Event::ArrowDown || event == Event::Character('j')) {
OnDown();
if (event == Event::ArrowLeft || event == Event::Character('h'))
}
if (event == Event::ArrowLeft || event == Event::Character('h')) {
OnLeft();
if (event == Event::ArrowRight || event == Event::Character('l'))
}
if (event == Event::ArrowRight || event == Event::Character('l')) {
OnRight();
if (event == Event::PageUp)
}
if (event == Event::PageUp) {
(*selected_) -= box_.y_max - box_.y_min;
if (event == Event::PageDown)
}
if (event == Event::PageDown) {
(*selected_) += box_.y_max - box_.y_min;
if (event == Event::Home)
}
if (event == Event::Home) {
(*selected_) = 0;
if (event == Event::End)
}
if (event == Event::End) {
(*selected_) = size() - 1;
if (event == Event::Tab && size())
}
if (event == Event::Tab && size()) {
*selected_ = (*selected_ + 1) % size();
if (event == Event::TabReverse && size())
}
if (event == Event::TabReverse && size()) {
*selected_ = (*selected_ + size() - 1) % size();
}
*selected_ = util::clamp(*selected_, 0, size() - 1);
@@ -269,11 +293,13 @@ class MenuBase : public ComponentBase {
event.mouse().button != Mouse::Left) {
return false;
}
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
for (int i = 0; i < size(); ++i) {
if (!boxes_[i].Contain(event.mouse().x, event.mouse().y))
if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) {
continue;
}
TakeFocus();
focused_entry() = i;
@@ -290,19 +316,23 @@ class MenuBase : public ComponentBase {
}
bool OnMouseWheel(Event event) {
if (!box_.Contain(event.mouse().x, event.mouse().y))
if (!box_.Contain(event.mouse().x, event.mouse().y)) {
return false;
}
int old_selected = *selected_;
if (event.mouse().button == Mouse::WheelUp)
if (event.mouse().button == Mouse::WheelUp) {
(*selected_)--;
if (event.mouse().button == Mouse::WheelDown)
}
if (event.mouse().button == Mouse::WheelDown) {
(*selected_)++;
}
*selected_ = util::clamp(*selected_, 0, size() - 1);
if (*selected_ != old_selected)
if (*selected_ != old_selected) {
OnChange();
}
return true;
}
@@ -319,12 +349,12 @@ class MenuBase : public ComponentBase {
animator_foreground_.clear();
for (int i = 0; i < size(); ++i) {
animation_background_[i] = 0.f;
animation_foreground_[i] = 0.f;
animator_background_.emplace_back(&animation_background_[i], 0.f,
animation_background_[i] = 0.F;
animation_foreground_[i] = 0.F;
animator_background_.emplace_back(&animation_background_[i], 0.F,
std::chrono::milliseconds(0),
animation::easing::Linear);
animator_foreground_.emplace_back(&animation_foreground_[i], 0.f,
animator_foreground_.emplace_back(&animation_foreground_[i], 0.F,
std::chrono::milliseconds(0),
animation::easing::Linear);
}
@@ -334,7 +364,7 @@ class MenuBase : public ComponentBase {
for (int i = 0; i < size(); ++i) {
bool is_focused = (focused_entry() == i) && is_menu_focused;
bool is_selected = (*selected_ == i);
float target = is_selected ? 1.f : is_focused ? 0.5f : 0.f;
float target = is_selected ? 1.F : is_focused ? 0.5F : 0.F; // NOLINT
if (animator_background_[i].to() != target) {
animator_background_[i] = animation::Animator(
&animation_background_[i], target,
@@ -367,8 +397,9 @@ class MenuBase : public ComponentBase {
}
void UpdateUnderlineTarget() {
if (!option_->underline.enabled)
if (!option_->underline.enabled) {
return;
}
if (FirstTarget() == animator_first_.to() &&
SecondTarget() == animator_second_.to()) {
@@ -398,32 +429,36 @@ class MenuBase : public ComponentBase {
bool Focusable() const final { return entries_.size(); }
int& focused_entry() { return option_->focused_entry(); }
int size() const { return entries_.size(); }
int FirstTarget() {
if (boxes_.size() == 0)
return 0;
return IsHorizontal() ? boxes_[*selected_].x_min - box_.x_min
: boxes_[*selected_].y_min - box_.y_min;
int size() const { return int(entries_.size()); }
float FirstTarget() {
if (boxes_.empty()) {
return 0.F;
}
int value = IsHorizontal() ? boxes_[*selected_].x_min - box_.x_min
: boxes_[*selected_].y_min - box_.y_min;
return float(value);
}
int SecondTarget() {
if (boxes_.size() == 0)
return 0;
return IsHorizontal() ? boxes_[*selected_].x_max - box_.x_min
: boxes_[*selected_].y_max - box_.y_min;
float SecondTarget() {
if (boxes_.empty()) {
return 0.F;
}
int value = IsHorizontal() ? boxes_[*selected_].x_max - box_.x_min
: boxes_[*selected_].y_max - box_.y_min;
return float(value);
}
protected:
ConstStringListRef entries_;
int* selected_ = 0;
int* selected_ = nullptr;
Ref<MenuOption> option_;
std::vector<Box> boxes_;
Box box_;
float first_ = 0.f;
float second_ = 0.f;
animation::Animator animator_first_ = animation::Animator(&first_, 0.f);
animation::Animator animator_second_ = animation::Animator(&second_, 0.f);
float first_ = 0.F;
float second_ = 0.F;
animation::Animator animator_first_ = animation::Animator(&first_, 0.F);
animation::Animator animator_second_ = animation::Animator(&second_, 0.F);
std::vector<animation::Animator> animator_background_;
std::vector<animation::Animator> animator_foreground_;
@@ -519,7 +554,7 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
Element element =
(option_->transform ? option_->transform : DefaultOptionTransform) //
(std::move(state));
(state);
auto focus_management = focused ? select : nothing;
return element | AnimatedColorStyle() | focus_management | reflect(box_);
@@ -527,9 +562,10 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
void UpdateAnimationTarget() {
bool focused = Focused();
float target = focused ? 1.0f : hovered_ ? 0.5f : 0.0f;
if (target == animator_background_.to())
float target = focused ? 1.F : hovered_ ? 0.5F : 0.F; // NOLINT
if (target == animator_background_.to()) {
return;
}
animator_background_ =
animation::Animator(&animation_background_, target,
option_->animated_colors.background.duration,
@@ -560,13 +596,15 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
bool Focusable() const override { return true; }
bool OnEvent(Event event) override {
if (!event.is_mouse())
if (!event.is_mouse()) {
return false;
}
hovered_ = box_.Contain(event.mouse().x, event.mouse().y);
if (!hovered_)
if (!hovered_) {
return false;
}
if (event.mouse().button == Mouse::Left &&
event.mouse().motion == Mouse::Released) {
@@ -587,12 +625,12 @@ Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> option) {
Box box_;
bool hovered_ = false;
float animation_background_ = 0.f;
float animation_foreground_ = 0.f;
float animation_background_ = 0.F;
float animation_foreground_ = 0.F;
animation::Animator animator_background_ =
animation::Animator(&animation_background_, 0.f);
animation::Animator(&animation_background_, 0.F);
animation::Animator animator_foreground_ =
animation::Animator(&animation_foreground_, 0.f);
animation::Animator(&animation_foreground_, 0.F);
};
return Make<Impl>(std::move(label), std::move(option));

View File

@@ -1,21 +1,20 @@
#include <algorithm> // for max
#include <functional> // for function
#include <memory> // for shared_ptr, allocator_traits<>::value_type
#include <string> // for string
#include <utility> // for move
#include <vector> // for vector
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
#include "ftxui/component/component.hpp" // for Make, Radiobox
#include "ftxui/component/component_base.hpp" // for ComponentBase
#include "ftxui/component/component_options.hpp" // for RadioboxOption
#include "ftxui/component/component_options.hpp" // for RadioboxOption, EntryState
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::End, Event::Home, Event::PageDown, Event::PageUp, Event::Return, Event::Tab, Event::TabReverse
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::WheelDown, Mouse::WheelUp, Mouse::Left, Mouse::Released
#include "ftxui/component/screen_interactive.hpp" // for Component
#include "ftxui/dom/elements.hpp" // for operator|, reflect, text, Element, hbox, vbox, Elements, focus, nothing, select
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/util.hpp" // for clamp
#include "ftxui/util/ref.hpp" // for Ref, ConstStringListRef
#include "ftxui/dom/elements.hpp" // for operator|, reflect, Element, vbox, Elements, focus, nothing, select
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/util.hpp" // for clamp
#include "ftxui/util/ref.hpp" // for Ref, ConstStringListRef
namespace ftxui {
@@ -50,41 +49,51 @@ class RadioboxBase : public ComponentBase {
is_focused,
};
auto element =
(option_->transform
? option_->transform
: RadioboxOption::Simple().transform)(std::move(state));
(option_->transform ? option_->transform
: RadioboxOption::Simple().transform)(state);
elements.push_back(element | focus_management | reflect(boxes_[i]));
}
return vbox(std::move(elements)) | reflect(box_);
}
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
bool OnEvent(Event event) override {
Clamp();
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (Focused()) {
int old_hovered = hovered_;
if (event == Event::ArrowUp || event == Event::Character('k'))
if (event == Event::ArrowUp || event == Event::Character('k')) {
(hovered_)--;
if (event == Event::ArrowDown || event == Event::Character('j'))
}
if (event == Event::ArrowDown || event == Event::Character('j')) {
(hovered_)++;
if (event == Event::PageUp)
}
if (event == Event::PageUp) {
(hovered_) -= box_.y_max - box_.y_min;
if (event == Event::PageDown)
}
if (event == Event::PageDown) {
(hovered_) += box_.y_max - box_.y_min;
if (event == Event::Home)
}
if (event == Event::Home) {
(hovered_) = 0;
if (event == Event::End)
}
if (event == Event::End) {
(hovered_) = size() - 1;
if (event == Event::Tab && size())
}
if (event == Event::Tab && size()) {
hovered_ = (hovered_ + 1) % size();
if (event == Event::TabReverse && size())
}
if (event == Event::TabReverse && size()) {
hovered_ = (hovered_ + size() - 1) % size();
}
hovered_ = util::clamp(hovered_, 0, size() - 1);
@@ -111,8 +120,9 @@ class RadioboxBase : public ComponentBase {
}
for (int i = 0; i < size(); ++i) {
if (!boxes_[i].Contain(event.mouse().x, event.mouse().y))
if (!boxes_[i].Contain(event.mouse().x, event.mouse().y)) {
continue;
}
TakeFocus();
focused_entry() = i;
@@ -130,20 +140,24 @@ class RadioboxBase : public ComponentBase {
}
bool OnMouseWheel(Event event) {
if (!box_.Contain(event.mouse().x, event.mouse().y))
if (!box_.Contain(event.mouse().x, event.mouse().y)) {
return false;
}
int old_hovered = hovered_;
if (event.mouse().button == Mouse::WheelUp)
if (event.mouse().button == Mouse::WheelUp) {
(hovered_)--;
if (event.mouse().button == Mouse::WheelDown)
}
if (event.mouse().button == Mouse::WheelDown) {
(hovered_)++;
}
hovered_ = util::clamp(hovered_, 0, size() - 1);
if (hovered_ != old_hovered)
if (hovered_ != old_hovered) {
option_->on_change();
}
return true;
}
@@ -157,7 +171,7 @@ class RadioboxBase : public ComponentBase {
bool Focusable() const final { return entries_.size(); }
int& focused_entry() { return option_->focused_entry(); }
int size() const { return entries_.size(); }
int size() const { return int(entries_.size()); }
ConstStringListRef entries_;
int* selected_;

View File

@@ -28,7 +28,8 @@ namespace ftxui {
Component Renderer(std::function<Element()> render) {
class Impl : public ComponentBase {
public:
Impl(std::function<Element()> render) : render_(std::move(render)) {}
explicit Impl(std::function<Element()> render)
: render_(std::move(render)) {}
Element Render() override { return render_(); }
std::function<Element()> render_;
};
@@ -82,15 +83,17 @@ Component Renderer(Component child, std::function<Element()> render) {
Component Renderer(std::function<Element(bool)> render) {
class Impl : public ComponentBase {
public:
Impl(std::function<Element(bool)> render) : render_(std::move(render)) {}
explicit Impl(std::function<Element(bool)> render)
: render_(std::move(render)) {}
private:
Element Render() override { return render_(Focused()) | reflect(box_); }
bool Focusable() const override { return true; }
bool OnEvent(Event event) override {
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
if (!CaptureMouse(event))
if (!CaptureMouse(event)) {
return false;
}
TakeFocus();
}
@@ -118,8 +121,8 @@ Component Renderer(std::function<Element(bool)> render) {
/// | Renderer(inverted);
/// screen.Loop(renderer);
/// ```
ComponentDecorator Renderer(ElementDecorator decorator) {
return [decorator](Component component) {
ComponentDecorator Renderer(ElementDecorator decorator) { // NOLINT
return [decorator](Component component) { // NOLINT
return Renderer(component, [component, decorator] {
return component->Render() | decorator;
});

View File

@@ -15,16 +15,19 @@ namespace {
class ResizableSplitLeftBase : public ComponentBase {
public:
ResizableSplitLeftBase(Component main, Component child, int* main_size)
: main_(main), child_(child), main_size_(main_size) {
: main_(std::move(main)),
child_(std::move(child)),
main_size_(main_size) {
Add(Container::Horizontal({
main,
child,
main_,
child_,
}));
}
bool OnEvent(Event event) final {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(std::move(event));
}
return ComponentBase::OnEvent(std::move(event));
}
@@ -71,16 +74,19 @@ class ResizableSplitLeftBase : public ComponentBase {
class ResizableSplitRightBase : public ComponentBase {
public:
ResizableSplitRightBase(Component main, Component child, int* main_size)
: main_(main), child_(child), main_size_(main_size) {
: main_(std::move(main)),
child_(std::move(child)),
main_size_(main_size) {
Add(Container::Horizontal({
child,
main,
child_,
main_,
}));
}
bool OnEvent(Event event) final {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(std::move(event));
}
return ComponentBase::OnEvent(std::move(event));
}
@@ -127,16 +133,19 @@ class ResizableSplitRightBase : public ComponentBase {
class ResizableSplitTopBase : public ComponentBase {
public:
ResizableSplitTopBase(Component main, Component child, int* main_size)
: main_(main), child_(child), main_size_(main_size) {
: main_(std::move(main)),
child_(std::move(child)),
main_size_(main_size) {
Add(Container::Vertical({
main,
child,
main_,
child_,
}));
}
bool OnEvent(Event event) final {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(std::move(event));
}
return ComponentBase::OnEvent(std::move(event));
}
@@ -183,16 +192,19 @@ class ResizableSplitTopBase : public ComponentBase {
class ResizableSplitBottomBase : public ComponentBase {
public:
ResizableSplitBottomBase(Component main, Component child, int* main_size)
: main_(main), child_(child), main_size_(main_size) {
: main_(std::move(main)),
child_(std::move(child)),
main_size_(main_size) {
Add(Container::Vertical({
child,
main,
child_,
main_,
}));
}
bool OnEvent(Event event) final {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(std::move(event));
}
return ComponentBase::OnEvent(std::move(event));
}

View File

@@ -1,15 +1,15 @@
#include <stdio.h> // for fileno, stdin
#include <algorithm> // for copy, max, min
#include <chrono> // for operator-, duration, operator>=, milliseconds, time_point, common_type<>::type
#include <array> // for array
#include <chrono> // for operator-, milliseconds, duration, operator>=, time_point, common_type<>::type
#include <csignal> // for signal, raise, SIGTSTP, SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, SIGWINCH
#include <cstdlib> // for NULL
#include <cstdio> // for fileno, size_t, stdin
#include <functional> // for function
#include <initializer_list> // for initializer_list
#include <iostream> // for cout, ostream, basic_ostream, operator<<, endl, flush
#include <stack> // for stack
#include <thread> // for thread, sleep_for
#include <type_traits> // for decay_t
#include <utility> // for swap, move
#include <utility> // for move, swap
#include <variant> // for visit
#include <vector> // for vector
@@ -50,14 +50,15 @@ namespace ftxui {
namespace animation {
void RequestAnimationFrame() {
auto* screen = ScreenInteractive::Active();
if (screen)
if (screen) {
screen->RequestAnimationFrame();
}
}
} // namespace animation
namespace {
ScreenInteractive* g_active_screen = nullptr;
ScreenInteractive* g_active_screen = nullptr; // NOLINT
void Flush() {
// Emscripten doesn't implement flush. We interpret zero as flush.
@@ -138,16 +139,14 @@ void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
int CheckStdinReady(int usec_timeout) {
timeval tv = {0, usec_timeout};
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
FD_ZERO(&fds); // NOLINT
FD_SET(STDIN_FILENO, &fds); // NOLINT
select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &tv); // NOLINT
return FD_ISSET(STDIN_FILENO, &fds); // NOLINT
}
// Read char from the terminal.
void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
const int buffer_size = 100;
auto parser = TerminalInputParser(std::move(out));
while (!*quit) {
@@ -156,16 +155,18 @@ void EventListener(std::atomic<bool>* quit, Sender<Task> out) {
continue;
}
char buff[buffer_size];
int l = read(fileno(stdin), buff, buffer_size);
for (int i = 0; i < l; ++i)
parser.Add(buff[i]);
const size_t buffer_size = 100;
std::array<char, buffer_size> buffer; // NOLINT;
int l = read(fileno(stdin), buffer.data(), buffer_size); // NOLINT
for (int i = 0; i < l; ++i) {
parser.Add(buffer[i]); // NOLINT
}
}
}
#endif
const std::string CSI = "\x1b[";
const std::string CSI = "\x1b["; // NOLINT
// DEC: Digital Equipment Corporation
enum class DECMode {
@@ -186,12 +187,13 @@ enum class DSRMode {
kCursor = 6,
};
const std::string Serialize(std::vector<DECMode> parameters) {
std::string Serialize(const std::vector<DECMode>& parameters) {
bool first = true;
std::string out;
for (DECMode parameter : parameters) {
if (!first)
if (!first) {
out += ";";
}
out += std::to_string(int(parameter));
first = false;
}
@@ -199,22 +201,22 @@ const std::string Serialize(std::vector<DECMode> parameters) {
}
// DEC Private Mode Set (DECSET)
const std::string Set(std::vector<DECMode> parameters) {
std::string Set(const std::vector<DECMode>& parameters) {
return CSI + "?" + Serialize(parameters) + "h";
}
// DEC Private Mode Reset (DECRST)
const std::string Reset(std::vector<DECMode> parameters) {
std::string Reset(const std::vector<DECMode>& parameters) {
return CSI + "?" + Serialize(parameters) + "l";
}
// Device Status Report (DSR)
const std::string DeviceStatusReport(DSRMode ps) {
std::string DeviceStatusReport(DSRMode ps) {
return CSI + std::to_string(int(ps)) + "n";
}
using SignalHandler = void(int);
std::stack<Closure> on_exit_functions;
std::stack<Closure> on_exit_functions; // NOLINT
void OnExit(int signal) {
(void)signal;
while (!on_exit_functions.empty()) {
@@ -223,14 +225,14 @@ void OnExit(int signal) {
}
}
auto install_signal_handler = [](int sig, SignalHandler handler) {
const auto install_signal_handler = [](int sig, SignalHandler handler) {
auto old_signal_handler = std::signal(sig, handler);
on_exit_functions.push([=] { std::signal(sig, old_signal_handler); });
};
Closure on_resize = [] {};
Closure g_on_resize = [] {}; // NOLINT
void OnResize(int /* signal */) {
on_resize();
g_on_resize();
}
void OnSigStop(int /*signal*/) {
@@ -239,17 +241,24 @@ void OnSigStop(int /*signal*/) {
class CapturedMouseImpl : public CapturedMouseInterface {
public:
CapturedMouseImpl(std::function<void(void)> callback) : callback_(callback) {}
explicit CapturedMouseImpl(std::function<void(void)> callback)
: callback_(std::move(callback)) {}
~CapturedMouseImpl() override { callback_(); }
CapturedMouseImpl(const CapturedMouseImpl&) = delete;
CapturedMouseImpl(CapturedMouseImpl&&) = delete;
CapturedMouseImpl& operator=(const CapturedMouseImpl&) = delete;
CapturedMouseImpl& operator=(CapturedMouseImpl&&) = delete;
private:
std::function<void(void)> callback_;
};
void AnimationListener(std::atomic<bool>* quit, Sender<Task> out) {
// Animation at around 60fps.
const auto time_delta = std::chrono::milliseconds(15);
while (!*quit) {
out->Send(AnimationTask());
std::this_thread::sleep_for(std::chrono::milliseconds(15));
std::this_thread::sleep_for(time_delta);
}
}
@@ -286,31 +295,36 @@ ScreenInteractive ScreenInteractive::FitComponent() {
}
void ScreenInteractive::Post(Task task) {
if (!quit_)
task_sender_->Send(task);
if (!quit_) {
task_sender_->Send(std::move(task));
}
}
void ScreenInteractive::PostEvent(Event event) {
Post(event);
}
void ScreenInteractive::RequestAnimationFrame() {
if (animation_requested_)
if (animation_requested_) {
return;
}
animation_requested_ = true;
auto now = animation::Clock::now();
if (now - previous_animation_time >= std::chrono::milliseconds(33))
const auto time_histeresis = std::chrono::milliseconds(33);
if (now - previous_animation_time >= time_histeresis) {
previous_animation_time = now;
}
}
CapturedMouse ScreenInteractive::CaptureMouse() {
if (mouse_captured)
if (mouse_captured) {
return nullptr;
}
mouse_captured = true;
return std::make_unique<CapturedMouseImpl>(
[this] { mouse_captured = false; });
}
void ScreenInteractive::Loop(Component component) {
void ScreenInteractive::Loop(Component component) { // NOLINT
// Suspend previously active screen:
if (g_active_screen) {
std::swap(suspended_screen_, g_active_screen);
@@ -324,7 +338,7 @@ void ScreenInteractive::Loop(Component component) {
// This screen is now active:
g_active_screen = this;
g_active_screen->Install();
g_active_screen->Main(component);
g_active_screen->Main(std::move(component));
g_active_screen->Uninstall();
g_active_screen = nullptr;
@@ -348,7 +362,7 @@ void ScreenInteractive::Loop(Component component) {
/// @brief Decorate a function. It executes the same way, but with the currently
/// active screen terminal hooks temporarilly uninstalled during its execution.
/// @param fn The function to decorate.
Closure ScreenInteractive::WithRestoredIO(Closure fn) {
Closure ScreenInteractive::WithRestoredIO(Closure fn) { // NOLINT
return [this, fn] {
Uninstall();
fn();
@@ -370,10 +384,11 @@ void ScreenInteractive::Install() {
// Install signal handlers to restore the terminal state on exit. The default
// signal handlers are restored on exit.
for (int signal : {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE})
for (int signal : {SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, SIGFPE}) {
install_signal_handler(signal, OnExit);
}
// Save the old terminal configuration and restore it on exit.
// Save the old terminal configuration and restore it on exit.
#if defined(_WIN32)
// Enable VT processing on stdout and stdin
auto stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -405,12 +420,12 @@ void ScreenInteractive::Install() {
SetConsoleMode(stdin_handle, in_mode);
SetConsoleMode(stdout_handle, out_mode);
#else
struct termios terminal;
struct termios terminal; // NOLINT
tcgetattr(STDIN_FILENO, &terminal);
on_exit_functions.push([=] { tcsetattr(STDIN_FILENO, TCSANOW, &terminal); });
terminal.c_lflag &= ~ICANON; // Non canonique terminal.
terminal.c_lflag &= ~ECHO; // Do not print after a key press.
terminal.c_lflag &= ~ICANON; // NOLINT Non canonique terminal.
terminal.c_lflag &= ~ECHO; // NOLINT Do not print after a key press.
terminal.c_cc[VMIN] = 0;
terminal.c_cc[VTIME] = 0;
// auto oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
@@ -420,19 +435,19 @@ void ScreenInteractive::Install() {
tcsetattr(STDIN_FILENO, TCSANOW, &terminal);
// Handle resize.
on_resize = [&] { task_sender_->Send(Event::Special({0})); };
g_on_resize = [&] { task_sender_->Send(Event::Special({0})); };
install_signal_handler(SIGWINCH, OnResize);
// Handle SIGTSTP/SIGCONT.
install_signal_handler(SIGTSTP, OnSigStop);
#endif
auto enable = [&](std::vector<DECMode> parameters) {
auto enable = [&](const std::vector<DECMode>& parameters) {
std::cout << Set(parameters);
on_exit_functions.push([=] { std::cout << Reset(parameters); });
};
auto disable = [&](std::vector<DECMode> parameters) {
auto disable = [&](const std::vector<DECMode>& parameters) {
std::cout << Reset(parameters);
on_exit_functions.push([=] { std::cout << Set(parameters); });
};
@@ -475,6 +490,7 @@ void ScreenInteractive::Uninstall() {
OnExit(0);
}
// NOLINTNEXTLINE
void ScreenInteractive::Main(Component component) {
previous_animation_time = animation::Clock::now();
@@ -493,8 +509,9 @@ void ScreenInteractive::Main(Component component) {
}
Task task;
if (!task_receiver_->Receive(&task))
if (!task_receiver_->Receive(&task)) {
break;
}
// clang-format off
std::visit([&](auto&& arg) {
@@ -527,8 +544,9 @@ void ScreenInteractive::Main(Component component) {
// Handle Animation
if constexpr (std::is_same_v<T, AnimationTask>) {
if (!animation_requested_)
if (!animation_requested_) {
return;
}
animation_requested_ = false;
animation::TimePoint now = animation::Clock::now();
@@ -546,6 +564,7 @@ void ScreenInteractive::Main(Component component) {
}
}
// NOLINTNEXTLINE
void ScreenInteractive::Draw(Component component) {
auto document = component->Render();
int dimx = 0;
@@ -596,13 +615,16 @@ void ScreenInteractive::Draw(Component component) {
// https://github.com/ArthurSonzogni/FTXUI/issues/136
static int i = -3;
++i;
if (!use_alternative_screen_ && (i % 150 == 0))
if (!use_alternative_screen_ && (i % 150 == 0)) { // NOLINT
std::cout << DeviceStatusReport(DSRMode::kCursor);
}
#else
static int i = -3;
++i;
if (!use_alternative_screen_ && (previous_frame_resized_ || i % 40 == 0))
if (!use_alternative_screen_ &&
(previous_frame_resized_ || i % 40 == 0)) { // NOLINT
std::cout << DeviceStatusReport(DSRMode::kCursor);
}
#endif
previous_frame_resized_ = resized;

View File

@@ -18,13 +18,13 @@ template <class T>
class SliderBase : public ComponentBase {
public:
SliderBase(ConstStringRef label, T* value, T min, T max, T increment)
: label_(label),
: label_(std::move(label)),
value_(value),
min_(min),
max_(max),
increment_(increment) {}
Element Render() {
Element Render() override {
auto gauge_color =
Focused() ? color(Color::GrayLight) : color(Color::GrayDark);
float percent = float(*value_ - min_) / float(max_ - min_);
@@ -40,8 +40,9 @@ class SliderBase : public ComponentBase {
}
bool OnEvent(Event event) final {
if (event.is_mouse())
if (event.is_mouse()) {
return OnMouseEvent(event);
}
if (event == Event::ArrowLeft || event == Event::Character('h')) {
*value_ -= increment_;

View File

@@ -14,11 +14,14 @@ TerminalInputParser::TerminalInputParser(Sender<Task> out)
void TerminalInputParser::Timeout(int time) {
timeout_ += time;
if (timeout_ < 50)
const int timeout_threshold = 50;
if (timeout_ < timeout_threshold) {
return;
}
timeout_ = 0;
if (pending_.size())
if (!pending_.empty()) {
Send(SPECIAL);
}
}
void TerminalInputParser::Add(char c) {
@@ -56,21 +59,23 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) {
// key. This also happens with linux with the `bind` command:
// See https://github.com/ArthurSonzogni/FTXUI/issues/337
// Here, we uniformize the new line character to `\n`.
if (pending_ == "\r")
if (pending_ == "\r") {
out_->Send(Event::Special("\n"));
else
} else {
out_->Send(Event::Special(std::move(pending_)));
}
pending_.clear();
return;
case MOUSE:
out_->Send(Event::Mouse(std::move(pending_), output.mouse));
out_->Send(Event::Mouse(std::move(pending_), output.mouse)); // NOLINT
pending_.clear();
return;
case CURSOR_REPORTING:
out_->Send(Event::CursorReporting(std::move(pending_), output.cursor.x,
output.cursor.y));
out_->Send(Event::CursorReporting(std::move(pending_), // NOLINT
output.cursor.x, // NOLINT
output.cursor.y)); // NOLINT
pending_.clear();
return;
}
@@ -78,12 +83,13 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) {
}
TerminalInputParser::Output TerminalInputParser::Parse() {
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
}
switch (Current()) {
case 24: // CAN
case 26: // SUB
case 24: // CAN NOLINT
case 26: // SUB NOLINT
return DROP;
case '\x1B':
@@ -92,11 +98,13 @@ TerminalInputParser::Output TerminalInputParser::Parse() {
break;
}
if (Current() < 32) // C0
if (Current() < 32) { // C0 NOLINT
return SPECIAL;
}
if (Current() == 127) // Delete
if (Current() == 127) { // Delete // NOLINT
return SPECIAL;
}
return ParseUTF8();
}
@@ -118,18 +126,18 @@ TerminalInputParser::Output TerminalInputParser::Parse() {
// Then some sequences are illegal if it exist a shorter representation of the
// same codepoint.
TerminalInputParser::Output TerminalInputParser::ParseUTF8() {
unsigned char head = static_cast<unsigned char>(Current());
unsigned char selector = 0b1000'0000;
auto head = static_cast<unsigned char>(Current());
unsigned char selector = 0b1000'0000; // NOLINT
// The non code-point part of the first byte.
unsigned char mask = selector;
// Find the first zero in the first byte.
int first_zero = 8;
for (int i = 0; i < 8; ++i) {
unsigned int first_zero = 8; // NOLINT
for (unsigned int i = 0; i < 8; ++i) { // NOLINT
mask |= selector;
if (head & selector) {
selector >>= 1;
selector >>= 1U;
continue;
}
first_zero = i;
@@ -137,48 +145,54 @@ TerminalInputParser::Output TerminalInputParser::ParseUTF8() {
}
// Accumulate the value of the first byte.
uint32_t value = head & ~mask;
auto value = uint32_t(head & ~mask); // NOLINT
// Invalid UTF8, with more than 5 bytes.
if (first_zero == 1 || first_zero >= 5)
const unsigned int max_utf8_bytes = 5;
if (first_zero == 1 || first_zero >= max_utf8_bytes) {
return DROP;
}
// Multi byte UTF-8.
for (int i = 2; i <= first_zero; ++i) {
if (!Eat())
for (unsigned int i = 2; i <= first_zero; ++i) {
if (!Eat()) {
return UNCOMPLETED;
}
// Invalid continuation byte.
head = static_cast<unsigned char>(Current());
if ((head & 0b1100'0000) != 0b1000'0000)
if ((head & 0b1100'0000) != 0b1000'0000) { // NOLINT
return DROP;
value <<= 6;
value += head & 0b0011'1111;
}
value <<= 6; // NOLINT
value += head & 0b0011'1111; // NOLINT
}
// Check for overlong UTF8 encoding.
int extra_byte;
if (value <= 0b000'0000'0111'1111) {
extra_byte = 0;
} else if (value <= 0b000'0111'1111'1111) {
extra_byte = 1;
} else if (value <= 0b1111'1111'1111'1111) {
extra_byte = 2;
} else if (value <= 0b1'0000'1111'1111'1111'1111) {
extra_byte = 3;
} else {
int extra_byte = 0;
if (value <= 0b000'0000'0111'1111) { // NOLINT
extra_byte = 0; // NOLINT
} else if (value <= 0b000'0111'1111'1111) { // NOLINT
extra_byte = 1; // NOLINT
} else if (value <= 0b1111'1111'1111'1111) { // NOLINT
extra_byte = 2; // NOLINT
} else if (value <= 0b1'0000'1111'1111'1111'1111) { // NOLINT
extra_byte = 3; // NOLINT
} else { // NOLINT
return DROP;
}
if (extra_byte != position_)
if (extra_byte != position_) {
return DROP;
}
return CHARACTER;
}
TerminalInputParser::Output TerminalInputParser::ParseESC() {
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
}
switch (Current()) {
case 'P':
return ParseDCS();
@@ -187,26 +201,32 @@ TerminalInputParser::Output TerminalInputParser::ParseESC() {
case ']':
return ParseOSC();
default:
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
return SPECIAL;
} else {
return SPECIAL;
}
}
}
TerminalInputParser::Output TerminalInputParser::ParseDCS() {
// Parse until the string terminator ST.
while (1) {
if (!Eat())
while (true) {
if (!Eat()) {
return UNCOMPLETED;
}
if (Current() != '\x1B')
if (Current() != '\x1B') {
continue;
}
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
}
if (Current() != '\\')
if (Current() != '\\') {
continue;
}
return SPECIAL;
}
@@ -217,8 +237,9 @@ TerminalInputParser::Output TerminalInputParser::ParseCSI() {
int argument = 0;
std::vector<int> arguments;
while (true) {
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
}
if (Current() == '<') {
altered = true;
@@ -226,7 +247,7 @@ TerminalInputParser::Output TerminalInputParser::ParseCSI() {
}
if (Current() >= '0' && Current() <= '9') {
argument *= 10;
argument *= 10; // NOLINT
argument += int(Current() - '0');
continue;
}
@@ -239,7 +260,7 @@ TerminalInputParser::Output TerminalInputParser::ParseCSI() {
if (Current() >= ' ' && Current() <= '~' && Current() != '<') {
arguments.push_back(argument);
argument = 0;
argument = 0; // NOLINT
switch (Current()) {
case 'M':
return ParseMouse(altered, true, std::move(arguments));
@@ -253,53 +274,61 @@ TerminalInputParser::Output TerminalInputParser::ParseCSI() {
}
// Invalid ESC in CSI.
if (Current() == '\x1B')
if (Current() == '\x1B') {
return SPECIAL;
}
}
}
TerminalInputParser::Output TerminalInputParser::ParseOSC() {
// Parse until the string terminator ST.
while (true) {
if (!Eat())
if (!Eat()) {
return UNCOMPLETED;
if (Current() != '\x1B')
}
if (Current() != '\x1B') {
continue;
if (!Eat())
}
if (!Eat()) {
return UNCOMPLETED;
if (Current() != '\\')
}
if (Current() != '\\') {
continue;
}
return SPECIAL;
}
}
TerminalInputParser::Output TerminalInputParser::ParseMouse(
TerminalInputParser::Output TerminalInputParser::ParseMouse( // NOLINT
bool altered,
bool pressed,
std::vector<int> arguments) {
if (arguments.size() != 3)
if (arguments.size() != 3) {
return SPECIAL;
}
(void)altered;
Output output(MOUSE);
output.mouse.button = Mouse::Button((arguments[0] & 3) + //
((arguments[0] & 64) >> 4));
output.mouse.motion = Mouse::Motion(pressed);
output.mouse.shift = bool(arguments[0] & 4);
output.mouse.meta = bool(arguments[0] & 8);
output.mouse.x = arguments[1];
output.mouse.y = arguments[2];
output.mouse.button = Mouse::Button((arguments[0] & 3) + // NOLINT
((arguments[0] & 64) >> 4)); // NOLINT
output.mouse.motion = Mouse::Motion(pressed); // NOLINT
output.mouse.shift = bool(arguments[0] & 4); // NOLINT
output.mouse.meta = bool(arguments[0] & 8); // NOLINT
output.mouse.x = arguments[1]; // NOLINT
output.mouse.y = arguments[2]; // NOLINT
return output;
}
// NOLINTNEXTLINE
TerminalInputParser::Output TerminalInputParser::ParseCursorReporting(
std::vector<int> arguments) {
if (arguments.size() != 2)
if (arguments.size() != 2) {
return SPECIAL;
}
Output output(CURSOR_REPORTING);
output.cursor.y = arguments[0];
output.cursor.x = arguments[1];
output.cursor.y = arguments[0]; // NOLINT
output.cursor.x = arguments[1]; // NOLINT
return output;
}

View File

@@ -48,7 +48,7 @@ class TerminalInputParser {
Output(Type t) : type(t) {}
};
void Send(Output type);
void Send(Output output);
Output Parse();
Output ParseUTF8();
Output ParseESC();

View File

@@ -5,21 +5,25 @@
namespace ftxui {
// NOLINTNEXTLINE
Component operator|(Component component, ComponentDecorator decorator) {
return decorator(component);
return decorator(component); // NOLINT
}
// NOLINTNEXTLINE
Component operator|(Component component, ElementDecorator decorator) {
return component | Renderer(decorator);
return component | Renderer(decorator); // NOLINT
}
// NOLINTNEXTLINE
Component& operator|=(Component& component, ComponentDecorator decorator) {
component = component | decorator;
component = component | decorator; // NOLINT
return component;
}
// NOLINTNEXTLINE
Component& operator|=(Component& component, ElementDecorator decorator) {
component = component | decorator;
component = component | decorator; // NOLINT
return component;
}