From 05c7bee6dde8e38c62c5aceb68ff07e96dfd50af Mon Sep 17 00:00:00 2001 From: MingSheng <102264706+mingsheng13@users.noreply.github.com> Date: Mon, 28 Aug 2023 20:07:26 +0100 Subject: [PATCH] Feature: input can now use overwrite mode when toggled with insert key (#735) Co-authored-by: ArthurSonzogni --- CHANGELOG.md | 4 +++ include/ftxui/component/component_options.hpp | 1 + include/ftxui/component/event.hpp | 1 + src/ftxui/component/event.cpp | 1 + src/ftxui/component/input.cpp | 19 ++++++++++--- src/ftxui/component/input_test.cpp | 28 +++++++++++++++++++ 6 files changed, 50 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4ae1b..a094fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Changelog current (development) --------------------- +### Component +- Feature: Add support for `Input`'s insert mode. Add `InputOption::insert` + option. Added by @mingsheng13. + 5.0.0 ----- diff --git a/include/ftxui/component/component_options.hpp b/include/ftxui/component/component_options.hpp index b401b6d..c437bf0 100644 --- a/include/ftxui/component/component_options.hpp +++ b/include/ftxui/component/component_options.hpp @@ -177,6 +177,7 @@ struct InputOption { std::function transform; Ref password = false; /// < Obscure the input content using '*'. Ref multiline = true; /// < Whether the input can be multiline. + Ref insert = true; /// < Insert or overtype character mode. /// Called when the content changes. std::function on_change = [] {}; diff --git a/include/ftxui/component/event.hpp b/include/ftxui/component/event.hpp index 504bee0..b481622 100644 --- a/include/ftxui/component/event.hpp +++ b/include/ftxui/component/event.hpp @@ -55,6 +55,7 @@ struct Event { static const Event TabReverse; static const Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12; + static const Event Insert; static const Event Home; static const Event End; diff --git a/src/ftxui/component/event.cpp b/src/ftxui/component/event.cpp index b653074..72a57f1 100644 --- a/src/ftxui/component/event.cpp +++ b/src/ftxui/component/event.cpp @@ -100,6 +100,7 @@ const Event Event::F10 = Event::Special("\x1B[21~"); // NOLINT const Event Event::F11 = Event::Special("\x1B[23~"); // NOLINT const Event Event::F12 = Event::Special("\x1B[24~"); // NOLINT +const Event Event::Insert = Event::Special("\x1B[2~"); // NOLINT const Event Event::Home = Event::Special({27, 91, 72}); // NOLINT const Event Event::End = Event::Special({27, 91, 70}); // NOLINT const Event Event::PageUp = Event::Special({27, 91, 53, 126}); // NOLINT diff --git a/src/ftxui/component/input.cpp b/src/ftxui/component/input.cpp index 1212214..caef66c 100644 --- a/src/ftxui/component/input.cpp +++ b/src/ftxui/component/input.cpp @@ -100,8 +100,9 @@ class InputBase : public ComponentBase, public InputOption { // Component implementation: Element Render() override { const bool is_focused = Focused(); - const auto focused = - (is_focused || hovered_) ? focusCursorBarBlinking : select; + const auto focused = (!is_focused && !hovered_) ? select + : insert() ? focusCursorBarBlinking + : focusCursorBlockBlinking; auto transform_func = transform ? transform : InputOption::Default().transform; @@ -342,10 +343,13 @@ class InputBase : public ComponentBase, public InputOption { } bool HandleCharacter(const std::string& character) { + if (!insert() && cursor_position() < (int)content->size() && + content()[cursor_position()] != '\n') { + HandleDelete(); + } content->insert(cursor_position(), character); cursor_position() += character.size(); on_change(); - return true; } @@ -391,7 +395,9 @@ class InputBase : public ComponentBase, public InputOption { if (event == Event::ArrowRightCtrl) { return HandleRightCtrl(); } - + if (event == Event::Insert) { + return HandleInsert(); + } return false; } @@ -509,6 +515,11 @@ class InputBase : public ComponentBase, public InputOption { return true; } + bool HandleInsert() { + insert() = !insert(); + return true; + } + bool Focusable() const final { return true; } bool hovered_ = false; diff --git a/src/ftxui/component/input_test.cpp b/src/ftxui/component/input_test.cpp index 96a63b3..863569a 100644 --- a/src/ftxui/component/input_test.cpp +++ b/src/ftxui/component/input_test.cpp @@ -754,4 +754,32 @@ TEST(InputTest, OnEnter) { EXPECT_TRUE(on_enter_called); } +TEST(InputTest, InsertMode) { + std::string content = "abc\nefg"; + bool insert = true; + int cursor_position = 1; + Component input = Input({ + .content = &content, + .insert = &insert, + .cursor_position = &cursor_position, + }); + + EXPECT_TRUE(insert); + EXPECT_TRUE(input->OnEvent(Event::Insert)); + EXPECT_FALSE(insert); + + EXPECT_EQ(content, "abc\nefg"); + EXPECT_TRUE(input->OnEvent(Event::Character('x'))); + EXPECT_EQ(content, "axc\nefg"); + EXPECT_TRUE(input->OnEvent(Event::Character('y'))); + EXPECT_EQ(content, "axy\nefg"); + EXPECT_TRUE(input->OnEvent(Event::Character('z'))); + EXPECT_EQ(content, "axyz\nefg"); + + EXPECT_TRUE(input->OnEvent(Event::ArrowDown)); + EXPECT_EQ(content, "axyz\nefg"); + EXPECT_TRUE(input->OnEvent(Event::Character('X'))); + EXPECT_EQ(content, "axyz\nefgX"); +} + } // namespace ftxui