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

Auto indent change if selection is linewise #7316

Merged
merged 9 commits into from
Jul 11, 2023

Conversation

Tudyx
Copy link
Contributor

@Tudyx Tudyx commented Jun 11, 2023

This make c auto indent if the selection begins by a whole line.

I inspired from the other functions in command.rs. I'm not sure if the implementation is very good, all the text editing functions in the code base are new to me.

Resolve #4507 #2783

before after
before_1 before_1
before_2 after_2

This also works if multiple lines are selected. Otherwise it behaves exactly as before.

Why not use a custom key bindings for this?

For me if you select a whole line and go to insert mod with c, you want the auto indentation behavior all of the time.

This is also consistent with the Vim V c or cc behavior.

This PR aims to be a QOL improvement, in the same spirit than #5837

Copy link
Member

@pascalkuthe pascalkuthe left a comment

Choose a reason for hiding this comment

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

I like the general utility and I think @archseer had something similar in mind. However, I think the details should be improved: The current implementation doesn't work with multi cursors. Changing that should be easy (just perform the check for all selection ranges). I also think that the condition should be more strict: We should only insert a new line if the selections exactly covers 1 line (and not just when it starts at a line start)

@danillos
Copy link
Contributor

danillos commented Jun 12, 2023

I took some time to be used to the newline char and when it is selected and hit c it would change the char. Like it does currently.

If sometimes it doesn't happens, the editor will not following a standard.

I would prefer to add this as default or something like it:

m = { l = ["extend_to_line_bounds", "trim_selections"] }

or mil mal

@Tudyx
Copy link
Contributor Author

Tudyx commented Jun 12, 2023

Thanks to your advice, I added support with multi-cursors.
I've also been stricter about the required condition, the selection may only contain whole lines. I didn't restrict to one line in particular because, in my opinion, we want this behavior even with multiple lines:

before after
multi_line_1 multi_line_1
multi_line_2_before multi_line_2_after

@Tudyx
Copy link
Contributor Author

Tudyx commented Jun 12, 2023

I found another implementation that is simpler and handles more edge case using trim_selections:

fn delete_selection_impl(cx: &mut Context, op: Operation) {
    let (view, doc) = current!(cx.editor);

    let selection = doc.selection(view.id);

    if cx.register != Some('_') {
        // first yank the selection
        let text = doc.text().slice(..);
        let values: Vec<String> = selection.fragments(text).map(Cow::into_owned).collect();
        let reg_name = cx.register.unwrap_or('"');
        cx.editor.registers.write(reg_name, values);
    };

    if matches!(op, Operation::Change) {
        trim_selections(cx);
    }

    let (view, doc) = current!(cx.editor);
    let selection = doc.selection(view.id);
    // then delete
    let transaction =
        Transaction::delete_by_selection(doc.text(), selection, |range| (range.from(), range.to()));
    doc.apply(&transaction, view.id);

    match op {
        Operation::Delete => {
            // exit select mode, if currently in select mode
            exit_select_mode(cx);
        }
        Operation::Change => {
            enter_insert_mode(cx);
        }
    }
}

The current implementation with multiple cursors doesn't work if at least one selection doesn't cover a whole line, but this one does.
I've made sure that the buffer we still store the none-trimmed version.
What do you think?

@the-mikedavis
Copy link
Member

Isn't that the same as using trim_selections (_) and then c? IMO this should either be done explicitly (i.e. _c) or with a custom keybind rather than built in to c.

@clo4
Copy link
Contributor

clo4 commented Jun 13, 2023

I agree in principle, _c is only one more keystroke and there's huge value in the consistency helix currently has. Although I think there's probably more value in making the default keybinds as ergonomic as possible. Most of the time _c is what I want to do. Vim makes the same choice with cc and S for good reason.

Maybe a solution is to implement the default c binding in terms of a new command, and keep change_selection as it is to (1) give people the option to use the current behavior and (2) avoid potentially breaking people's keybinds?

@pascalkuthe
Copy link
Member

I like the idea of introducing a new command. I think while this command is a bit less consistent than the current binding I think this is such a common usecase that it's worth introducing. Regarding the new implementation you posted I think I prefer the current implementation. xc acting the same as xdo makes sense to me. x_c leaves training whitepaces and leading whitespace that were added manually (that the user likely wants to remove, think a weidly formatted macro being replaced with normal code).

@Tudyx
Copy link
Contributor Author

Tudyx commented Jun 13, 2023

Thanks for your feedback, I will implement it as a new command then.

@Tudyx
Copy link
Contributor Author

Tudyx commented Jun 14, 2023

I've implemented as a new command. I've also added a "no yank" version, as it also exists for the previous change command.

If you want to try it out, please add this to your config:

[keys.normal]
"c" = "change_selection_with_indent"
[keys.select]
"c" = "change_selection_with_indent"

@kirawi kirawi added the A-helix-term Area: Helix term improvements label Jun 15, 2023
@pascalkuthe
Copy link
Member

This looks good to me for the most part but I prefer a better name for the command. I think we can make this the default mapping too

@the-mikedavis
Copy link
Member

Actually I think just having the one command (change_selection) is ok. The current change_selection command is effectively equivalent to di so restoring the existing behavior is as easy as binding those two commands or typing them out fully in the cases where you don't want the indentation.

I've tinkered around with c while thinking about this change. In my own workflows/muscle-memory I almost never use c across lines/blocks: I always insert new stuff and then delete the old. Trying out some refactors and intentionally using c though, I can see the motivation for this change. In general I don't like adding too much nuanced behavior to commands because I think it can make them unpredictable when you have multiple selections all over a file, but I think I'm ok with it in this scenario 👍

@pascalkuthe pascalkuthe added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. A-command Area: Commands and removed A-helix-term Area: Helix term improvements labels Jun 20, 2023
@pascalkuthe pascalkuthe added S-waiting-on-review Status: Awaiting review from a maintainer. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 21, 2023
pascalkuthe
pascalkuthe previously approved these changes Jun 21, 2023
helix-term/src/commands.rs Outdated Show resolved Hide resolved
helix-term/src/commands.rs Outdated Show resolved Hide resolved
helix-term/src/commands.rs Outdated Show resolved Hide resolved
@pascalkuthe pascalkuthe added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from a maintainer. labels Jun 21, 2023
@archseer archseer added this to the next milestone Jul 11, 2023
@pascalkuthe pascalkuthe added S-waiting-on-review Status: Awaiting review from a maintainer. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 11, 2023
@the-mikedavis the-mikedavis changed the title Auto indent change if selection begins by a whole line Auto indent change if selection is linewise Jul 11, 2023
@the-mikedavis the-mikedavis merged commit 9893a1f into helix-editor:master Jul 11, 2023
6 checks passed
mtoohey31 pushed a commit to mtoohey31/helix that referenced this pull request Jun 2, 2024
smortime pushed a commit to smortime/helix that referenced this pull request Jul 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-command Area: Commands S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants