Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Duplicate Lines shortcut to CodeTextEditor #66553

Merged
merged 1 commit into from
Sep 26, 2023

Conversation

PucklaJ
Copy link
Contributor

@PucklaJ PucklaJ commented Sep 28, 2022

This PR adds the shortcut script_text_editor/duplicate_lines. The default buttons are Ctrl+Alt+Down. For macOS the default buttons are Cmd+Shift+Down. These shortcuts are similiar to the VS Code command editor.action.copyLinesDownAction. If no text is selected it behaves the same as duplicate_selection, but if text is selected it will duplicate the whole lines of the selection.
This also supports multiple carets.

script_text_editor/duplicate_lines:
duplicate_lines_below

script_text_editor/duplicate_selection:
duplicate_selection

@PucklaJ
Copy link
Contributor Author

PucklaJ commented Oct 9, 2022

Added support for multiple carets

@PucklaJ PucklaJ force-pushed the duplicate_lines branch 2 times, most recently from 919f7d7 to e95dc4f Compare October 18, 2022 09:44
@YuriSizov YuriSizov modified the milestones: 4.0, 4.1 Feb 10, 2023
@MewPurPur
Copy link
Contributor

MewPurPur commented Apr 15, 2023

I'll do a code review in a sec, but can you argue for why you think this feature should be added? We don't accept features just because PRs exist for them.

I personally think Ctrl+Shift+D does what I want just fine. If I have no selections, this PR does the same, just adjusts the caret in one of the scenarios. If I want to duplicate multiple lines, I'm just going to do a proper selection with triple-clicking and then dragging to a line's end - both easy and very well-known functionalities.

Copy link
Contributor

@MewPurPur MewPurPur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't tested the feature itself, just a code review.

editor/code_editor.cpp Outdated Show resolved Hide resolved
Comment on lines 1636 to 1489
int select_from_column = -1;
int select_to_column = -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

select_from_column and select_to_column are unnecessary, this is line duplication. You only used this variable once.

Copy link
Contributor Author

@PucklaJ PucklaJ Apr 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to remove them, but when the text gets inserted, the selection gets deleted, which means that I need to store them before changing the caret. And I think that I should transfer the selection to the duplication since it means that you can perform the same duplication multiple times in a row. Which is something I use very often.

editor/code_editor.cpp Outdated Show resolved Hide resolved
editor/code_editor.cpp Outdated Show resolved Hide resolved
Comment on lines 1634 to 1487
int select_from_line = -1;
int select_to_line = -1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't use these much outside of places where has_selection() is checked. You should define them close to the scope where the variables have a meaning.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I put them in their own scope I would need to write duplicate code.

@torcado194
Copy link

I would love this feature. I have never once wanted to duplicate a subsection within a line using a hotkey, especially if that selection spans multiple lines, I couldn't imagine a scenario in which I would want to duplicate that content in-place.
I duplicate lines constantly, duplicating and swapping lines are probably my most used hotkeys aside from undo/redo. Needing to make sure my selections encompass the entirety of the lines I want to duplicate before i'm able to duplicate multiple lines is very tedious, especially with no way to automatically spread selections to the start/end of lines. If a cursor in my multi-cursor selection started in the middle of the line? Now i have to redo the whole selection to move the start point to the beginning of the line.
And a mouse-based alternative isn't ideal. I'm already typing, I want to use the keyboard, not the mouse. At least for something this simple.

@MewPurPur
Copy link
Contributor

MewPurPur commented Apr 16, 2023

@torcado194 That makes sense, I think "Duplicate Lines" is a hard thing to argue against actually. What about this particular implementation, with separate "below" and "above" versions? That's the main part I find unnecessary.

@torcado194
Copy link

I agree, I hardly ever use "duplicate above". "below" is the default direction for the duplicate line action for any editor I use (and is what I'd expect). the "duplicate above" result can be easily substituted using the keyboard by duplicating below and swapping the new selected lines upward, at the cost of additional keystrokes equal to the line count.
but on the other hand the duplicate above and below functions are found in many editors I've used (visual studio and vs code for example)
maybe it's not part of godot's philosophy but I would much rather have more hotkey functions than less, even if they're unassigned by default.

@PucklaJ
Copy link
Contributor Author

PucklaJ commented Apr 17, 2023

What about this particular implementation, with separate "below" and "above" versions?

I tried to recreate the feature from VS Code and there they have both a above and below version. But I agree I hardly use it either.

@PucklaJ
Copy link
Contributor Author

PucklaJ commented Apr 18, 2023

I will merge all commits into one, once you are done reviewing

@YuriSizov YuriSizov requested a review from Paulb23 April 18, 2023 16:11
@akien-mga akien-mga modified the milestones: 4.1, 4.x Jun 19, 2023
@PucklaJ
Copy link
Contributor Author

PucklaJ commented Aug 18, 2023

@MewPurPur @Paulb23 This PR has just been hanging here for quite some time. Can you please finish reviewing it. I would really like it to be merged. I think it adds some good keyboard shortcuts which can really improve your productivity.

@MewPurPur
Copy link
Contributor

I still think it should be just "Duplicate Lines" that does it below, instead of above and below versions. It's not like regular duplicate is "before" and "after" I don't got much else to say, the code to me looks good and my remarks have been clarified or addressed.

@PucklaJ
Copy link
Contributor Author

PucklaJ commented Aug 26, 2023

That said, before this can be merged you need to squash your commits.

Done

I also dropped the commit which replaces the duplicate_selection shortcut so that it doesn't break compatibility.

Copy link
Member

@Paulb23 Paulb23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks fine, few minor comments.

I'm wanting to move things like this into CodeEdit, could then take advantage of unit tests as well. If you fancy doing that :)

text_editor->deselect(caret_index);

text_editor->insert_text_at_caret(insert_text, caret_index);
text_editor->set_caret_line(new_caret_line, true, true, 0, caret_index);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should set adjust_veiwport to false here, and leave it up to set_caret_column

}
}

text_editor->merge_overlapping_carets();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we expecting carets to overlap here?

}

// The text will be inserted at the end of the current line.
text_editor->set_caret_column(text_editor->get_line(text_editor->get_caret_line(caret_index)).length(), true, caret_index);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to adjust_veiwport here either

new_caret_line = select_to_line + select_num_lines;

for (int i = select_from_line; i <= select_to_line; i++) {
text_editor->unfold_line(i);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can unfold in the same loop above

@PucklaJ PucklaJ requested a review from a team as a code owner August 29, 2023 09:49
@PucklaJ
Copy link
Contributor Author

PucklaJ commented Aug 29, 2023

@Paulb23 I moved the code into CodeEdit and then adjusted the code based on your review.

Copy link
Member

@Paulb23 Paulb23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

One small change, could you bind it to to the CodeEdit API? and again would appreciate any unit tests.

scene/gui/code_edit.h Show resolved Hide resolved
@AThousandShips AThousandShips changed the title Add Duplicate Lines Below and Above shortcut to CodeTextEditor Add Duplicate Lines shortcut to CodeTextEditor Sep 3, 2023
@PucklaJ PucklaJ requested a review from a team as a code owner September 16, 2023 05:44
@PucklaJ
Copy link
Contributor Author

PucklaJ commented Sep 16, 2023

@Paulb23 After a rebase and fixing a merge conflict I added unit tests and bound duplicate_lines to the CodeEdit API.

@PucklaJ PucklaJ requested a review from a team as a code owner September 16, 2023 06:04
@@ -2395,6 +2399,8 @@ void ScriptTextEditor::register_editor() {
ED_SHORTCUT("script_text_editor/unfold_all_lines", TTR("Unfold All Lines"), Key::NONE);
ED_SHORTCUT("script_text_editor/duplicate_selection", TTR("Duplicate Selection"), KeyModifierMask::SHIFT | KeyModifierMask::CTRL | Key::D);
ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_selection", "macos", KeyModifierMask::SHIFT | KeyModifierMask::META | Key::C);
ED_SHORTCUT("script_text_editor/duplicate_lines", TTR("Duplicate Lines"), KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::DOWN);
ED_SHORTCUT_OVERRIDE("script_text_editor/duplicate_lines", "macos", KeyModifierMask::CMD_OR_CTRL | KeyModifierMask::ALT | Key::Z);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a common macOS shortcut for this purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. Honestly I just put anything there because it would have been a duplicate otherwise

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to know what's the expected macOS shortcut for this operation (e.g. in VS Code or Xcode). CC @bruvzg @coppolaemilio

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just looked it up. On VS Code its shift+cmd+down

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might work. Seems like we use this mapping but only for PC here, and there's a different override for macOS:

// core/input/input_map.cpp
        inputs = List<Ref<InputEvent>>();
        inputs.push_back(InputEventKey::create_reference(Key::DOWN | KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL));
        default_builtin_cache.insert("ui_text_caret_add_below", inputs);

        inputs = List<Ref<InputEvent>>();
        inputs.push_back(InputEventKey::create_reference(Key::L | KeyModifierMask::SHIFT | KeyModifierMask::CMD_OR_CTRL));
        default_builtin_cache.insert("ui_text_caret_add_below.macos", inputs);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it on macos to cmd_or_ctrl+shift+down

Copy link
Contributor

@YuriSizov YuriSizov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consensus seems to be for this, at a glance the style looks fine.

@YuriSizov
Copy link
Contributor

Could you please squash your commits into one? Make sure that the final commit has a short but descriptive message (the title of this PR is a good option). See this documentation, if you need help with squashing.

@PucklaJ
Copy link
Contributor Author

PucklaJ commented Sep 25, 2023

@YuriSizov @Paulb23 @MewPurPur The commits are squashed. Everything is ready. Thank you for approving this PR.

This keyboard shortcut has been made with inspiration from the VS Code keyboard shortcut editor.action.copyLinesDownAction. It duplicates all selected lines and inserts them below no matter where the caret is within the line.
@akien-mga akien-mga merged commit 1aa2d8b into godotengine:master Sep 26, 2023
15 checks passed
@akien-mga
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants