mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 20:17:42 +00:00
LibGUI: Unindent selected text on shift+tab press
Selected text is unindented when Shift+Tab is pressed. Select text, indent it with Tab, then unindent with Shift+Tab.
This commit is contained in:
parent
2fbaa7996c
commit
9369610bf4
4 changed files with 63 additions and 0 deletions
|
@ -959,6 +959,35 @@ void IndentSelection::undo()
|
||||||
m_document.set_all_cursors(m_range.start());
|
m_document.set_all_cursors(m_range.start());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UnindentSelection::UnindentSelection(TextDocument& document, size_t tab_width, TextRange const& range)
|
||||||
|
: TextDocumentUndoCommand(document)
|
||||||
|
, m_tab_width(tab_width)
|
||||||
|
, m_range(range)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnindentSelection::redo()
|
||||||
|
{
|
||||||
|
for (size_t i = m_range.start().line(); i <= m_range.end().line(); i++) {
|
||||||
|
if (m_document.line(i).leading_spaces() >= m_tab_width)
|
||||||
|
m_document.remove({ { i, 0 }, { i, m_tab_width } });
|
||||||
|
else
|
||||||
|
m_document.remove({ { i, 0 }, { i, m_document.line(i).leading_spaces() } });
|
||||||
|
}
|
||||||
|
|
||||||
|
m_document.set_all_cursors(m_range.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnindentSelection::undo()
|
||||||
|
{
|
||||||
|
auto const tab = String::repeated(' ', m_tab_width);
|
||||||
|
|
||||||
|
for (size_t i = m_range.start().line(); i <= m_range.end().line(); i++)
|
||||||
|
m_document.insert_at({ i, 0 }, tab, m_client);
|
||||||
|
|
||||||
|
m_document.set_all_cursors(m_range.start());
|
||||||
|
}
|
||||||
|
|
||||||
TextPosition TextDocument::insert_at(TextPosition const& position, StringView text, Client const* client)
|
TextPosition TextDocument::insert_at(TextPosition const& position, StringView text, Client const* client)
|
||||||
{
|
{
|
||||||
TextPosition cursor = position;
|
TextPosition cursor = position;
|
||||||
|
|
|
@ -271,4 +271,16 @@ private:
|
||||||
TextRange m_range;
|
TextRange m_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class UnindentSelection : public TextDocumentUndoCommand {
|
||||||
|
public:
|
||||||
|
UnindentSelection(TextDocument&, size_t tab_width, TextRange const&);
|
||||||
|
virtual void undo() override;
|
||||||
|
virtual void redo() override;
|
||||||
|
TextRange const& range() const { return m_range; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t m_tab_width { 0 };
|
||||||
|
TextRange m_range;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -869,6 +869,10 @@ void TextEditor::keydown_event(KeyEvent& event)
|
||||||
|
|
||||||
if (event.key() == KeyCode::Key_Tab) {
|
if (event.key() == KeyCode::Key_Tab) {
|
||||||
if (has_selection()) {
|
if (has_selection()) {
|
||||||
|
if (event.modifiers() == Mod_Shift) {
|
||||||
|
unindent_selection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (is_indenting_selection()) {
|
if (is_indenting_selection()) {
|
||||||
indent_selection();
|
indent_selection();
|
||||||
return;
|
return;
|
||||||
|
@ -988,6 +992,23 @@ void TextEditor::indent_selection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEditor::unindent_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 (current_line().first_non_whitespace_column() != 0) {
|
||||||
|
if (current_line().first_non_whitespace_column() > m_soft_tab_width && selection_start.column() != 0) {
|
||||||
|
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 });
|
||||||
|
} else if (selection_start.column() != 0) {
|
||||||
|
m_selection.set_start({ selection_start.line(), selection_start.column() - current_line().leading_spaces() });
|
||||||
|
m_selection.set_end({ selection_end.line(), selection_end.column() - current_line().leading_spaces() });
|
||||||
|
}
|
||||||
|
execute<UnindentSelection>(m_soft_tab_width, TextRange(selection_start, selection_end));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TextEditor::delete_previous_word()
|
void TextEditor::delete_previous_word()
|
||||||
{
|
{
|
||||||
TextRange to_erase(document().first_word_before(m_cursor, true), m_cursor);
|
TextRange to_erase(document().first_word_before(m_cursor, true), m_cursor);
|
||||||
|
|
|
@ -153,6 +153,7 @@ public:
|
||||||
virtual void redo();
|
virtual void redo();
|
||||||
bool is_indenting_selection();
|
bool is_indenting_selection();
|
||||||
void indent_selection();
|
void indent_selection();
|
||||||
|
void unindent_selection();
|
||||||
|
|
||||||
Function<void()> on_change;
|
Function<void()> on_change;
|
||||||
Function<void(bool modified)> on_modified_change;
|
Function<void(bool modified)> on_modified_change;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue