From 2f8c7b1b3094811d61b439f15b272b3a3a09d7f9 Mon Sep 17 00:00:00 2001 From: Snow Date: Fri, 2 Dec 2022 16:14:57 +0800 Subject: LibGUI: Add shortcut for inserting new line This adds shortcut for inserting a new empty indented line above/below current cursor position. - for inserting line below. - for inserting line above. --- Userland/Libraries/LibGUI/TextDocument.cpp | 49 ++++++++++++++++++++++++++++++ Userland/Libraries/LibGUI/TextDocument.h | 21 +++++++++++++ Userland/Libraries/LibGUI/TextEditor.cpp | 11 +++++++ 3 files changed, 81 insertions(+) (limited to 'Userland/Libraries') diff --git a/Userland/Libraries/LibGUI/TextDocument.cpp b/Userland/Libraries/LibGUI/TextDocument.cpp index abe9f2b33e..e238660af7 100644 --- a/Userland/Libraries/LibGUI/TextDocument.cpp +++ b/Userland/Libraries/LibGUI/TextDocument.cpp @@ -919,6 +919,55 @@ void RemoveTextCommand::undo() m_document.set_all_cursors(new_cursor); } +InsertLineCommand::InsertLineCommand(TextDocument& document, TextPosition cursor, DeprecatedString&& text, InsertPosition pos) + : TextDocumentUndoCommand(document) + , m_cursor(cursor) + , m_text(move(text)) + , m_pos(pos) +{ +} + +void InsertLineCommand::redo() +{ + size_t line_number = compute_line_number(); + m_document.insert_line(line_number, make(m_document, m_text)); + m_document.set_all_cursors(TextPosition { line_number, m_document.line(line_number).length() }); +} + +void InsertLineCommand::undo() +{ + size_t line_number = compute_line_number(); + m_document.remove_line(line_number); + m_document.set_all_cursors(m_cursor); +} + +size_t InsertLineCommand::compute_line_number() const +{ + if (m_pos == InsertPosition::Above) + return m_cursor.line(); + + if (m_pos == InsertPosition::Below) + return m_cursor.line() + 1; + + VERIFY_NOT_REACHED(); +} + +DeprecatedString InsertLineCommand::action_text() const +{ + StringBuilder action_text_builder; + action_text_builder.append("Insert Line"sv); + + if (m_pos == InsertPosition::Above) { + action_text_builder.append(" (Above)"sv); + } else if (m_pos == InsertPosition::Below) { + action_text_builder.append(" (Below)"sv); + } else { + VERIFY_NOT_REACHED(); + } + + return action_text_builder.to_deprecated_string(); +} + ReplaceAllTextCommand::ReplaceAllTextCommand(GUI::TextDocument& document, DeprecatedString const& text, GUI::TextRange const& range, DeprecatedString const& action_text) : TextDocumentUndoCommand(document) , m_text(text) diff --git a/Userland/Libraries/LibGUI/TextDocument.h b/Userland/Libraries/LibGUI/TextDocument.h index c26bad0890..912354f04d 100644 --- a/Userland/Libraries/LibGUI/TextDocument.h +++ b/Userland/Libraries/LibGUI/TextDocument.h @@ -246,6 +246,27 @@ private: TextRange m_range; }; +class InsertLineCommand : public TextDocumentUndoCommand { +public: + enum class InsertPosition { + Above, + Below, + }; + + InsertLineCommand(TextDocument&, TextPosition, DeprecatedString&&, InsertPosition); + virtual ~InsertLineCommand() = default; + virtual void undo() override; + virtual void redo() override; + virtual DeprecatedString action_text() const override; + +private: + size_t compute_line_number() const; + + TextPosition m_cursor; + DeprecatedString m_text; + InsertPosition m_pos; +}; + class ReplaceAllTextCommand final : public GUI::TextDocumentUndoCommand { public: diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp index 617a73e5b1..dd3e3be72d 100644 --- a/Userland/Libraries/LibGUI/TextEditor.cpp +++ b/Userland/Libraries/LibGUI/TextEditor.cpp @@ -890,6 +890,17 @@ void TextEditor::keydown_event(KeyEvent& event) try_update_autocomplete(); } }; + if (is_multi_line() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_Return) { + if (!is_editable()) + return; + + size_t indent_length = current_line().leading_spaces(); + DeprecatedString indent = current_line().to_utf8().substring(0, indent_length); + auto insert_pos = event.shift() ? InsertLineCommand::InsertPosition::Above : InsertLineCommand::InsertPosition::Below; + execute(m_cursor, move(indent), insert_pos); + return; + } + if (is_multi_line() && !event.shift() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_Space) { if (m_autocomplete_provider) { try_show_autocomplete(UserRequestedAutocomplete::Yes); -- cgit v1.2.3