mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:27:35 +00:00
LibGUI: Add Ctrl-W to insert mode
In Vim's insert mode, Ctrl-W deletes the word before the cursor, like Ctrl-Backspace. Unlike Ctrl-Backspace, if only whitespace exists between the end of the word and the cursor, the word will be deleted with the whitespace. To do so, this commit introduces two methods: delete_previous_word() for TextEditor and first_word_before() for TextDocument, where the former depends on the latter. delete_previous_word() is then called in VimEditingEngine.
This commit is contained in:
parent
8f01a8b741
commit
808e5e813f
5 changed files with 52 additions and 0 deletions
|
@ -674,6 +674,39 @@ TextPosition TextDocument::first_word_break_after(const TextPosition& position)
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextPosition TextDocument::first_word_before(const TextPosition& position, bool start_at_column_before) const
|
||||||
|
{
|
||||||
|
if (position.column() == 0) {
|
||||||
|
if (position.line() == 0) {
|
||||||
|
return TextPosition(0, 0);
|
||||||
|
}
|
||||||
|
auto previous_line = this->line(position.line() - 1);
|
||||||
|
return TextPosition(position.line() - 1, previous_line.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto target = position;
|
||||||
|
auto line = this->line(target.line());
|
||||||
|
if (target.column() == line.length())
|
||||||
|
start_at_column_before = 1;
|
||||||
|
|
||||||
|
auto nonblank_passed = !is_ascii_blank(line.code_points()[target.column() - start_at_column_before]);
|
||||||
|
while (target.column() > 0) {
|
||||||
|
auto prev_code_point = line.code_points()[target.column() - 1];
|
||||||
|
nonblank_passed |= !is_ascii_blank(prev_code_point);
|
||||||
|
|
||||||
|
if (nonblank_passed && is_ascii_blank(prev_code_point)) {
|
||||||
|
break;
|
||||||
|
} else if (is_ascii_punctuation(prev_code_point)) {
|
||||||
|
target.set_column(target.column() - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.set_column(target.column() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
void TextDocument::undo()
|
void TextDocument::undo()
|
||||||
{
|
{
|
||||||
if (!can_undo())
|
if (!can_undo())
|
||||||
|
|
|
@ -106,6 +106,8 @@ public:
|
||||||
TextPosition first_word_break_before(const TextPosition&, bool start_at_column_before) const;
|
TextPosition first_word_break_before(const TextPosition&, bool start_at_column_before) const;
|
||||||
TextPosition first_word_break_after(const TextPosition&) const;
|
TextPosition first_word_break_after(const TextPosition&) const;
|
||||||
|
|
||||||
|
TextPosition first_word_before(const TextPosition&, bool start_at_column_before) const;
|
||||||
|
|
||||||
void add_to_undo_stack(NonnullOwnPtr<TextDocumentUndoCommand>);
|
void add_to_undo_stack(NonnullOwnPtr<TextDocumentUndoCommand>);
|
||||||
|
|
||||||
bool can_undo() const { return m_undo_stack.can_undo(); }
|
bool can_undo() const { return m_undo_stack.can_undo(); }
|
||||||
|
|
|
@ -883,6 +883,12 @@ void TextEditor::keydown_event(KeyEvent& event)
|
||||||
event.ignore();
|
event.ignore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEditor::delete_previous_word()
|
||||||
|
{
|
||||||
|
TextRange to_erase(document().first_word_before(m_cursor, true), m_cursor);
|
||||||
|
execute<RemoveTextCommand>(document().text_in_range(to_erase), to_erase);
|
||||||
|
}
|
||||||
|
|
||||||
void TextEditor::delete_current_line()
|
void TextEditor::delete_current_line()
|
||||||
{
|
{
|
||||||
if (has_selection())
|
if (has_selection())
|
||||||
|
|
|
@ -135,6 +135,7 @@ public:
|
||||||
void paste();
|
void paste();
|
||||||
void do_delete();
|
void do_delete();
|
||||||
void delete_current_line();
|
void delete_current_line();
|
||||||
|
void delete_previous_word();
|
||||||
void select_all();
|
void select_all();
|
||||||
virtual void undo();
|
virtual void undo();
|
||||||
virtual void redo();
|
virtual void redo();
|
||||||
|
|
|
@ -794,6 +794,16 @@ bool VimEditingEngine::on_key_in_insert_mode(const KeyEvent& event)
|
||||||
if (EditingEngine::on_key(event))
|
if (EditingEngine::on_key(event))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (event.ctrl()) {
|
||||||
|
switch (event.key()) {
|
||||||
|
case KeyCode::Key_W:
|
||||||
|
m_editor->delete_previous_word();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (event.key() == KeyCode::Key_Escape || (event.ctrl() && event.key() == KeyCode::Key_LeftBracket) || (event.ctrl() && event.key() == KeyCode::Key_C)) {
|
if (event.key() == KeyCode::Key_Escape || (event.ctrl() && event.key() == KeyCode::Key_LeftBracket) || (event.ctrl() && event.key() == KeyCode::Key_C)) {
|
||||||
if (m_editor->cursor().column() > 0)
|
if (m_editor->cursor().column() > 0)
|
||||||
move_one_left();
|
move_one_left();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue