30std::vector<std::string>
Split(
const std::string& input) {
31 std::vector<std::string>
output;
32 std::stringstream
ss(input);
34 while (std::getline(
ss, line)) {
37 if (input.back() ==
'\n') {
92class InputBase :
public ComponentBase,
public InputOption {
109 if (content->empty()) {
123 const std::vector<std::string>
lines =
Split(*content);
125 cursor_position() =
util::clamp(cursor_position(), 0, (
int)content->size());
130 for (
const auto& line :
lines) {
144 for (
size_t i = 0; i <
lines.size(); ++i) {
145 const std::string& line =
lines[i];
170 auto element =
hbox({
187 Element Text(
const std::string& input) {
193 out.reserve(10 + input.size() * 3 / 2);
194 for (
size_t i = 0; i < input.size(); ++i) {
201 if (cursor_position() == 0) {
205 const size_t end = cursor_position();
207 cursor_position() =
static_cast<int>(
start);
213 if (cursor_position() == (
int)content->size()) {
216 const size_t start = cursor_position();
217 const size_t end =
GlyphNext(content(), cursor_position());
231 if (cursor_position() == 0) {
236 static_cast<int>(
GlyphPrevious(content(), cursor_position()));
241 if (cursor_position() == (
int)content->size()) {
246 static_cast<int>(
GlyphNext(content(), cursor_position()));
251 size_t iter = cursor_position();
258 if (content()[
iter] ==
'\n') {
269 if (cursor_position() == (
int)content().
size() ||
270 content()[cursor_position()] ==
'\n') {
276 static_cast<int>(
GlyphNext(content(), cursor_position()));
281 if (cursor_position() == 0) {
289 if (cursor_position() == 0) {
296 cursor_position() =
static_cast<int>(
previous);
299 static_cast<int>(
GlyphPrevious(content(), cursor_position()));
301 if (cursor_position() == 0) {
308 cursor_position() =
static_cast<int>(
previous);
316 if (cursor_position() == (
int)content->size()) {
324 if (content()[cursor_position()] ==
'\n') {
328 static_cast<int>(
GlyphNext(content(), cursor_position()));
329 if (cursor_position() == (
int)content().size()) {
334 static_cast<int>(
GlyphNext(content(), cursor_position()));
341 cursor_position() = 0;
346 cursor_position() =
static_cast<int>(content->size());
359 if (!insert() && cursor_position() < (
int)content->size() &&
360 content()[cursor_position()] !=
'\n') {
363 content->insert(cursor_position(), character);
364 cursor_position() +=
static_cast<int>(character.size());
369 bool OnEvent(Event
event)
override {
370 cursor_position() =
util::clamp(cursor_position(), 0, (
int)content->size());
375 if (
event.is_character()) {
378 if (
event.is_mouse()) {
418 if (cursor_position() == 0) {
423 while (cursor_position()) {
428 cursor_position() =
static_cast<int>(
previous);
431 while (cursor_position()) {
436 cursor_position() =
static_cast<int>(
previous);
442 if (cursor_position() == (
int)content().
size()) {
447 while (cursor_position() < (
int)content().
size()) {
449 static_cast<int>(
GlyphNext(content(), cursor_position()));
455 while (cursor_position() < (
int)content().size()) {
460 cursor_position() =
static_cast<int>(
next);
467 hovered_ = box_.Contain(
event.mouse().x,
483 if (content->empty()) {
484 cursor_position() = 0;
489 std::vector<std::string>
lines =
Split(*content);
492 for (
const auto& line :
lines) {
521 cursor_position() = 0;
523 cursor_position() +=
static_cast<int>(
lines[i].size() + 1);
527 static_cast<int>(
GlyphWidth(content(), cursor_position()));
529 static_cast<int>(
GlyphNext(content(), cursor_position()));
537 insert() = !insert();
543 bool hovered_ =
false;
603 option.content = std::move(content);
629 option.content = std::move(content);
630 option.placeholder = std::move(placeholder);
An adapter. Own or reference a constant string. For convenience, this class convert multiple mutable ...
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
size_t GlyphNext(const std::string &input, size_t start)
Element focusCursorBarBlinking(Element)
Same as focus, but set the cursor shape to be a blinking bar.
Element xflex(Element)
Expand/Minimize if possible/needed on the X axis.
WordBreakProperty CodepointToWordBreakProperty(uint32_t codepoint)
Decorator size(WidthOrHeight, Constraint, int value)
Apply a constraint on the size of an element.
std::shared_ptr< Node > Element
std::shared_ptr< T > Make(Args &&... args)
std::shared_ptr< ComponentBase > Component
int string_width(const std::string &)
Element hbox(Elements)
A container displaying elements horizontally one by one.
Element text(std::wstring text)
Display a piece of unicode text.
std::vector< Element > Elements
Component Input(InputOption options={})
An input box for editing text.
bool EatCodePoint(const std::string &input, size_t start, size_t *end, uint32_t *ucs)
Element select(Element)
Set the child to be the one selected among its siblings.
Element focus(Element)
Set the child to be the one in focus globally.
Decorator reflect(Box &box)
bool IsFullWidth(uint32_t ucs)
Element frame(Element)
Allow an element to be displayed inside a 'virtual' area. It size can be larger than its container....
void Render(Screen &screen, const Element &element)
Display an element on a ftxui::Screen.
Element focusCursorBlockBlinking(Element)
Same as focus, but set the cursor shape to be a blinking block.
size_t GlyphPrevious(const std::string &input, size_t start)
Element vbox(Elements)
A container displaying elements vertically one by one.
static const Event ArrowLeftCtrl
static const Event Backspace
static const Event ArrowUp
static const Event ArrowDown
static const Event Return
static const Event ArrowLeft
static const Event Delete
static const Event Insert
static const Event ArrowRightCtrl
static const Event ArrowRight