mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-12-16 01:48:56 +08:00
Compare commits
10 Commits
a1df432245
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
170c1b94dd | ||
|
|
942ab6a82d | ||
|
|
9f4b2bcf96 | ||
|
|
117417e841 | ||
|
|
c8fbef03c9 | ||
|
|
183a426efa | ||
|
|
d9c62b3678 | ||
|
|
1d5516a8a5 | ||
|
|
e986b98faf | ||
|
|
97ffd572df |
1
.bazelignore
Normal file
1
.bazelignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
bazel/test/
|
||||||
3
.bazelrc
3
.bazelrc
@@ -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
|
||||||
|
|||||||
7
.github/workflows/build.yaml
vendored
7
.github/workflows/build.yaml
vendored
@@ -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
5
.gitignore
vendored
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -37,6 +43,9 @@ Next
|
|||||||
output. Thanks @zozowell in #1064.
|
output. Thanks @zozowell in #1064.
|
||||||
- Fix vertical `ftxui::Slider`. The "up" key was previously decreasing the
|
- Fix vertical `ftxui::Slider`. The "up" key was previously decreasing the
|
||||||
value. Thanks @its-pablo in #1093 for reporting the issue.
|
value. Thanks @its-pablo in #1093 for reporting the issue.
|
||||||
|
- Fix Windows UTF-16 key input handling. Emoji and other code points outside the
|
||||||
|
Basic Multilingual Plane (BMP) are now correctly processed. Thanks @739C1AE2
|
||||||
|
in #1160 for fixing the issue.
|
||||||
|
|
||||||
### Dom
|
### Dom
|
||||||
- Fix integer overflow in `ComputeShrinkHard`. Thanks @its-pablo in #1137 for
|
- Fix integer overflow in `ComputeShrinkHard`. Thanks @its-pablo in #1137 for
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -23,6 +23,12 @@
|
|||||||
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Request Feature</a> ·
|
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Request Feature</a> ·
|
||||||
<a href="https://github.com/ArthurSonzogni/FTXUI/pulls">Send a Pull Request</a>
|
<a href="https://github.com/ArthurSonzogni/FTXUI/pulls">Send a Pull Request</a>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<a href="https://github.com/ArthurSonzogni/">English</a> |
|
||||||
|
<a href="https://github.com/ArthurSonzogni/ftxui-translations/tree/zh-CH">中文翻译</a> |
|
||||||
|
<a href="https://github.com/ArthurSonzogni/ftxui-translations/tree/zh-CH">繁體中文</a> |
|
||||||
|
<a href="https://github.com/ArthurSonzogni/ftxui-translations/tree/ja">日本語</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
# FTXUI
|
# FTXUI
|
||||||
@@ -419,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
1
bazel/test/.bazelrc
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../.bazelrc
|
||||||
23
bazel/test/BUILD.bazel
Normal file
23
bazel/test/BUILD.bazel
Normal 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
9
bazel/test/MODULE.bazel
Normal 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
38
bazel/test/README.md
Normal 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
|
||||||
|
```
|
||||||
4
bazel/test/WORKSPACE.bazel
Normal file
4
bazel/test/WORKSPACE.bazel
Normal 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
16
bazel/test/smoke.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -92,6 +92,24 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
// Ignore non english pages and/or the main page.
|
||||||
|
const excluded_lang = [
|
||||||
|
"/de",
|
||||||
|
"/es",
|
||||||
|
"/fr",
|
||||||
|
"/it",
|
||||||
|
"/ja",
|
||||||
|
"/ja",
|
||||||
|
"/ko"
|
||||||
|
"/ru",
|
||||||
|
"/zh-CH",
|
||||||
|
"/zh-TW",
|
||||||
|
]
|
||||||
|
if (excluded_lang.some(lang => window.location.pathname.startsWith(lang)) ||
|
||||||
|
window.location.pathname.endsWith("index.html")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Click on the navtree, except for the main page where this is already done
|
// Click on the navtree, except for the main page where this is already done
|
||||||
// automatically.
|
// automatically.
|
||||||
let delay = 0;
|
let delay = 0;
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ add_executable(demo demo.cpp)
|
|||||||
target_link_libraries(demo PRIVATE ftxui::component)
|
target_link_libraries(demo PRIVATE ftxui::component)
|
||||||
```
|
```
|
||||||
|
|
||||||
@todo 考虑到中国多数地区使用Conan很有可能遇到各种网络问题,我想做一个定制的版本说明,但是我对conan的了解有限再加上没有找到合适的资料,因此这个计划短暂的被搁置了,如果您知道方法,欢迎在[中文版本](xiaoditx.girhub.io/public/docs/ftxui%E4%B8%AD%E6%96%87%E7%BF%BB%E8%AF%91/installation/conan/)的下方留下评论以提醒我
|
@todo 中国大陆在这方面的下载可能会受限制,需要一个替代的方案
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Clone and build the project using CMake:
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/ArthurSonzogni/FTXUI.git
|
git clone https://github.com/ArthurSonzogni/FTXUI.git
|
||||||
cd FTXUI
|
cd FTXUI
|
||||||
cmake -S . -B build -DFTXUI_ENABLE_INSTALL=ON -D
|
cmake -S . -B build -D FTXUI_ENABLE_INSTALL=ON
|
||||||
cmake --build build -j
|
cmake --build build -j
|
||||||
sudo cmake --install build
|
sudo cmake --install build
|
||||||
```
|
```
|
||||||
|
|||||||
12
flake.lock
generated
12
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694529238,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1697915759,
|
"lastModified": 1765644376,
|
||||||
"narHash": "sha256-WyMj5jGcecD+KC8gEs+wFth1J1wjisZf8kVZH13f1Zo=",
|
"narHash": "sha256-yqHBL2wYGwjGL2GUF2w3tofWl8qO9tZEuI4wSqbCrtE=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "51d906d2341c9e866e48c2efcaac0f2d70bfd43e",
|
"rev": "23735a82a828372c4ef92c660864e82fbe2f5fbe",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
12
flake.nix
12
flake.nix
@@ -12,15 +12,9 @@
|
|||||||
let llvm = pkgs.llvmPackages_latest; in
|
let llvm = pkgs.llvmPackages_latest; in
|
||||||
{
|
{
|
||||||
packages = rec {
|
packages = rec {
|
||||||
default = pkgs.stdenv.mkDerivation rec {
|
default = pkgs.stdenv.mkDerivation {
|
||||||
pname = "ftxui";
|
name = "ftxui";
|
||||||
version = "v4.0.0";
|
src = ./.;
|
||||||
src = pkgs.fetchFromGitHub {
|
|
||||||
owner = "ArthurSonzogni";
|
|
||||||
repo = "FTXUI";
|
|
||||||
rev = version;
|
|
||||||
sha256 = "sha256-3kAhHDUwzwdvHc8JZAcA14tGqa6w69qrN1JXhSxNBQY=";
|
|
||||||
};
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.cmake
|
pkgs.cmake
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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&)>;
|
||||||
|
|||||||
@@ -5,26 +5,31 @@
|
|||||||
#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 <string_view> // for string_view
|
||||||
#include <vector> // for vector
|
#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
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
@@ -17,8 +18,13 @@ template <typename T>
|
|||||||
class ConstRef {
|
class ConstRef {
|
||||||
public:
|
public:
|
||||||
ConstRef() = default;
|
ConstRef() = default;
|
||||||
|
|
||||||
|
// Owning constructors:
|
||||||
ConstRef(T t) : variant_(std::move(t)) {} // NOLINT
|
ConstRef(T t) : variant_(std::move(t)) {} // NOLINT
|
||||||
|
|
||||||
|
// Referencing constructors:
|
||||||
ConstRef(const T* t) : variant_(t) {} // NOLINT
|
ConstRef(const T* t) : variant_(t) {} // NOLINT
|
||||||
|
|
||||||
ConstRef& operator=(ConstRef&&) noexcept = default;
|
ConstRef& operator=(ConstRef&&) noexcept = default;
|
||||||
ConstRef(const ConstRef<T>&) = default;
|
ConstRef(const ConstRef<T>&) = default;
|
||||||
ConstRef(ConstRef<T>&&) noexcept = default;
|
ConstRef(ConstRef<T>&&) noexcept = default;
|
||||||
@@ -46,8 +52,13 @@ template <typename T>
|
|||||||
class Ref {
|
class Ref {
|
||||||
public:
|
public:
|
||||||
Ref() = default;
|
Ref() = default;
|
||||||
|
|
||||||
|
// Owning constructors:
|
||||||
Ref(T t) : variant_(std::move(t)) {} // NOLINT
|
Ref(T t) : variant_(std::move(t)) {} // NOLINT
|
||||||
|
//
|
||||||
|
// Referencing constructors:
|
||||||
Ref(T* t) : variant_(t) {} // NOLINT
|
Ref(T* t) : variant_(t) {} // NOLINT
|
||||||
|
//
|
||||||
~Ref() = default;
|
~Ref() = default;
|
||||||
Ref& operator=(Ref&&) noexcept = default;
|
Ref& operator=(Ref&&) noexcept = default;
|
||||||
Ref(const Ref<T>&) = default;
|
Ref(const Ref<T>&) = default;
|
||||||
@@ -83,10 +94,15 @@ class StringRef : public Ref<std::string> {
|
|||||||
public:
|
public:
|
||||||
using Ref<std::string>::Ref;
|
using Ref<std::string>::Ref;
|
||||||
|
|
||||||
|
// Owning constructors:
|
||||||
StringRef(const wchar_t* ref) // NOLINT
|
StringRef(const wchar_t* ref) // NOLINT
|
||||||
: StringRef(to_string(std::wstring(ref))) {}
|
: StringRef(to_string(std::wstring(ref))) {}
|
||||||
StringRef(const char* ref) // NOLINT
|
StringRef(const char* ref) // NOLINT
|
||||||
: StringRef(std::string(ref)) {}
|
: StringRef(std::string(ref)) {}
|
||||||
|
StringRef(std::string_view ref) // NOLINT
|
||||||
|
: StringRef(std::string(ref)) {}
|
||||||
|
StringRef(std::wstring_view ref) // NOLINT
|
||||||
|
: StringRef(to_string(ref)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief An adapter. Own or reference a constant string. For convenience, this
|
/// @brief An adapter. Own or reference a constant string. For convenience, this
|
||||||
@@ -95,14 +111,21 @@ class ConstStringRef : public ConstRef<std::string> {
|
|||||||
public:
|
public:
|
||||||
using ConstRef<std::string>::ConstRef;
|
using ConstRef<std::string>::ConstRef;
|
||||||
|
|
||||||
|
// Referencing constructors:
|
||||||
ConstStringRef(const std::wstring* ref) // NOLINT
|
ConstStringRef(const std::wstring* ref) // NOLINT
|
||||||
: ConstStringRef(to_string(*ref)) {}
|
: ConstStringRef(to_string(*ref)) {}
|
||||||
|
|
||||||
|
// Owning constructors:
|
||||||
ConstStringRef(const std::wstring ref) // NOLINT
|
ConstStringRef(const std::wstring ref) // NOLINT
|
||||||
: ConstStringRef(to_string(ref)) {}
|
: ConstStringRef(to_string(ref)) {}
|
||||||
|
ConstStringRef(std::wstring_view ref) // NOLINT
|
||||||
|
: ConstStringRef(to_string(ref)) {}
|
||||||
ConstStringRef(const wchar_t* ref) // NOLINT
|
ConstStringRef(const wchar_t* ref) // NOLINT
|
||||||
: ConstStringRef(to_string(std::wstring(ref))) {}
|
: ConstStringRef(to_string(std::wstring(ref))) {}
|
||||||
ConstStringRef(const char* ref) // NOLINT
|
ConstStringRef(const char* ref) // NOLINT
|
||||||
: ConstStringRef(std::string(ref)) {}
|
: ConstStringRef(std::string(ref)) {}
|
||||||
|
ConstStringRef(std::string_view ref) // NOLINT
|
||||||
|
: ConstStringRef(std::string(ref)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief An adapter. Reference a list of strings.
|
/// @brief An adapter. Reference a list of strings.
|
||||||
@@ -125,10 +148,12 @@ 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::string_view>, //
|
||||||
|
const std::vector<std::string_view>*, //
|
||||||
const std::vector<std::wstring>*, //
|
const std::vector<std::wstring>*, //
|
||||||
Adapter*, //
|
Adapter*, //
|
||||||
std::unique_ptr<Adapter> //
|
std::unique_ptr<Adapter> //
|
||||||
@@ -141,25 +166,26 @@ class ConstStringListRef {
|
|||||||
ConstStringListRef(ConstStringListRef&&) = default;
|
ConstStringListRef(ConstStringListRef&&) = default;
|
||||||
ConstStringListRef(const ConstStringListRef&) = default;
|
ConstStringListRef(const ConstStringListRef&) = default;
|
||||||
|
|
||||||
ConstStringListRef(std::vector<std::string> value) // NOLINT
|
ConstStringListRef(std::vector<std::string> value) { // NOLINT
|
||||||
{
|
|
||||||
variant_ = std::make_shared<Variant>(value);
|
variant_ = std::make_shared<Variant>(value);
|
||||||
}
|
}
|
||||||
ConstStringListRef(const std::vector<std::string>* value) // NOLINT
|
ConstStringListRef(const std::vector<std::string>* value) {// NOLINT
|
||||||
{
|
|
||||||
variant_ = std::make_shared<Variant>(value);
|
variant_ = std::make_shared<Variant>(value);
|
||||||
}
|
}
|
||||||
ConstStringListRef(const std::vector<std::wstring>* value) // NOLINT
|
ConstStringListRef(std::vector<std::string_view> value) { // NOLINT
|
||||||
{
|
|
||||||
variant_ = std::make_shared<Variant>(value);
|
variant_ = std::make_shared<Variant>(value);
|
||||||
}
|
}
|
||||||
ConstStringListRef(Adapter* adapter) // NOLINT
|
ConstStringListRef(const std::vector<std::string_view>* value) { // NOLINT
|
||||||
{
|
variant_ = std::make_shared<Variant>(value);
|
||||||
|
}
|
||||||
|
ConstStringListRef(const std::vector<std::wstring>* value) { // NOLINT
|
||||||
|
variant_ = std::make_shared<Variant>(value);
|
||||||
|
}
|
||||||
|
ConstStringListRef(Adapter* adapter) { // NOLINT
|
||||||
variant_ = std::make_shared<Variant>(adapter);
|
variant_ = std::make_shared<Variant>(adapter);
|
||||||
}
|
}
|
||||||
template <typename AdapterType>
|
template <typename AdapterType>
|
||||||
ConstStringListRef(std::unique_ptr<AdapterType> adapter) // NOLINT
|
ConstStringListRef(std::unique_ptr<AdapterType> adapter) { // NOLINT
|
||||||
{
|
|
||||||
variant_ = std::make_shared<Variant>(
|
variant_ = std::make_shared<Variant>(
|
||||||
static_cast<std::unique_ptr<Adapter>>(std::move(adapter)));
|
static_cast<std::unique_ptr<Adapter>>(std::move(adapter)));
|
||||||
}
|
}
|
||||||
@@ -168,11 +194,34 @@ class ConstStringListRef {
|
|||||||
return variant_ ? std::visit(SizeVisitor(), *variant_) : 0;
|
return variant_ ? std::visit(SizeVisitor(), *variant_) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string operator[](size_t i) const {
|
std::string_view operator[](size_t i) const {
|
||||||
return variant_ ? std::visit(IndexedGetter(i), *variant_) : "";
|
return variant_ ? std::visit(IndexedGetter{i}, *variant_) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct IndexedGetter {
|
||||||
|
size_t i;
|
||||||
|
std::string_view operator()(const std::vector<std::string>& v) const {
|
||||||
|
return v[i];
|
||||||
|
}
|
||||||
|
std::string_view operator()(const std::vector<std::string>* v) const {
|
||||||
|
return (*v)[i];
|
||||||
|
}
|
||||||
|
std::string_view operator()(const std::vector<std::string_view>& v) const {
|
||||||
|
return std::string(v[i]);
|
||||||
|
}
|
||||||
|
std::string_view operator()(const std::vector<std::string_view>* v) const {
|
||||||
|
return std::string((*v)[i]);
|
||||||
|
}
|
||||||
|
std::string_view operator()(const std::vector<std::wstring>* v) const {
|
||||||
|
return to_string((*v)[i]);
|
||||||
|
}
|
||||||
|
std::string_view operator()(Adapter* v) const { return std::string((*v)[i]); }
|
||||||
|
std::string_view operator()(const std::unique_ptr<Adapter>& v) const {
|
||||||
|
return (*v)[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SizeVisitor {
|
struct SizeVisitor {
|
||||||
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();
|
||||||
@@ -180,6 +229,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 +244,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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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) //
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class MenuBase : public ComponentBase, public MenuOption {
|
|||||||
const bool is_selected = (selected() == i);
|
const bool is_selected = (selected() == i);
|
||||||
|
|
||||||
const EntryState state = {
|
const EntryState state = {
|
||||||
entries[i], false, is_selected, is_focused, i,
|
std::string(entries[i]), false, is_selected, is_focused, i,
|
||||||
};
|
};
|
||||||
|
|
||||||
Element element = (entries_option.transform ? entries_option.transform
|
Element element = (entries_option.transform ? entries_option.transform
|
||||||
@@ -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) //
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class RadioboxBase : public ComponentBase, public RadioboxOption {
|
|||||||
const bool is_focused = (focused_entry() == i) && is_menu_focused;
|
const bool is_focused = (focused_entry() == i) && is_menu_focused;
|
||||||
const bool is_selected = (hovered_ == i);
|
const bool is_selected = (hovered_ == i);
|
||||||
auto state = EntryState{
|
auto state = EntryState{
|
||||||
entries[i], selected() == i, is_selected, is_focused, i,
|
std::string(entries[i]), selected() == i, is_selected, is_focused, i,
|
||||||
};
|
};
|
||||||
auto element =
|
auto element =
|
||||||
(transform ? transform : RadioboxOption::Simple().transform)(state);
|
(transform ? transform : RadioboxOption::Simple().transform)(state);
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1098,6 +1098,7 @@ void ScreenInteractive::FetchTerminalEvents() {
|
|||||||
// Convert the input events to FTXUI events.
|
// Convert the input events to FTXUI events.
|
||||||
// For each event, we call the terminal input parser to convert it to
|
// For each event, we call the terminal input parser to convert it to
|
||||||
// Event.
|
// Event.
|
||||||
|
std::wstring wstring;
|
||||||
for (const auto& r : records) {
|
for (const auto& r : records) {
|
||||||
switch (r.EventType) {
|
switch (r.EventType) {
|
||||||
case KEY_EVENT: {
|
case KEY_EVENT: {
|
||||||
@@ -1106,11 +1107,16 @@ void ScreenInteractive::FetchTerminalEvents() {
|
|||||||
if (key_event.bKeyDown == FALSE) {
|
if (key_event.bKeyDown == FALSE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::wstring wstring;
|
const wchar_t wc = key_event.uChar.UnicodeChar;
|
||||||
wstring += key_event.uChar.UnicodeChar;
|
wstring += wc;
|
||||||
|
if (wc >= 0xd800 && wc <= 0xdbff) {
|
||||||
|
// Wait for the Low Surrogate to arrive in the next record.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (auto it : to_string(wstring)) {
|
for (auto it : to_string(wstring)) {
|
||||||
internal_->terminal_input_parser.Add(it);
|
internal_->terminal_input_parser.Add(it);
|
||||||
}
|
}
|
||||||
|
wstring.clear();
|
||||||
} break;
|
} break;
|
||||||
case WINDOW_BUFFER_SIZE_EVENT:
|
case WINDOW_BUFFER_SIZE_EVENT:
|
||||||
Post(Event::Special({0}));
|
Post(Event::Special({0}));
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#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 <string_view> // for string_view
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/deprecated.hpp" // for text, vtext
|
#include "ftxui/dom/deprecated.hpp" // for 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
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// 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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from typing import List, Dict
|
|||||||
|
|
||||||
# --- Configuration ---
|
# --- Configuration ---
|
||||||
# URL for the translations repository. This is where other language branches reside.
|
# URL for the translations repository. This is where other language branches reside.
|
||||||
TRANSLATIONS_REPO_URL = "git@github.com:ArthurSonzogni/ftxui-translations.git"
|
TRANSLATIONS_REPO_URL = "https://github.com/ArthurSonzogni/ftxui-translations"
|
||||||
# --- End Configuration ---
|
# --- End Configuration ---
|
||||||
|
|
||||||
# Mapping of language codes to their display names for the dropdown menu.
|
# Mapping of language codes to their display names for the dropdown menu.
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ console = Console()
|
|||||||
# Config & Constants
|
# Config & Constants
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
FTXUI_REPO_URL = "git@github.com:ArthurSonzogni/FTXUI.git"
|
FTXUI_REPO_URL = "git@github.com:ArthurSonzogni/FTXUI.git"
|
||||||
TRANSLATIONS_REPO_URL = "https://github.com/ArthurSonzogni/ftxui-translations.git"
|
TRANSLATIONS_REPO_URL = "git@github.com:ArthurSonzogni/ftxui-translations.git"
|
||||||
MODEL = "gemini-2.5-flash"
|
MODEL = "gemini-2.5-flash"
|
||||||
|
|
||||||
# --- FREE TIER LIMITS (Conservative) ---
|
# --- FREE TIER LIMITS (Conservative) ---
|
||||||
@@ -150,7 +150,8 @@ limiter = RateLimiter(LIMIT_RPM, LIMIT_TPM)
|
|||||||
# Prompts
|
# Prompts
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
AGENT_NEW_FILE_PROMPT = """\
|
AGENT_NEW_FILE_PROMPT = """\
|
||||||
You are an autonomous documentation translator.
|
You are an autonomous documentation translator. You are translating the FTXUI
|
||||||
|
C++ library from English into {lang_name} ("{lang_code}").
|
||||||
|
|
||||||
GOAL
|
GOAL
|
||||||
- Translate a single, NEW file to {lang_name} ("{lang_code}").
|
- Translate a single, NEW file to {lang_name} ("{lang_code}").
|
||||||
@@ -173,7 +174,8 @@ TOOLS: {allowed_tools}.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
AGENT_DIFF_FILE_PROMPT = """\
|
AGENT_DIFF_FILE_PROMPT = """\
|
||||||
You are an autonomous documentation translator.
|
You are an autonomous documentation translator. You are translating the FTXUI
|
||||||
|
C++ library from English into {lang_name} ("{lang_code}").
|
||||||
|
|
||||||
GOAL
|
GOAL
|
||||||
- Update existing translation: {tx_root}/{rel_path}
|
- Update existing translation: {tx_root}/{rel_path}
|
||||||
@@ -195,6 +197,16 @@ WORKFLOW
|
|||||||
4. ONLY update text where the source changed.
|
4. ONLY update text where the source changed.
|
||||||
5. DO NOT translate code.
|
5. DO NOT translate code.
|
||||||
|
|
||||||
|
RULES:
|
||||||
|
1. Translate ONLY documentation:
|
||||||
|
* C++ comments (//, /* ... */)
|
||||||
|
* Doxygen comments (///, /** ... */).
|
||||||
|
* Prose in Markdown.
|
||||||
|
2. DO NOT translate/modify:
|
||||||
|
* C/C++ code, identifiers, includes, macros.
|
||||||
|
* Doxygen commands/params.
|
||||||
|
* Markdown code fences/URLs.
|
||||||
|
|
||||||
TOOLS: {allowed_tools}.
|
TOOLS: {allowed_tools}.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -404,9 +416,15 @@ def main() -> None:
|
|||||||
all_files.sort()
|
all_files.sort()
|
||||||
|
|
||||||
for lang_code in args.langs:
|
for lang_code in args.langs:
|
||||||
lang_name = LANG_NAMES.get(lang_code, lang_code)
|
lang_name = LANG_NAMES.get(lang_code, "")
|
||||||
print_step(f"Processing Language: {lang_name} ({lang_code})")
|
print_step(f"Processing Language: {lang_name} ({lang_code})")
|
||||||
|
|
||||||
|
if not lang_name:
|
||||||
|
exit_msg = f"Unknown language code: {lang_code}. Please update LANG_NAMES dictionary."
|
||||||
|
print_err(exit_msg)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
checkout_or_create_branch(tx_dir, lang_code)
|
checkout_or_create_branch(tx_dir, lang_code)
|
||||||
|
|
||||||
cache_path = tx_dir / CACHE_FILE
|
cache_path = tx_dir / CACHE_FILE
|
||||||
|
|||||||
Reference in New Issue
Block a user