Skip to content

Commit abea158

Browse files
committed
Merge pull request godotengine#66553 from PucklaJ/duplicate_lines
Add Duplicate Lines shortcut to CodeTextEditor
2 parents 467038d + b3d7f66 commit abea158

11 files changed

Lines changed: 174 additions & 0 deletions

File tree

doc/classes/CodeEdit.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,12 @@
152152
Perform an indent as if the user activated the "ui_text_indent" action.
153153
</description>
154154
</method>
155+
<method name="duplicate_lines">
156+
<return type="void" />
157+
<description>
158+
Duplicates all lines currently selected with any caret. Duplicates the entire line beneath the current one no matter where the caret is within the line.
159+
</description>
160+
</method>
155161
<method name="fold_all_lines">
156162
<return type="void" />
157163
<description>

editor/code_editor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,11 @@ void CodeTextEditor::input(const Ref<InputEvent> &event) {
805805
accept_event();
806806
return;
807807
}
808+
if (ED_IS_SHORTCUT("script_text_editor/duplicate_lines", key_event)) {
809+
text_editor->duplicate_lines();
810+
accept_event();
811+
return;
812+
}
808813
}
809814

810815
void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {

editor/plugins/script_text_editor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,9 @@ void ScriptTextEditor::_edit_option(int p_op) {
13061306
case EDIT_DUPLICATE_SELECTION: {
13071307
code_editor->duplicate_selection();
13081308
} break;
1309+
case EDIT_DUPLICATE_LINES: {
1310+
code_editor->get_text_editor()->duplicate_lines();
1311+
} break;
13091312
case EDIT_TOGGLE_FOLD_LINE: {
13101313
int previous_line = -1;
13111314
for (int caret_idx : tx->get_caret_index_edit_order()) {
@@ -2173,6 +2176,7 @@ void ScriptTextEditor::_enable_code_editor() {
21732176
edit_menu->get_popup()->add_separator();
21742177
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_select_all"), EDIT_SELECT_ALL);
21752178
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
2179+
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_lines"), EDIT_DUPLICATE_LINES);
21762180
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/evaluate_selection"), EDIT_EVALUATE);
21772181
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_word_wrap"), EDIT_TOGGLE_WORD_WRAP);
21782182
edit_menu->get_popup()->add_separator();
@@ -2395,6 +2399,8 @@ void ScriptTextEditor::register_editor() {
23952399
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), Key::NONE);
23962400
ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::SHIFT | KeyModifierMask::CTRL | Key::D);
23972401
ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KeyModifierMask::SHIFT | KeyModifierMask::META | Key::C);
2402+
ED_SHORTCUT("script_text_editor/duplicate_lines", TTR("Duplicate Lines"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::DOWN);
2403+
ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_lines", "macos", KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::DOWN);
23982404
ED_SHORTCUT("script_text_editor/evaluate_selection", TTR("Evaluate Selection"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::SHIFT | Key::E);
23992405
ED_SHORTCUT("script_text_editor/toggle_word_wrap", TTR("Toggle Word Wrap"), KeyModifierMask::ALT | Key::Z);
24002406
ED_SHORTCUT("script_text_editor/trim_trailing_whitespace", TTR("Trim Trailing Whitespace"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::T);

editor/plugins/script_text_editor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class ScriptTextEditor : public ScriptEditorBase {
126126
EDIT_UNINDENT,
127127
EDIT_DELETE_LINE,
128128
EDIT_DUPLICATE_SELECTION,
129+
EDIT_DUPLICATE_LINES,
129130
EDIT_PICK_COLOR,
130131
EDIT_TO_UPPERCASE,
131132
EDIT_TO_LOWERCASE,

editor/plugins/text_editor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,9 @@ void TextEditor::_edit_option(int p_op) {
392392
case EDIT_DUPLICATE_SELECTION: {
393393
code_editor->duplicate_selection();
394394
} break;
395+
case EDIT_DUPLICATE_LINES: {
396+
code_editor->get_text_editor()->duplicate_lines();
397+
} break;
395398
case EDIT_TOGGLE_FOLD_LINE: {
396399
int previous_line = -1;
397400
for (int caret_idx : tx->get_caret_index_edit_order()) {
@@ -651,6 +654,7 @@ TextEditor::TextEditor() {
651654
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/unfold_all_lines"), EDIT_UNFOLD_ALL_LINES);
652655
edit_menu->get_popup()->add_separator();
653656
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
657+
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_lines"), EDIT_DUPLICATE_LINES);
654658
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_word_wrap"), EDIT_TOGGLE_WORD_WRAP);
655659
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/trim_trailing_whitespace"), EDIT_TRIM_TRAILING_WHITESAPCE);
656660
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/convert_indent_to_spaces"), EDIT_CONVERT_INDENT_TO_SPACES);

editor/plugins/text_editor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class TextEditor : public ScriptEditorBase {
7171
EDIT_UNINDENT,
7272
EDIT_DELETE_LINE,
7373
EDIT_DUPLICATE_SELECTION,
74+
EDIT_DUPLICATE_LINES,
7475
EDIT_TO_UPPERCASE,
7576
EDIT_TO_LOWERCASE,
7677
EDIT_CAPITALIZE,

editor/plugins/text_shader_editor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,9 @@ void TextShaderEditor::_menu_option(int p_option) {
671671
case EDIT_DUPLICATE_SELECTION: {
672672
shader_editor->duplicate_selection();
673673
} break;
674+
case EDIT_DUPLICATE_LINES: {
675+
shader_editor->get_text_editor()->duplicate_lines();
676+
} break;
674677
case EDIT_TOGGLE_WORD_WRAP: {
675678
TextEdit::LineWrappingMode wrap = shader_editor->get_text_editor()->get_line_wrapping_mode();
676679
shader_editor->get_text_editor()->set_line_wrapping_mode(wrap == TextEdit::LINE_WRAPPING_BOUNDARY ? TextEdit::LINE_WRAPPING_NONE : TextEdit::LINE_WRAPPING_BOUNDARY);
@@ -1122,6 +1125,7 @@ TextShaderEditor::TextShaderEditor() {
11221125
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/delete_line"), EDIT_DELETE_LINE);
11231126
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_comment"), EDIT_TOGGLE_COMMENT);
11241127
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_selection"), EDIT_DUPLICATE_SELECTION);
1128+
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/duplicate_lines"), EDIT_DUPLICATE_LINES);
11251129
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("script_text_editor/toggle_word_wrap"), EDIT_TOGGLE_WORD_WRAP);
11261130
edit_menu->get_popup()->add_separator();
11271131
edit_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("ui_text_completion_query"), EDIT_COMPLETE);

editor/plugins/text_shader_editor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class TextShaderEditor : public MarginContainer {
120120
EDIT_UNINDENT,
121121
EDIT_DELETE_LINE,
122122
EDIT_DUPLICATE_SELECTION,
123+
EDIT_DUPLICATE_LINES,
123124
EDIT_TOGGLE_WORD_WRAP,
124125
EDIT_TOGGLE_COMMENT,
125126
EDIT_COMPLETE,

scene/gui/code_edit.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,6 +2399,68 @@ void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
23992399
}
24002400
}
24012401

2402+
/* Text manipulation */
2403+
void CodeEdit::duplicate_lines() {
2404+
begin_complex_operation();
2405+
2406+
Vector<int> caret_edit_order = get_caret_index_edit_order();
2407+
for (const int &caret_index : caret_edit_order) {
2408+
// The text that will be inserted. All lines in one string.
2409+
String insert_text;
2410+
2411+
// The new line position of the caret after the operation.
2412+
int new_caret_line = get_caret_line(caret_index);
2413+
// The new column position of the caret after the operation.
2414+
int new_caret_column = get_caret_column(caret_index);
2415+
// The caret positions of the selection. Stays -1 if there is no selection.
2416+
int select_from_line = -1;
2417+
int select_to_line = -1;
2418+
int select_from_column = -1;
2419+
int select_to_column = -1;
2420+
// Number of lines of the selection.
2421+
int select_num_lines = -1;
2422+
2423+
if (has_selection(caret_index)) {
2424+
select_from_line = get_selection_from_line(caret_index);
2425+
select_to_line = get_selection_to_line(caret_index);
2426+
select_from_column = get_selection_from_column(caret_index);
2427+
select_to_column = get_selection_to_column(caret_index);
2428+
select_num_lines = select_to_line - select_from_line + 1;
2429+
2430+
for (int i = select_from_line; i <= select_to_line; i++) {
2431+
insert_text += "\n" + get_line(i);
2432+
unfold_line(i);
2433+
}
2434+
new_caret_line = select_to_line + select_num_lines;
2435+
} else {
2436+
insert_text = "\n" + get_line(new_caret_line);
2437+
new_caret_line++;
2438+
2439+
unfold_line(get_caret_line(caret_index));
2440+
}
2441+
2442+
// The text will be inserted at the end of the current line.
2443+
set_caret_column(get_line(get_caret_line(caret_index)).length(), false, caret_index);
2444+
2445+
deselect(caret_index);
2446+
2447+
insert_text_at_caret(insert_text, caret_index);
2448+
set_caret_line(new_caret_line, false, true, 0, caret_index);
2449+
set_caret_column(new_caret_column, true, caret_index);
2450+
2451+
if (select_from_line != -1) {
2452+
// Advance the selection by the number of duplicated lines.
2453+
select_from_line += select_num_lines;
2454+
select_to_line += select_num_lines;
2455+
2456+
select(select_from_line, select_from_column, select_to_line, select_to_column, caret_index);
2457+
}
2458+
}
2459+
2460+
end_complex_operation();
2461+
queue_redraw();
2462+
}
2463+
24022464
/* Visual */
24032465
Color CodeEdit::_get_brace_mismatch_color() const {
24042466
return theme_cache.brace_mismatch_color;
@@ -2598,6 +2660,9 @@ void CodeEdit::_bind_methods() {
25982660

25992661
ClassDB::bind_method(D_METHOD("set_symbol_lookup_word_as_valid", "valid"), &CodeEdit::set_symbol_lookup_word_as_valid);
26002662

2663+
/* Text manipulation */
2664+
ClassDB::bind_method(D_METHOD("duplicate_lines"), &CodeEdit::duplicate_lines);
2665+
26012666
/* Inspector */
26022667
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symbol_lookup_on_click"), "set_symbol_lookup_on_click_enabled", "is_symbol_lookup_on_click_enabled");
26032668
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "line_folding"), "set_line_folding_enabled", "is_line_folding_enabled");

scene/gui/code_edit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,9 @@ class CodeEdit : public TextEdit {
486486

487487
void set_symbol_lookup_word_as_valid(bool p_valid);
488488

489+
/* Text manipulation */
490+
void duplicate_lines();
491+
489492
CodeEdit();
490493
~CodeEdit();
491494
};

0 commit comments

Comments
 (0)