1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13:38:11 +00:00

LibGUI: Indent selected text on tab press

If selected text is less than a whole line, usual delete/replace takes
place. Otherwise, if the selected text is a whole line or spans
multiple lines, the selection will be indented.
This commit is contained in:
huttongrabiel 2022-06-18 12:02:51 -07:00 committed by Sam Atkins
parent 80705a72bd
commit 2fbaa7996c
4 changed files with 80 additions and 2 deletions

View file

@ -867,6 +867,15 @@ void TextEditor::keydown_event(KeyEvent& event)
return;
}
if (event.key() == KeyCode::Key_Tab) {
if (has_selection()) {
if (is_indenting_selection()) {
indent_selection();
return;
}
}
}
if (event.key() == KeyCode::Key_Delete) {
if (!is_editable())
return;
@ -952,6 +961,33 @@ void TextEditor::keydown_event(KeyEvent& event)
event.ignore();
}
bool TextEditor::is_indenting_selection()
{
auto const selection_start = m_selection.start() > m_selection.end() ? m_selection.end() : m_selection.start();
auto const selection_end = m_selection.end() > m_selection.start() ? m_selection.end() : m_selection.start();
auto const whole_line_selected = selection_end.column() - selection_start.column() >= current_line().length() - current_line().first_non_whitespace_column();
auto const on_same_line = selection_start.line() == selection_end.line();
if (has_selection() && (whole_line_selected || !on_same_line)) {
return true;
}
return false;
}
void TextEditor::indent_selection()
{
auto const selection_start = m_selection.start() > m_selection.end() ? m_selection.end() : m_selection.start();
auto const selection_end = m_selection.end() > m_selection.start() ? m_selection.end() : m_selection.start();
if (is_indenting_selection()) {
execute<IndentSelection>(m_soft_tab_width, TextRange(selection_start, selection_end));
m_selection.set_start({ selection_start.line(), selection_start.column() + m_soft_tab_width });
m_selection.set_end({ selection_end.line(), selection_end.column() + m_soft_tab_width });
set_cursor({ m_cursor.line(), m_cursor.column() + m_soft_tab_width });
}
}
void TextEditor::delete_previous_word()
{
TextRange to_erase(document().first_word_before(m_cursor, true), m_cursor);
@ -1444,7 +1480,7 @@ void TextEditor::insert_at_cursor_or_replace_selection(StringView text)
{
ReflowDeferrer defer(*this);
VERIFY(is_editable());
if (has_selection())
if (has_selection() && !is_indenting_selection())
delete_selection();
// Check if adding a newline leaves the previous line as just whitespace.
@ -1453,7 +1489,8 @@ void TextEditor::insert_at_cursor_or_replace_selection(StringView text)
&& clear_length > 0
&& current_line().leading_spaces() == clear_length;
execute<InsertTextCommand>(text, m_cursor);
if (!is_indenting_selection())
execute<InsertTextCommand>(text, m_cursor);
if (should_clear_last_line) { // If it does leave just whitespace, clear it.
auto const original_cursor_position = cursor();