2 Commits

Author SHA1 Message Date
Miko
9f4b2bcf96 Add string view overloads (#1154)
Some checks failed
Build / Bazel, cl, windows-latest (push) Has been cancelled
Build / Bazel, clang++, macos-latest (push) Has been cancelled
Build / Bazel, clang++, ubuntu-latest (push) Has been cancelled
Build / Bazel, g++, macos-latest (push) Has been cancelled
Build / Bazel, g++, ubuntu-latest (push) Has been cancelled
Build / CMake, cl, windows-latest (push) Has been cancelled
Build / CMake, gcc, ubuntu-latest (push) Has been cancelled
Build / CMake, llvm, ubuntu-latest (push) Has been cancelled
Build / CMake, llvm, macos-latest (push) Has been cancelled
Build / Test modules (llvm, ubuntu-latest) (push) Has been cancelled
Documentation / documentation (push) Has been cancelled
This is better ergonomic, as `std::string_view` is lightweight and accept more conversion than `const std::string&`.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2025-12-13 20:22:11 +01:00
Daisuke Kato
117417e841 fix(bazel): ensure FTXUI is publicly accessible and add external smoke test (#1157)
- Set `visibility = ["//visibility:public"]` on the top-level `:ftxui` alias
  so the library can be consumed from external Bazel workspaces.
- Add `bazel_integration/` minimal external workspace to validate
  external usage via Bzlmod.
- Introduce `smoke` target that depends on `@ftxui//:ftxui`.
- Add CI job to build the smoke target using:
    --enable_bzlmod
    --override_module=ftxui=..
  This prevents regressions in visibility or public API changes.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
2025-12-13 19:49:42 +01:00
41 changed files with 392 additions and 155 deletions

1
.bazelignore Normal file
View File

@@ -0,0 +1 @@
bazel/test/

View File

@@ -1,4 +1,5 @@
common --enable_bzlmod common --enable_bzlmod
common --enable_workspace
build --features=layering_check build --features=layering_check
build --enable_bzlmod build --enable_bzlmod
@@ -6,4 +7,4 @@ build --enable_bzlmod
build --enable_platform_specific_config build --enable_platform_specific_config
build:linux --cxxopt=-std=c++20 build:linux --cxxopt=-std=c++20
build:macos --cxxopt=-std=c++20 build:macos --cxxopt=-std=c++20
build:windows --cxxopt=-std:c++20 build:windows --cxxopt=/std:c++20

View File

@@ -56,6 +56,13 @@ jobs:
CXX: ${{ matrix.cxx }} CXX: ${{ matrix.cxx }}
run: bazel test --test_output=all ... run: bazel test --test_output=all ...
- name: "Bazel Smoke test"
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: bazel build //... --enable_bzlmod --override_module=ftxui=../..
working-directory: bazel/test
test_cmake: test_cmake:
name: "CMake, ${{ matrix.compiler }}, ${{ matrix.os }}" name: "CMake, ${{ matrix.compiler }}, ${{ matrix.os }}"
strategy: strategy:

5
.gitignore vendored
View File

@@ -24,6 +24,7 @@ out/
!BUILD.bazel !BUILD.bazel
!MODULE.bazel !MODULE.bazel
!.bazelrc !.bazelrc
!.bazelignore
# .github directory: # .github directory:
!.github/**/*.yaml !.github/**/*.yaml
@@ -37,6 +38,10 @@ out/
# bazel directory: # bazel directory:
!bazel/**/*.bzl !bazel/**/*.bzl
!.bcr/* !.bcr/*
!bazel/test/*.bazel
!bazel/test/*.bazelrc
!bazel/test/*.cpp
!bazel/test/*.md
# doc directory: # doc directory:
!doc/**/Doxyfile.in !doc/**/Doxyfile.in

View File

@@ -15,13 +15,16 @@ load(":bazel/ftxui.bzl", "generate_examples")
load(":bazel/ftxui.bzl", "windows_copts") load(":bazel/ftxui.bzl", "windows_copts")
# A meta target depending on all of the ftxui submodules. # A meta target depending on all of the ftxui submodules.
# Note that component depends on dom and screen, so ftxui is just an alias for # Note that component depends on dom and screen, so ftxui re-exports all headers.
# component.
# ┌component──┐ # ┌component──┐
# │┌dom──────┐│ # │┌dom──────┐│
# ││┌screen─┐││ # ││┌screen─┐││
# └┴┴───────┴┴┘ # └┴┴───────┴┴┘
alias(name = "ftxui", actual = ":component") ftxui_cc_library(
name = "ftxui",
hdrs = glob(["include/ftxui/**/*.hpp"]),
deps = [":component"],
)
# @ftxui:screen is a module that provides a screen buffer and color management # @ftxui:screen is a module that provides a screen buffer and color management
# for terminal applications. A screen is a 2D array of cells, each cell can # for terminal applications. A screen is a 2D array of cells, each cell can

View File

@@ -25,6 +25,12 @@ Next
``` ```
Thanks @mikomikotaishi for PR #1015. Thanks @mikomikotaishi for PR #1015.
- Remove dependency on 'pthread'. - Remove dependency on 'pthread'.
- Bugfix: Bazel target @ftxui is now visible. Thanks @dskkato in #1157.
### General
- Breaking. Move to `std::string_view` instead of `const std::string&` where
applicable. This yields better interoperability with string literals and
avoids unnecessary copies. Thanks @mikomikotaishi for PR #1154
### Component ### Component
- Feature: POSIX Piped Input Handling. - Feature: POSIX Piped Input Handling.

View File

@@ -425,9 +425,13 @@ cc_binary(
name = "your_target", name = "your_target",
srcs = ["your_source.cc"], srcs = ["your_source.cc"],
deps = [ deps = [
# Choose submodules
"@ftxui//:component", "@ftxui//:component",
"@ftxui//:dom", "@ftxui//:dom",
"@ftxui//:screen", "@ftxui//:screen",
# Or use the single ftxui target (includes all modules)
# "@ftxui//:ftxui",
], ],
) )
``` ```

1
bazel/test/.bazelrc Symbolic link
View File

@@ -0,0 +1 @@
../../.bazelrc

23
bazel/test/BUILD.bazel Normal file
View File

@@ -0,0 +1,23 @@
# Copyright 2025 Arthur Sonzogni. All rights reserved.
# Use of this source code is governed by the MIT license that can be found in
# the LICENSE file.
# Test using individual submodules
cc_binary(
name = "smoke",
srcs = ["smoke.cpp"],
deps = [
"@ftxui//:component",
"@ftxui//:dom",
"@ftxui//:screen",
],
)
# Test using the single ftxui target
cc_binary(
name = "smoke_single_dependency",
srcs = ["smoke.cpp"],
deps = [
"@ftxui",
],
)

9
bazel/test/MODULE.bazel Normal file
View File

@@ -0,0 +1,9 @@
# Copyright 2025 Arthur Sonzogni. All rights reserved.
# Use of this source code is governed by the MIT license that can be found in
# the LICENSE file.
module(
name = "ftxui_integration_test",
version = "0.0.1",
)
bazel_dep(name = "ftxui", version = "6.1.9")

38
bazel/test/README.md Normal file
View File

@@ -0,0 +1,38 @@
# FTXUI Bazel Integration Test
This directory contains integration tests to verify that FTXUI can be properly consumed as an external dependency using Bazel with Bzlmod.
## Purpose
These tests ensure that:
- FTXUI's public API is correctly exposed to external projects
- Both single-target (`@ftxui//:ftxui`) and submodule-based dependencies work correctly
- Headers are properly re-exported and accessible from downstream projects
## Build Instructions
To build all targets:
```bash
bazel build //... --enable_bzlmod --override_module=ftxui=../..
```
To build individual targets:
```bash
# Test using individual submodules
bazel build //:smoke --enable_bzlmod --override_module=ftxui=../..
# Test using the single ftxui target
bazel build //:smoke_single_dependency --enable_bzlmod --override_module=ftxui=../..
```
## Run the Examples
```bash
# Run the submodules version
./bazel-bin/smoke
# Run the single-target version
./bazel-bin/smoke_single_dependency
```

View File

@@ -0,0 +1,4 @@
# Copyright 2025 Arthur Sonzogni. All rights reserved.
# Use of this source code is governed by the MIT license that can be found in
# the LICENSE file.
workspace(name = "ftxui_smoke_test")

16
bazel/test/smoke.cpp Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2025 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <ftxui/component/component.hpp>
#include <ftxui/component/screen_interactive.hpp>
int main() {
using namespace ftxui;
auto screen = ScreenInteractive::TerminalOutput();
auto component = Button("Quit", screen.ExitLoopClosure());
screen.Loop(component);
return 0;
}

View File

@@ -6,6 +6,7 @@
#include <ftxui/component/mouse.hpp> // for Mouse #include <ftxui/component/mouse.hpp> // for Mouse
#include <string> // for string, operator== #include <string> // for string, operator==
#include <string_view>
namespace ftxui { namespace ftxui {
@@ -28,13 +29,13 @@ class ComponentBase;
/// @ingroup component /// @ingroup component
struct Event { struct Event {
// --- Constructor section --------------------------------------------------- // --- Constructor section ---------------------------------------------------
static Event Character(std::string); static Event Character(std::string_view);
static Event Character(char); static Event Character(char);
static Event Character(wchar_t); static Event Character(wchar_t);
static Event Special(std::string); static Event Special(std::string_view);
static Event Mouse(std::string, Mouse mouse); static Event Mouse(std::string_view, Mouse mouse);
static Event CursorPosition(std::string, int x, int y); // Internal static Event CursorPosition(std::string_view, int x, int y); // Internal
static Event CursorShape(std::string, int shape); // Internal static Event CursorShape(std::string_view, int shape); // Internal
// --- Arrow --- // --- Arrow ---
static const Event ArrowLeft; static const Event ArrowLeft;

View File

@@ -106,9 +106,9 @@ struct Canvas {
// Draw using character of size 2x4 at position (x,y) // Draw using character of size 2x4 at position (x,y)
// x is considered to be a multiple of 2. // x is considered to be a multiple of 2.
// y is considered to be a multiple of 4. // y is considered to be a multiple of 4.
void DrawText(int x, int y, const std::string& value); void DrawText(int x, int y, std::string_view value);
void DrawText(int x, int y, const std::string& value, const Color& color); void DrawText(int x, int y, std::string_view value, const Color& color);
void DrawText(int x, int y, const std::string& value, const Stylizer& style); void DrawText(int x, int y, std::string_view value, const Stylizer& style);
// Draw using directly pixels or images -------------------------------------- // Draw using directly pixels or images --------------------------------------
// x is considered to be a multiple of 2. // x is considered to be a multiple of 2.

View File

@@ -7,6 +7,7 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string_view>
#include "ftxui/dom/canvas.hpp" #include "ftxui/dom/canvas.hpp"
#include "ftxui/dom/direction.hpp" #include "ftxui/dom/direction.hpp"
#include "ftxui/dom/flexbox_config.hpp" #include "ftxui/dom/flexbox_config.hpp"
@@ -51,8 +52,8 @@ Elements operator|(Elements, Decorator);
Decorator operator|(Decorator, Decorator); Decorator operator|(Decorator, Decorator);
// --- Widget --- // --- Widget ---
Element text(std::string text); Element text(std::string_view text);
Element vtext(std::string text); Element vtext(std::string_view text);
Element separator(); Element separator();
Element separatorLight(); Element separatorLight();
Element separatorDashed(); Element separatorDashed();
@@ -61,7 +62,7 @@ Element separatorDouble();
Element separatorEmpty(); Element separatorEmpty();
Element separatorStyled(BorderStyle); Element separatorStyled(BorderStyle);
Element separator(Pixel); Element separator(Pixel);
Element separatorCharacter(std::string); Element separatorCharacter(std::string_view);
Element separatorHSelector(float left, Element separatorHSelector(float left,
float right, float right,
Color unselected_color, Color unselected_color,
@@ -89,11 +90,11 @@ Decorator borderStyled(Color);
Decorator borderWith(const Pixel&); Decorator borderWith(const Pixel&);
Element window(Element title, Element content, BorderStyle border = ROUNDED); Element window(Element title, Element content, BorderStyle border = ROUNDED);
Element spinner(int charset_index, size_t image_index); Element spinner(int charset_index, size_t image_index);
Element paragraph(const std::string& text); Element paragraph(std::string_view text);
Element paragraphAlignLeft(const std::string& text); Element paragraphAlignLeft(std::string_view text);
Element paragraphAlignRight(const std::string& text); Element paragraphAlignRight(std::string_view text);
Element paragraphAlignCenter(const std::string& text); Element paragraphAlignCenter(std::string_view text);
Element paragraphAlignJustify(const std::string& text); Element paragraphAlignJustify(std::string_view text);
Element graph(GraphFunction); Element graph(GraphFunction);
Element emptyElement(); Element emptyElement();
Element canvas(ConstRef<Canvas>); Element canvas(ConstRef<Canvas>);
@@ -120,8 +121,8 @@ Element bgcolor(const LinearGradient&, Element);
Decorator focusPosition(int x, int y); Decorator focusPosition(int x, int y);
Decorator focusPositionRelative(float x, float y); Decorator focusPositionRelative(float x, float y);
Element automerge(Element child); Element automerge(Element child);
Decorator hyperlink(std::string link); Decorator hyperlink(std::string_view link);
Element hyperlink(std::string link, Element child); Element hyperlink(std::string_view link, Element child);
Element selectionStyleReset(Element); Element selectionStyleReset(Element);
Decorator selectionColor(Color foreground); Decorator selectionColor(Color foreground);
Decorator selectionBackgroundColor(Color foreground); Decorator selectionBackgroundColor(Color foreground);

View File

@@ -30,7 +30,7 @@ class Selection {
Selection SaturateVertical(Box box); Selection SaturateVertical(Box box);
bool IsEmpty() const { return empty_; } bool IsEmpty() const { return empty_; }
void AddPart(const std::string& part, int y, int left, int right); void AddPart(std::string_view part, int y, int left, int right);
std::string GetParts() { return parts_.str(); } std::string GetParts() { return parts_.str(); }
private: private:

View File

@@ -68,7 +68,7 @@ class Screen : public Image {
// Store an hyperlink in the screen. Return the id of the hyperlink. The id is // Store an hyperlink in the screen. Return the id of the hyperlink. The id is
// used to identify the hyperlink when the user click on it. // used to identify the hyperlink when the user click on it.
uint8_t RegisterHyperlink(const std::string& link); uint8_t RegisterHyperlink(std::string_view link);
const std::string& Hyperlink(uint8_t id) const; const std::string& Hyperlink(uint8_t id) const;
using SelectionStyle = std::function<void(Pixel&)>; using SelectionStyle = std::function<void(Pixel&)>;

View File

@@ -4,27 +4,32 @@
#ifndef FTXUI_SCREEN_STRING_HPP #ifndef FTXUI_SCREEN_STRING_HPP
#define FTXUI_SCREEN_STRING_HPP #define FTXUI_SCREEN_STRING_HPP
#include <string> // for string, wstring, to_string #include <string> // for string, wstring, to_string
#include <vector> // for vector #include <string_view> // for string_view
#include <vector> // for vector
namespace ftxui { namespace ftxui {
std::string to_string(const std::wstring& s); std::string to_string(std::wstring_view s);
std::wstring to_wstring(const std::string& s); std::wstring to_wstring(std::string_view s);
template <typename T> template <typename T>
std::wstring to_wstring(T s) { std::wstring to_wstring(T s) {
return to_wstring(std::to_string(s)); return to_wstring(std::string_view(std::to_string(s)));
}
template <>
inline std::wstring to_wstring(const char* s) {
return to_wstring(std::string_view(s));
} }
int string_width(const std::string&); int string_width(std::string_view);
// Split the string into a its glyphs. An empty one is inserted ater fullwidth // Split the string into a its glyphs. An empty one is inserted ater fullwidth
// ones. // ones.
std::vector<std::string> Utf8ToGlyphs(const std::string& input); std::vector<std::string> Utf8ToGlyphs(std::string_view input);
// Map every cells drawn by |input| to their corresponding Glyphs. Half-size // Map every cells drawn by |input| to their corresponding Glyphs. Half-size
// Glyphs takes one cell, full-size Glyphs take two cells. // Glyphs takes one cell, full-size Glyphs take two cells.
std::vector<int> CellToGlyphIndex(const std::string& input); std::vector<int> CellToGlyphIndex(std::string_view input);
} // namespace ftxui } // namespace ftxui

View File

@@ -7,6 +7,7 @@
#include <ftxui/screen/string.hpp> #include <ftxui/screen/string.hpp>
#include <memory> #include <memory>
#include <string> #include <string>
#include <string_view>
#include <variant> #include <variant>
#include <vector> #include <vector>
@@ -125,13 +126,15 @@ class ConstStringListRef {
Adapter& operator=(Adapter&&) = default; Adapter& operator=(Adapter&&) = default;
virtual ~Adapter() = default; virtual ~Adapter() = default;
virtual size_t size() const = 0; virtual size_t size() const = 0;
virtual std::string operator[](size_t i) const = 0; virtual std::string_view operator[](size_t i) const = 0;
}; };
using Variant = std::variant<const std::vector<std::string>, // using Variant = std::variant<const std::vector<std::string>, //
const std::vector<std::string>*, // const std::vector<std::string>*, //
const std::vector<std::wstring>*, // const std::vector<std::string_view>, //
Adapter*, // const std::vector<std::string_view>*, //
std::unique_ptr<Adapter> // const std::vector<std::wstring>*, //
Adapter*, //
std::unique_ptr<Adapter> //
>; >;
ConstStringListRef() = default; ConstStringListRef() = default;
@@ -149,6 +152,14 @@ class ConstStringListRef {
{ {
variant_ = std::make_shared<Variant>(value); variant_ = std::make_shared<Variant>(value);
} }
ConstStringListRef(std::vector<std::string_view> value) // NOLINT
{
variant_ = std::make_shared<Variant>(value);
}
ConstStringListRef(const std::vector<std::string_view>* value) // NOLINT
{
variant_ = std::make_shared<Variant>(value);
}
ConstStringListRef(const std::vector<std::wstring>* value) // NOLINT ConstStringListRef(const std::vector<std::wstring>* value) // NOLINT
{ {
variant_ = std::make_shared<Variant>(value); variant_ = std::make_shared<Variant>(value);
@@ -169,7 +180,62 @@ class ConstStringListRef {
} }
std::string operator[](size_t i) const { std::string operator[](size_t i) const {
return variant_ ? std::visit(IndexedGetter(i), *variant_) : ""; if (!variant_) {
return "";
}
auto& v = *variant_;
if (std::holds_alternative<const std::vector<std::string>>(v)) {
return std::get<const std::vector<std::string>>(v)[i];
}
if (std::holds_alternative<const std::vector<std::string>*>(v)) {
return (*std::get<const std::vector<std::string>*>(v))[i];
}
if (std::holds_alternative<const std::vector<std::string_view>>(v)) {
return std::string(std::get<const std::vector<std::string_view>>(v)[i]);
}
if (std::holds_alternative<const std::vector<std::string_view>*>(v)) {
return std::string(
(*std::get<const std::vector<std::string_view>*>(v))[i]);
}
if (std::holds_alternative<const std::vector<std::wstring>*>(v)) {
return to_string((*std::get<const std::vector<std::wstring>*>(v))[i]);
}
if (std::holds_alternative<Adapter*>(v)) {
return std::string((*std::get<Adapter*>(v))[i]);
}
if (std::holds_alternative<std::unique_ptr<Adapter>>(v)) {
return std::string((*std::get<std::unique_ptr<Adapter>>(v))[i]);
}
return "";
}
std::string_view at(size_t i) const {
if (!variant_) {
return "";
}
auto& v = *variant_;
if (std::holds_alternative<const std::vector<std::string>>(v)) {
return std::get<const std::vector<std::string>>(v)[i];
}
if (std::holds_alternative<const std::vector<std::string>*>(v)) {
return (*std::get<const std::vector<std::string>*>(v))[i];
}
if (std::holds_alternative<const std::vector<std::string_view>>(v)) {
return std::get<const std::vector<std::string_view>>(v)[i];
}
if (std::holds_alternative<const std::vector<std::string_view>*>(v)) {
return (*std::get<const std::vector<std::string_view>*>(v))[i];
}
if (std::holds_alternative<const std::vector<std::wstring>*>(v)) {
return {};
}
if (std::holds_alternative<Adapter*>(v)) {
return (*std::get<Adapter*>(v))[i];
}
if (std::holds_alternative<std::unique_ptr<Adapter>>(v)) {
return (*std::get<std::unique_ptr<Adapter>>(v))[i];
}
return {};
} }
private: private:
@@ -180,6 +246,12 @@ class ConstStringListRef {
size_t operator()(const std::vector<std::string>* v) const { size_t operator()(const std::vector<std::string>* v) const {
return v->size(); return v->size();
} }
size_t operator()(const std::vector<std::string_view>& v) const {
return v.size();
}
size_t operator()(const std::vector<std::string_view>* v) const {
return v->size();
}
size_t operator()(const std::vector<std::wstring>* v) const { size_t operator()(const std::vector<std::wstring>* v) const {
return v->size(); return v->size();
} }
@@ -189,25 +261,6 @@ class ConstStringListRef {
} }
}; };
struct IndexedGetter {
IndexedGetter(size_t index) // NOLINT
: index_(index) {}
size_t index_;
std::string operator()(const std::vector<std::string>& v) const {
return v[index_];
}
std::string operator()(const std::vector<std::string>* v) const {
return (*v)[index_];
}
std::string operator()(const std::vector<std::wstring>* v) const {
return to_string((*v)[index_]);
}
std::string operator()(const Adapter* v) const { return (*v)[index_]; }
std::string operator()(const std::unique_ptr<Adapter>& v) const {
return (*v)[index_];
}
};
std::shared_ptr<Variant> variant_; std::shared_ptr<Variant> variant_;
}; };

View File

@@ -48,7 +48,7 @@ class ButtonBase : public ComponentBase, public ButtonOption {
} }
const EntryState state{ const EntryState state{
*label, false, active, focused_or_hover, Index(), std::string(*label), false, active, focused_or_hover, Index(),
}; };
auto element = (transform ? transform : DefaultTransform) // auto element = (transform ? transform : DefaultTransform) //

View File

@@ -27,7 +27,7 @@ class CheckboxBase : public ComponentBase, public CheckboxOption {
const bool is_focused = Focused(); const bool is_focused = Focused();
const bool is_active = Active(); const bool is_active = Active();
auto entry_state = EntryState{ auto entry_state = EntryState{
*label, *checked, is_active, is_focused || hovered_, -1, std::string(*label), *checked, is_active, is_focused || hovered_, -1,
}; };
auto element = (transform ? transform : CheckboxOption::Simple().transform)( auto element = (transform ? transform : CheckboxOption::Simple().transform)(
entry_state); entry_state);

View File

@@ -25,9 +25,9 @@ namespace ftxui {
/// @brief An event corresponding to a given typed character. /// @brief An event corresponding to a given typed character.
/// @param input The character typed by the user. /// @param input The character typed by the user.
// static // static
Event Event::Character(std::string input) { Event Event::Character(std::string_view input) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::string(input);
event.type_ = Type::Character; event.type_ = Type::Character;
return event; return event;
} }
@@ -50,9 +50,9 @@ Event Event::Character(wchar_t c) {
/// @param input The sequence of character send by the terminal. /// @param input The sequence of character send by the terminal.
/// @param mouse The mouse state. /// @param mouse The mouse state.
// static // static
Event Event::Mouse(std::string input, struct Mouse mouse) { Event Event::Mouse(std::string_view input, struct Mouse mouse) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::string(input);
event.type_ = Type::Mouse; event.type_ = Type::Mouse;
event.data_.mouse = mouse; // NOLINT event.data_.mouse = mouse; // NOLINT
return event; return event;
@@ -60,9 +60,9 @@ Event Event::Mouse(std::string input, struct Mouse mouse) {
/// @brief An event corresponding to a terminal DCS (Device Control String). /// @brief An event corresponding to a terminal DCS (Device Control String).
// static // static
Event Event::CursorShape(std::string input, int shape) { Event Event::CursorShape(std::string_view input, int shape) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::string(input);
event.type_ = Type::CursorShape; event.type_ = Type::CursorShape;
event.data_.cursor_shape = shape; // NOLINT event.data_.cursor_shape = shape; // NOLINT
return event; return event;
@@ -71,17 +71,17 @@ Event Event::CursorShape(std::string input, int shape) {
/// @brief An custom event whose meaning is defined by the user of the library. /// @brief An custom event whose meaning is defined by the user of the library.
/// @param input An arbitrary sequence of character defined by the developer. /// @param input An arbitrary sequence of character defined by the developer.
// static // static
Event Event::Special(std::string input) { Event Event::Special(std::string_view input) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::string(input);
return event; return event;
} }
/// @internal /// @internal
// static // static
Event Event::CursorPosition(std::string input, int x, int y) { Event Event::CursorPosition(std::string_view input, int x, int y) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::string(input);
event.type_ = Type::CursorPosition; event.type_ = Type::CursorPosition;
event.data_.cursor = {x, y}; // NOLINT event.data_.cursor = {x, y}; // NOLINT
return event; return event;
@@ -292,12 +292,12 @@ const Event Event::ArrowLeftCtrl = Event::Special("\x1B[1;5D");
const Event Event::ArrowRightCtrl = Event::Special("\x1B[1;5C"); const Event Event::ArrowRightCtrl = Event::Special("\x1B[1;5C");
const Event Event::ArrowUpCtrl = Event::Special("\x1B[1;5A"); const Event Event::ArrowUpCtrl = Event::Special("\x1B[1;5A");
const Event Event::ArrowDownCtrl = Event::Special("\x1B[1;5B"); const Event Event::ArrowDownCtrl = Event::Special("\x1B[1;5B");
const Event Event::Backspace = Event::Special({127}); const Event Event::Backspace = Event::Special(std::string({127}));
const Event Event::Delete = Event::Special("\x1B[3~"); const Event Event::Delete = Event::Special("\x1B[3~");
const Event Event::Escape = Event::Special("\x1B"); const Event Event::Escape = Event::Special("\x1B");
const Event Event::Return = Event::Special({10}); const Event Event::Return = Event::Special(std::string({10}));
const Event Event::Tab = Event::Special({9}); const Event Event::Tab = Event::Special(std::string({9}));
const Event Event::TabReverse = Event::Special({27, 91, 90}); const Event Event::TabReverse = Event::Special(std::string({27, 91, 90}));
// See https://invisible-island.net/xterm/xterm-function-keys.html // See https://invisible-island.net/xterm/xterm-function-keys.html
// We follow xterm-new / vterm-xf86-v4 / mgt / screen // We follow xterm-new / vterm-xf86-v4 / mgt / screen
@@ -315,11 +315,11 @@ const Event Event::F11 = Event::Special("\x1B[23~");
const Event Event::F12 = Event::Special("\x1B[24~"); const Event Event::F12 = Event::Special("\x1B[24~");
const Event Event::Insert = Event::Special("\x1B[2~"); const Event Event::Insert = Event::Special("\x1B[2~");
const Event Event::Home = Event::Special({27, 91, 72}); const Event Event::Home = Event::Special(std::string({27, 91, 72}));
const Event Event::End = Event::Special({27, 91, 70}); const Event Event::End = Event::Special(std::string({27, 91, 70}));
const Event Event::PageUp = Event::Special({27, 91, 53, 126}); const Event Event::PageUp = Event::Special(std::string({27, 91, 53, 126}));
const Event Event::PageDown = Event::Special({27, 91, 54, 126}); const Event Event::PageDown = Event::Special(std::string({27, 91, 54, 126}));
const Event Event::Custom = Event::Special({0}); const Event Event::Custom = Event::Special(std::string({0}));
const Event Event::a = Event::Character("a"); const Event Event::a = Event::Character("a");
const Event Event::b = Event::Character("b"); const Event Event::b = Event::Character("b");

View File

@@ -144,9 +144,8 @@ class MenuBase : public ComponentBase, public MenuOption {
std::reverse(elements.begin(), elements.end()); std::reverse(elements.begin(), elements.end());
} }
const Element bar = IsHorizontal() const Element bar =
? hbox(std::move(elements)) IsHorizontal() ? hbox(std::move(elements)) : vbox(std::move(elements));
: vbox(std::move(elements));
if (!underline.enabled) { if (!underline.enabled) {
return bar | reflect(box_); return bar | reflect(box_);
@@ -623,7 +622,7 @@ Component MenuEntry(MenuEntryOption option) {
UpdateAnimationTarget(); UpdateAnimationTarget();
const EntryState state{ const EntryState state{
label(), false, hovered_, is_focused, Index(), std::string(label()), false, hovered_, is_focused, Index(),
}; };
Element element = (transform ? transform : DefaultOptionTransform) // Element element = (transform ? transform : DefaultOptionTransform) //

View File

@@ -1054,7 +1054,7 @@ void ScreenInteractive::Signal(int signal) {
} }
if (signal == SIGWINCH) { if (signal == SIGWINCH) {
Post(Event::Special({0})); Post(Event::Special(std::string({0})));
return; return;
} }
#endif #endif

View File

@@ -21,8 +21,8 @@ class TaskRunner {
auto PostTask(Task task) -> void; auto PostTask(Task task) -> void;
/// Schedules a task to be executed after a certain duration. /// Schedules a task to be executed after a certain duration.
auto PostDelayedTask(Task task, auto PostDelayedTask(Task task, std::chrono::steady_clock::duration duration)
std::chrono::steady_clock::duration duration) -> void; -> void;
/// Runs the tasks in the queue, return the delay until the next delayed task /// Runs the tasks in the queue, return the delay until the next delayed task
/// can be executed. /// can be executed.

View File

@@ -338,7 +338,7 @@ TEST(Event, Control) {
EXPECT_TRUE(received_events.empty()); EXPECT_TRUE(received_events.empty());
} else { } else {
EXPECT_EQ(1, received_events.size()); EXPECT_EQ(1, received_events.size());
EXPECT_EQ(received_events[0], Event::Special({test.input})); EXPECT_EQ(received_events[0], Event::Special(std::string({test.input})));
} }
} }
} }

View File

@@ -782,7 +782,7 @@ void Canvas::DrawBlockEllipseFilled(int x1,
/// @param x the x coordinate of the text. /// @param x the x coordinate of the text.
/// @param y the y coordinate of the text. /// @param y the y coordinate of the text.
/// @param value the text to draw. /// @param value the text to draw.
void Canvas::DrawText(int x, int y, const std::string& value) { void Canvas::DrawText(int x, int y, std::string_view value) {
DrawText(x, y, value, nostyle); DrawText(x, y, value, nostyle);
} }
@@ -793,7 +793,7 @@ void Canvas::DrawText(int x, int y, const std::string& value) {
/// @param color the color of the text. /// @param color the color of the text.
void Canvas::DrawText(int x, void Canvas::DrawText(int x,
int y, int y,
const std::string& value, std::string_view value,
const Color& color) { const Color& color) {
DrawText(x, y, value, [color](Pixel& p) { p.foreground_color = color; }); DrawText(x, y, value, [color](Pixel& p) { p.foreground_color = color; });
} }
@@ -805,7 +805,7 @@ void Canvas::DrawText(int x,
/// @param style the style of the text. /// @param style the style of the text.
void Canvas::DrawText(int x, void Canvas::DrawText(int x,
int y, int y,
const std::string& value, std::string_view value,
const Stylizer& style) { const Stylizer& style) {
for (const auto& it : Utf8ToGlyphs(value)) { for (const auto& it : Utf8ToGlyphs(value)) {
if (!IsIn(x, y)) { if (!IsIn(x, y)) {

View File

@@ -2,8 +2,8 @@
// Use of this source code is governed by the MIT license that can be found in // Use of this source code is governed by the MIT license that can be found in
// the LICENSE file. // the LICENSE file.
#include <gtest/gtest.h> // for Test, TestInfo (ptr only), EXPECT_EQ, Message, TEST, TestPartResult #include <gtest/gtest.h> // for Test, TestInfo (ptr only), EXPECT_EQ, Message, TEST, TestPartResult
#include <array> // for array #include <array> // for array
#include <cstddef> // for size_t #include <cstddef> // for size_t
#include <queue> #include <queue>
#include <stack> // for stack #include <stack> // for stack
#include <string> // for allocator, basic_string, string #include <string> // for allocator, basic_string, string

View File

@@ -48,8 +48,8 @@ class Hyperlink : public NodeDecorator {
/// Element document = /// Element document =
/// hyperlink("https://github.com/ArthurSonzogni/FTXUI", "link"); /// hyperlink("https://github.com/ArthurSonzogni/FTXUI", "link");
/// ``` /// ```
Element hyperlink(std::string link, Element child) { Element hyperlink(std::string_view link, Element child) {
return std::make_shared<Hyperlink>(std::move(child), std::move(link)); return std::make_shared<Hyperlink>(std::move(child), std::string(link));
} }
/// @brief Decorate using a hyperlink. /// @brief Decorate using a hyperlink.
@@ -67,8 +67,10 @@ Element hyperlink(std::string link, Element child) {
/// text("red") | hyperlink("https://github.com/Arthursonzogni/FTXUI"); /// text("red") | hyperlink("https://github.com/Arthursonzogni/FTXUI");
/// ``` /// ```
// NOLINTNEXTLINE // NOLINTNEXTLINE
Decorator hyperlink(std::string link) { Decorator hyperlink(std::string_view link) {
return [link](Element child) { return hyperlink(link, std::move(child)); }; return [link = std::string(link)](Element child) {
return hyperlink(link, std::move(child));
};
} }
} // namespace ftxui } // namespace ftxui

View File

@@ -38,7 +38,7 @@ Element Split(const std::string& paragraph,
/// @brief Return an element drawing the paragraph on multiple lines. /// @brief Return an element drawing the paragraph on multiple lines.
/// @ingroup dom /// @ingroup dom
/// @see flexbox. /// @see flexbox.
Element paragraph(const std::string& the_text) { Element paragraph(std::string_view the_text) {
return paragraphAlignLeft(the_text); return paragraphAlignLeft(the_text);
} }
@@ -46,8 +46,8 @@ Element paragraph(const std::string& the_text) {
/// the left. /// the left.
/// @ingroup dom /// @ingroup dom
/// @see flexbox. /// @see flexbox.
Element paragraphAlignLeft(const std::string& the_text) { Element paragraphAlignLeft(std::string_view the_text) {
return Split(the_text, [](const std::string& line) { return Split(std::string(the_text), [](const std::string& line) {
static const auto config = FlexboxConfig().SetGap(1, 0); static const auto config = FlexboxConfig().SetGap(1, 0);
return flexbox(Split(line), config); return flexbox(Split(line), config);
}); });
@@ -57,8 +57,8 @@ Element paragraphAlignLeft(const std::string& the_text) {
/// the right. /// the right.
/// @ingroup dom /// @ingroup dom
/// @see flexbox. /// @see flexbox.
Element paragraphAlignRight(const std::string& the_text) { Element paragraphAlignRight(std::string_view the_text) {
return Split(the_text, [](const std::string& line) { return Split(std::string(the_text), [](const std::string& line) {
static const auto config = FlexboxConfig().SetGap(1, 0).Set( static const auto config = FlexboxConfig().SetGap(1, 0).Set(
FlexboxConfig::JustifyContent::FlexEnd); FlexboxConfig::JustifyContent::FlexEnd);
return flexbox(Split(line), config); return flexbox(Split(line), config);
@@ -69,8 +69,8 @@ Element paragraphAlignRight(const std::string& the_text) {
/// the center. /// the center.
/// @ingroup dom /// @ingroup dom
/// @see flexbox. /// @see flexbox.
Element paragraphAlignCenter(const std::string& the_text) { Element paragraphAlignCenter(std::string_view the_text) {
return Split(the_text, [](const std::string& line) { return Split(std::string(the_text), [](const std::string& line) {
static const auto config = static const auto config =
FlexboxConfig().SetGap(1, 0).Set(FlexboxConfig::JustifyContent::Center); FlexboxConfig().SetGap(1, 0).Set(FlexboxConfig::JustifyContent::Center);
return flexbox(Split(line), config); return flexbox(Split(line), config);
@@ -82,8 +82,8 @@ Element paragraphAlignCenter(const std::string& the_text) {
/// the center. /// the center.
/// @ingroup dom /// @ingroup dom
/// @see flexbox. /// @see flexbox.
Element paragraphAlignJustify(const std::string& the_text) { Element paragraphAlignJustify(std::string_view the_text) {
return Split(the_text, [](const std::string& line) { return Split(std::string(the_text), [](const std::string& line) {
static const auto config = FlexboxConfig().SetGap(1, 0).Set( static const auto config = FlexboxConfig().SetGap(1, 0).Set(
FlexboxConfig::JustifyContent::SpaceBetween); FlexboxConfig::JustifyContent::SpaceBetween);
Elements words = Split(line); Elements words = Split(line);

View File

@@ -143,7 +143,7 @@ Selection Selection::SaturateVertical(Box box) {
return {start_x, start_y, end_x, end_y, parent_}; return {start_x, start_y, end_x, end_y, parent_};
} }
void Selection::AddPart(const std::string& part, int y, int left, int right) { void Selection::AddPart(std::string_view part, int y, int left, int right) {
if (parent_ != this) { if (parent_ != this) {
parent_->AddPart(part, y, left, right); parent_->AddPart(part, y, left, right);
return; return;

View File

@@ -392,8 +392,8 @@ Element separatorEmpty() {
/// ──── /// ────
/// down /// down
/// ``` /// ```
Element separatorCharacter(std::string value) { Element separatorCharacter(std::string_view value) {
return std::make_shared<Separator>(std::move(value)); return std::make_shared<Separator>(std::string(value));
} }
/// @brief Draw a separator in between two element filled with a given pixel. /// @brief Draw a separator in between two element filled with a given pixel.

View File

@@ -25,12 +25,12 @@ TEST(TableTest, Empty) {
} }
TEST(TableTest, Basic) { TEST(TableTest, Basic) {
auto table = Table({ auto table = Table(std::initializer_list<std::vector<std::string>>({
{"a", "b", "c", "d"}, {"a", "b", "c", "d"},
{"e", "f", "g", "h"}, {"e", "f", "g", "h"},
{"i", "j", "k", "l"}, {"i", "j", "k", "l"},
{"m", "n", "o", "p"}, {"m", "n", "o", "p"},
}); }));
Screen screen(10, 10); Screen screen(10, 10);
Render(screen, table.Render()); Render(screen, table.Render());
EXPECT_EQ( EXPECT_EQ(

View File

@@ -4,8 +4,9 @@
#include <algorithm> // for min #include <algorithm> // for min
#include <memory> // for make_shared #include <memory> // for make_shared
#include <sstream> #include <sstream>
#include <string> // for string, wstring #include <string> // for string, wstring
#include <utility> // for move #include <string_view> // for string_view
#include <utility> // for move
#include "ftxui/dom/deprecated.hpp" // for text, vtext #include "ftxui/dom/deprecated.hpp" // for text, vtext
#include "ftxui/dom/elements.hpp" // for Element, text, vtext #include "ftxui/dom/elements.hpp" // for Element, text, vtext
@@ -24,6 +25,7 @@ using ftxui::Screen;
class Text : public Node { class Text : public Node {
public: public:
explicit Text(std::string text) : text_(std::move(text)) {} explicit Text(std::string text) : text_(std::move(text)) {}
explicit Text(std::string_view sv) : Text(std::string(sv)) {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min_x = string_width(text_); requirement_.min_x = string_width(text_);
@@ -96,6 +98,8 @@ class VText : public Node {
explicit VText(std::string text) explicit VText(std::string text)
: text_(std::move(text)), width_{std::min(string_width(text_), 1)} {} : text_(std::move(text)), width_{std::min(string_width(text_), 1)} {}
explicit VText(std::string_view sv) : VText(std::string(sv)) {}
void ComputeRequirement() override { void ComputeRequirement() override {
requirement_.min_x = width_; requirement_.min_x = width_;
requirement_.min_y = string_width(text_); requirement_.min_y = string_width(text_);
@@ -138,8 +142,8 @@ class VText : public Node {
/// ```bash /// ```bash
/// Hello world! /// Hello world!
/// ``` /// ```
Element text(std::string text) { Element text(std::string_view text) {
return std::make_shared<Text>(std::move(text)); return std::make_shared<Text>(std::string(text));
} }
/// @brief Display a piece of unicode text. /// @brief Display a piece of unicode text.
@@ -161,6 +165,25 @@ Element text(std::wstring text) { // NOLINT
return std::make_shared<Text>(to_string(text)); return std::make_shared<Text>(to_string(text));
} }
/// @brief Display a piece of unicode text.
/// @ingroup dom
/// @see ftxui::to_wstring
///
/// ### Example
///
/// ```cpp
/// Element document = text(L"Hello world!");
/// ```
///
/// ### Output
///
/// ```bash
/// Hello world!
/// ```
Element text(std::wstring_view sv) {
return text(std::wstring(sv));
}
/// @brief Display a piece of unicode text vertically. /// @brief Display a piece of unicode text vertically.
/// @ingroup dom /// @ingroup dom
/// @see ftxui::to_wstring /// @see ftxui::to_wstring
@@ -187,8 +210,8 @@ Element text(std::wstring text) { // NOLINT
/// d /// d
/// ! /// !
/// ``` /// ```
Element vtext(std::string text) { Element vtext(std::string_view text) {
return std::make_shared<VText>(std::move(text)); return std::make_shared<VText>(std::string(text));
} }
/// @brief Display a piece unicode text vertically. /// @brief Display a piece unicode text vertically.
@@ -221,4 +244,34 @@ Element vtext(std::wstring text) { // NOLINT
return std::make_shared<VText>(to_string(text)); return std::make_shared<VText>(to_string(text));
} }
/// @brief Display a piece unicode text vertically.
/// @ingroup dom
/// @see ftxui::to_wstring
///
/// ### Example
///
/// ```cpp
/// Element document = vtext(L"Hello world!");
/// ```
///
/// ### Output
///
/// ```bash
/// H
/// e
/// l
/// l
/// o
///
/// w
/// o
/// r
/// l
/// d
/// !
/// ```
Element vtext(std::wstring_view text) { // NOLINT
return vtext(std::wstring(text));
}
} // namespace ftxui } // namespace ftxui

View File

@@ -2,7 +2,8 @@
// Use of this source code is governed by the MIT license that can be found in // Use of this source code is governed by the MIT license that can be found in
// the LICENSE file. // the LICENSE file.
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <string> // for allocator, string #include <string> // for allocator, string
#include <string_view> // for string_view
#include "ftxui/dom/elements.hpp" // for text, operator|, border, Element #include "ftxui/dom/elements.hpp" // for text, operator|, border, Element
#include "ftxui/dom/node.hpp" // for Render #include "ftxui/dom/node.hpp" // for Render
@@ -121,5 +122,13 @@ TEST(TextTest, CombiningCharactersWithSpace) {
EXPECT_EQ(t, screen.ToString()); EXPECT_EQ(t, screen.ToString());
} }
TEST(TextTest, WithStringViews) {
const std::string_view t = "Hello, world!";
auto element = text(t);
Screen screen(13, 1);
Render(screen, element);
EXPECT_EQ(t, screen.ToString());
}
} // namespace ftxui } // namespace ftxui
// NOLINTEND // NOLINTEND

View File

@@ -531,7 +531,7 @@ void Screen::ApplyShader() {
} }
// clang-format on // clang-format on
std::uint8_t Screen::RegisterHyperlink(const std::string& link) { std::uint8_t Screen::RegisterHyperlink(std::string_view link) {
for (std::size_t i = 0; i < hyperlinks_.size(); ++i) { for (std::size_t i = 0; i < hyperlinks_.size(); ++i) {
if (hyperlinks_[i] == link) { if (hyperlinks_[i] == link) {
return i; return i;
@@ -540,7 +540,7 @@ std::uint8_t Screen::RegisterHyperlink(const std::string& link) {
if (hyperlinks_.size() == std::numeric_limits<std::uint8_t>::max()) { if (hyperlinks_.size() == std::numeric_limits<std::uint8_t>::max()) {
return 0; return 0;
} }
hyperlinks_.push_back(link); hyperlinks_.push_back(std::string(link));
return hyperlinks_.size() - 1; return hyperlinks_.size() - 1;
} }

View File

@@ -1171,7 +1171,7 @@ namespace ftxui {
// one codepoint. Put the codepoint into |ucs|. Start at |start| and update // one codepoint. Put the codepoint into |ucs|. Start at |start| and update
// |end| to represent the beginning of the next byte to eat for consecutive // |end| to represent the beginning of the next byte to eat for consecutive
// executions. // executions.
bool EatCodePoint(const std::string& input, bool EatCodePoint(std::string_view input,
size_t start, size_t start,
size_t* end, size_t* end,
uint32_t* ucs) { uint32_t* ucs) {
@@ -1241,7 +1241,7 @@ bool EatCodePoint(const std::string& input,
// one codepoint. Put the codepoint into |ucs|. Start at |start| and update // one codepoint. Put the codepoint into |ucs|. Start at |start| and update
// |end| to represent the beginning of the next byte to eat for consecutive // |end| to represent the beginning of the next byte to eat for consecutive
// executions. // executions.
bool EatCodePoint(const std::wstring& input, bool EatCodePoint(std::wstring_view input,
size_t start, size_t start,
size_t* end, size_t* end,
uint32_t* ucs) { uint32_t* ucs) {
@@ -1328,7 +1328,7 @@ int wstring_width(const std::wstring& text) {
return width; return width;
} }
int string_width(const std::string& input) { int string_width(std::string_view input) {
int width = 0; int width = 0;
size_t start = 0; size_t start = 0;
while (start < input.size()) { while (start < input.size()) {
@@ -1355,7 +1355,7 @@ int string_width(const std::string& input) {
return width; return width;
} }
std::vector<std::string> Utf8ToGlyphs(const std::string& input) { std::vector<std::string> Utf8ToGlyphs(std::string_view input) {
std::vector<std::string> out; std::vector<std::string> out;
out.reserve(input.size()); out.reserve(input.size());
size_t start = 0; size_t start = 0;
@@ -1367,7 +1367,7 @@ std::vector<std::string> Utf8ToGlyphs(const std::string& input) {
continue; continue;
} }
const std::string append = input.substr(start, end - start); const auto append = input.substr(start, end - start);
start = end; start = end;
// Ignore control characters. // Ignore control characters.
@@ -1386,18 +1386,18 @@ std::vector<std::string> Utf8ToGlyphs(const std::string& input) {
// Fullwidth characters take two cells. The second is made of the empty // Fullwidth characters take two cells. The second is made of the empty
// string to reserve the space the first is taking. // string to reserve the space the first is taking.
if (IsFullWidth(codepoint)) { if (IsFullWidth(codepoint)) {
out.push_back(append); out.push_back(std::string(append));
out.emplace_back(""); out.emplace_back("");
continue; continue;
} }
// Normal characters: // Normal characters:
out.push_back(append); out.push_back(std::string(append));
} }
return out; return out;
} }
size_t GlyphPrevious(const std::string& input, size_t start) { size_t GlyphPrevious(std::string_view input, size_t start) {
while (true) { while (true) {
if (start == 0) { if (start == 0) {
return 0; return 0;
@@ -1422,7 +1422,7 @@ size_t GlyphPrevious(const std::string& input, size_t start) {
} }
} }
size_t GlyphNext(const std::string& input, size_t start) { size_t GlyphNext(std::string_view input, size_t start) {
bool glyph_found = false; bool glyph_found = false;
while (start < input.size()) { while (start < input.size()) {
size_t end = 0; size_t end = 0;
@@ -1448,7 +1448,7 @@ size_t GlyphNext(const std::string& input, size_t start) {
return static_cast<int>(input.size()); return static_cast<int>(input.size());
} }
size_t GlyphIterate(const std::string& input, int glyph_offset, size_t start) { size_t GlyphIterate(std::string_view input, int glyph_offset, size_t start) {
if (glyph_offset >= 0) { if (glyph_offset >= 0) {
for (int i = 0; i < glyph_offset; ++i) { for (int i = 0; i < glyph_offset; ++i) {
start = GlyphNext(input, start); start = GlyphNext(input, start);
@@ -1462,7 +1462,7 @@ size_t GlyphIterate(const std::string& input, int glyph_offset, size_t start) {
} }
} }
std::vector<int> CellToGlyphIndex(const std::string& input) { std::vector<int> CellToGlyphIndex(std::string_view input) {
int x = -1; int x = -1;
std::vector<int> out; std::vector<int> out;
out.reserve(input.size()); out.reserve(input.size());
@@ -1503,7 +1503,7 @@ std::vector<int> CellToGlyphIndex(const std::string& input) {
return out; return out;
} }
int GlyphCount(const std::string& input) { int GlyphCount(std::string_view input) {
int size = 0; int size = 0;
size_t start = 0; size_t start = 0;
size_t end = 0; size_t end = 0;
@@ -1531,8 +1531,7 @@ int GlyphCount(const std::string& input) {
return size; return size;
} }
std::vector<WordBreakProperty> Utf8ToWordBreakProperty( std::vector<WordBreakProperty> Utf8ToWordBreakProperty(std::string_view input) {
const std::string& input) {
std::vector<WordBreakProperty> out; std::vector<WordBreakProperty> out;
out.reserve(input.size()); out.reserve(input.size());
size_t start = 0; size_t start = 0;
@@ -1563,7 +1562,7 @@ std::vector<WordBreakProperty> Utf8ToWordBreakProperty(
} }
/// Convert a std::wstring into a UTF8 std::string. /// Convert a std::wstring into a UTF8 std::string.
std::string to_string(const std::wstring& s) { std::string to_string(std::wstring_view s) {
std::string out; std::string out;
size_t i = 0; size_t i = 0;
@@ -1635,7 +1634,7 @@ std::string to_string(const std::wstring& s) {
} }
/// Convert a UTF8 std::string into a std::wstring. /// Convert a UTF8 std::string into a std::wstring.
std::wstring to_wstring(const std::string& s) { std::wstring to_wstring(std::string_view s) {
std::wstring out; std::wstring out;
size_t i = 0; size_t i = 0;

View File

@@ -10,11 +10,11 @@
namespace ftxui { namespace ftxui {
bool EatCodePoint(const std::string& input, bool EatCodePoint(std::string_view input,
size_t start, size_t start,
size_t* end, size_t* end,
uint32_t* ucs); uint32_t* ucs);
bool EatCodePoint(const std::wstring& input, bool EatCodePoint(std::wstring_view input,
size_t start, size_t start,
size_t* end, size_t* end,
uint32_t* ucs); uint32_t* ucs);
@@ -23,17 +23,15 @@ bool IsCombining(uint32_t ucs);
bool IsFullWidth(uint32_t ucs); bool IsFullWidth(uint32_t ucs);
bool IsControl(uint32_t ucs); bool IsControl(uint32_t ucs);
size_t GlyphPrevious(const std::string& input, size_t start); size_t GlyphPrevious(std::string_view input, size_t start);
size_t GlyphNext(const std::string& input, size_t start); size_t GlyphNext(std::string_view input, size_t start);
// Return the index in the |input| string of the glyph at |glyph_offset|, // Return the index in the |input| string of the glyph at |glyph_offset|,
// starting at |start| // starting at |start|
size_t GlyphIterate(const std::string& input, size_t GlyphIterate(std::string_view input, int glyph_offset, size_t start = 0);
int glyph_offset,
size_t start = 0);
// Returns the number of glyphs in |input|. // Returns the number of glyphs in |input|.
int GlyphCount(const std::string& input); int GlyphCount(std::string_view input);
// Properties from: // Properties from:
// https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/WordBreakProperty.txt // https://www.unicode.org/Public/UCD/latest/ucd/auxiliary/WordBreakProperty.txt
@@ -58,10 +56,9 @@ enum class WordBreakProperty : int8_t {
ZWJ, ZWJ,
}; };
WordBreakProperty CodepointToWordBreakProperty(uint32_t codepoint); WordBreakProperty CodepointToWordBreakProperty(uint32_t codepoint);
std::vector<WordBreakProperty> Utf8ToWordBreakProperty( std::vector<WordBreakProperty> Utf8ToWordBreakProperty(std::string_view input);
const std::string& input);
bool IsWordBreakingCharacter(const std::string& input, size_t glyph_index); bool IsWordBreakingCharacter(std::string_view input, size_t glyph_index);
} // namespace ftxui } // namespace ftxui
#endif /* end of include guard: FTXUI_SCREEN_STRING_INTERNAL_HPP */ #endif /* end of include guard: FTXUI_SCREEN_STRING_INTERNAL_HPP */

View File

@@ -154,14 +154,14 @@ TEST(StringTest, to_string) {
} }
TEST(StringTest, to_wstring) { TEST(StringTest, to_wstring) {
EXPECT_EQ(to_wstring(std::string("hello")), L"hello"); EXPECT_EQ(to_wstring("hello"), L"hello");
EXPECT_EQ(to_wstring(std::string("")), L""); EXPECT_EQ(to_wstring(""), L"");
EXPECT_EQ(to_wstring(std::string("ÿ")), L"ÿ"); EXPECT_EQ(to_wstring("ÿ"), L"ÿ");
EXPECT_EQ(to_wstring(std::string("߿")), L"߿"); EXPECT_EQ(to_wstring("߿"), L"߿");
EXPECT_EQ(to_wstring(std::string("ɰɱ")), L"ɰɱ"); EXPECT_EQ(to_wstring("ɰɱ"), L"ɰɱ");
EXPECT_EQ(to_wstring(std::string("«»")), L"«»"); EXPECT_EQ(to_wstring("«»"), L"«»");
EXPECT_EQ(to_wstring(std::string("嵰嵲嵫")), L"嵰嵲嵫"); EXPECT_EQ(to_wstring("嵰嵲嵫"), L"嵰嵲嵫");
EXPECT_EQ(to_wstring(std::string("🎅🎄")), L"🎅🎄"); EXPECT_EQ(to_wstring("🎅🎄"), L"🎅🎄");
} }
} // namespace ftxui } // namespace ftxui

View File

@@ -13,7 +13,7 @@ class Adapter : public ConstStringListRef::Adapter {
public: public:
Adapter(std::vector<std::string>& entries) : entries(entries) {} Adapter(std::vector<std::string>& entries) : entries(entries) {}
size_t size() const override { return entries.size() * 2; } size_t size() const override { return entries.size() * 2; }
std::string operator[](size_t index) const override { std::string_view operator[](size_t index) const override {
return entries[index / 2]; return entries[index / 2];
} }
std::vector<std::string>& entries; std::vector<std::string>& entries;