Add a keyboard shortcut to select the word under cursor in TextEdit
This also acts as a general-purpose "deselect" shortcut since pressing it a second time will deselect text. This is available both in the script editor and in TextEdit fields in use, both in the editor and projects. The Duplicate Line script editor shortcut was moved to Ctrl + Shift + D since it conflicts with the new shortcut (Ctrl + D). The rationale for doing so is that Duplicate Line is a less commonly used action, and its behavior can be replicated by copying and pasting the current line anyway. (With no selection active, the whole line will be copied.)
This commit is contained in:
parent
de4c17f716
commit
80f4e407b2
|
@ -353,6 +353,7 @@ static const _BuiltinActionDisplayName _builtin_action_display_names[] = {
|
||||||
{ "ui_text_scroll_down", TTRC("Scroll Down") },
|
{ "ui_text_scroll_down", TTRC("Scroll Down") },
|
||||||
{ "ui_text_scroll_down.OSX", TTRC("Scroll Down") },
|
{ "ui_text_scroll_down.OSX", TTRC("Scroll Down") },
|
||||||
{ "ui_text_select_all", TTRC("Select All") },
|
{ "ui_text_select_all", TTRC("Select All") },
|
||||||
|
{ "ui_text_select_word_under_caret", TTRC("Select Word Under Caret") },
|
||||||
{ "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") },
|
{ "ui_text_toggle_insert_mode", TTRC("Toggle Insert Mode") },
|
||||||
{ "ui_graph_duplicate", TTRC("Duplicate Nodes") },
|
{ "ui_graph_duplicate", TTRC("Duplicate Nodes") },
|
||||||
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
{ "ui_graph_delete", TTRC("Delete Nodes") },
|
||||||
|
@ -650,6 +651,10 @@ const OrderedHashMap<String, List<Ref<InputEvent>>> &InputMap::get_builtins() {
|
||||||
inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CMD));
|
inputs.push_back(InputEventKey::create_reference(KEY_A | KEY_MASK_CMD));
|
||||||
default_builtin_cache.insert("ui_text_select_all", inputs);
|
default_builtin_cache.insert("ui_text_select_all", inputs);
|
||||||
|
|
||||||
|
inputs = List<Ref<InputEvent>>();
|
||||||
|
inputs.push_back(InputEventKey::create_reference(KEY_D | KEY_MASK_CMD));
|
||||||
|
default_builtin_cache.insert("ui_text_select_word_under_caret", inputs);
|
||||||
|
|
||||||
inputs = List<Ref<InputEvent>>();
|
inputs = List<Ref<InputEvent>>();
|
||||||
inputs.push_back(InputEventKey::create_reference(KEY_INSERT));
|
inputs.push_back(InputEventKey::create_reference(KEY_INSERT));
|
||||||
default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs);
|
default_builtin_cache.insert("ui_text_toggle_insert_mode", inputs);
|
||||||
|
|
|
@ -732,6 +732,10 @@
|
||||||
</member>
|
</member>
|
||||||
<member name="input/ui_text_select_all" type="Dictionary" setter="" getter="">
|
<member name="input/ui_text_select_all" type="Dictionary" setter="" getter="">
|
||||||
</member>
|
</member>
|
||||||
|
<member name="input/ui_text_select_word_under_caret" type="Dictionary" setter="" getter="">
|
||||||
|
If no selection is currently active, selects the word currently under the caret in text fields. If a selection is currently active, deselects the current selection.
|
||||||
|
[b]Note:[/b] Currently, this is only implemented in [TextEdit], not [LineEdit].
|
||||||
|
</member>
|
||||||
<member name="input/ui_text_toggle_insert_mode" type="Dictionary" setter="" getter="">
|
<member name="input/ui_text_toggle_insert_mode" type="Dictionary" setter="" getter="">
|
||||||
</member>
|
</member>
|
||||||
<member name="input/ui_undo" type="Dictionary" setter="" getter="">
|
<member name="input/ui_undo" type="Dictionary" setter="" getter="">
|
||||||
|
|
|
@ -1896,7 +1896,7 @@ void ScriptTextEditor::register_editor() {
|
||||||
#ifdef OSX_ENABLED
|
#ifdef OSX_ENABLED
|
||||||
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
|
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_C);
|
||||||
#else
|
#else
|
||||||
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_CMD | KEY_D);
|
ED_SHORTCUT("script_text_editor/clone_down", TTR("Clone Down"), KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_D);
|
||||||
#endif
|
#endif
|
||||||
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E);
|
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_E);
|
||||||
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
|
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KEY_MASK_CMD | KEY_MASK_ALT | KEY_T);
|
||||||
|
|
|
@ -3381,13 +3381,18 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SELECT ALL, CUT, COPY, PASTE.
|
// SELECT ALL, SELECT WORD UNDER CARET, CUT, COPY, PASTE.
|
||||||
|
|
||||||
if (k->is_action("ui_text_select_all", true)) {
|
if (k->is_action("ui_text_select_all", true)) {
|
||||||
select_all();
|
select_all();
|
||||||
accept_event();
|
accept_event();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (k->is_action("ui_text_select_word_under_caret", true)) {
|
||||||
|
select_word_under_caret();
|
||||||
|
accept_event();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (k->is_action("ui_cut", true)) {
|
if (k->is_action("ui_cut", true)) {
|
||||||
cut();
|
cut();
|
||||||
accept_event();
|
accept_event();
|
||||||
|
@ -5149,6 +5154,39 @@ void TextEdit::select_all() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextEdit::select_word_under_caret() {
|
||||||
|
if (!selecting_enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.size() == 1 && text[0].length() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selection.active) {
|
||||||
|
// Allow toggling selection by pressing the shortcut a second time.
|
||||||
|
// This is also usable as a general-purpose "deselect" shortcut after
|
||||||
|
// selecting anything.
|
||||||
|
deselect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int begin = 0;
|
||||||
|
int end = 0;
|
||||||
|
const Vector<Vector2i> words = TS->shaped_text_get_word_breaks(text.get_line_data(cursor.line)->get_rid());
|
||||||
|
for (int i = 0; i < words.size(); i++) {
|
||||||
|
if (words[i].x <= cursor.column && words[i].y >= cursor.column) {
|
||||||
|
begin = words[i].x;
|
||||||
|
end = words[i].y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select(cursor.line, begin, cursor.line, end);
|
||||||
|
// Move the cursor to the end of the word for easier editing.
|
||||||
|
cursor_set_column(end, false);
|
||||||
|
}
|
||||||
|
|
||||||
void TextEdit::deselect() {
|
void TextEdit::deselect() {
|
||||||
selection.active = false;
|
selection.active = false;
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -731,6 +731,7 @@ public:
|
||||||
void copy();
|
void copy();
|
||||||
void paste();
|
void paste();
|
||||||
void select_all();
|
void select_all();
|
||||||
|
void select_word_under_caret();
|
||||||
void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
|
void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
|
||||||
void deselect();
|
void deselect();
|
||||||
void swap_lines(int line1, int line2);
|
void swap_lines(int line1, int line2);
|
||||||
|
|
Loading…
Reference in New Issue