Browse Source

Merge pull request #48739 from Calinou/textedit-add-select-word-under-cursor

Add a keyboard shortcut to select the word under cursor in TextEdit
Rémi Verschelde 4 years ago
parent
commit
45d3b965bb

+ 5 - 0
core/input/input_map.cpp

@@ -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);

+ 4 - 0
doc/classes/ProjectSettings.xml

@@ -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="">

+ 1 - 1
editor/plugins/script_text_editor.cpp

@@ -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);

+ 39 - 1
scene/gui/text_edit.cpp

@@ -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();

+ 1 - 0
scene/gui/text_edit.h

@@ -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);