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 ability to select and cut text in the input buffer #689

Merged
merged 6 commits into from
Jan 17, 2024

Conversation

Tastaturtaste
Copy link
Contributor

Addresses issue nushell/nushell#380.

All CutXXX commands like "CutFromStart" or "CutWordLeft" should use the OS copy/paste buffer not an internal buffer

This is already the case if the crate is compiled with the feature system_clipboard. This is, afaik, not (yet) done for nushell.

Copy link

codecov bot commented Dec 27, 2023

Codecov Report

Attention: 268 lines in your changes are missing coverage. Please review.

Comparison is base (dc27ed8) 49.32% compared to head (39ba732) 49.69%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     nushell/nushell#689      +/-   ##
==========================================
+ Coverage   49.32%   49.69%   +0.37%     
==========================================
  Files          46       46              
  Lines        7998     8433     +435     
==========================================
+ Hits         3945     4191     +246     
- Misses       4053     4242     +189     
Files Coverage Δ
src/edit_mode/emacs.rs 93.85% <100.00%> (+0.22%) ⬆️
src/edit_mode/keybindings.rs 92.59% <100.00%> (+3.86%) ⬆️
src/edit_mode/vi/parser.rs 96.10% <ø> (ø)
src/edit_mode/vi/vi_keybindings.rs 100.00% <100.00%> (ø)
src/painting/styled_text.rs 61.65% <98.34%> (+61.65%) ⬆️
src/edit_mode/vi/command.rs 29.76% <0.00%> (-1.11%) ⬇️
src/core_editor/line_buffer.rs 87.69% <0.00%> (-1.94%) ⬇️
src/engine.rs 5.08% <6.66%> (+0.10%) ⬆️
src/enums.rs 16.86% <2.32%> (-2.61%) ⬇️
src/edit_mode/vi/motion.rs 38.63% <21.42%> (-5.49%) ⬇️
... and 1 more

src/core_editor/editor.rs Outdated Show resolved Hide resolved
@fdncred
Copy link
Collaborator

fdncred commented Dec 27, 2023

This looks like a promising start. Is it enabled in any of the reedline demos so we can try it out?

@Tastaturtaste
Copy link
Contributor Author

You can try it out in the basic example of reedline. It is not gated behind a feature. But if you want to use Ctrl+V you have to compile with feature system_clipboard, at least on windows.

@fdncred
Copy link
Collaborator

fdncred commented Dec 27, 2023

Hmmm, I'm on macos and can't get it to work. I compiled with cargo run --examples basic --features=system_clipboard. I tried Ctrl+A, Shift+Left, Shift+Right and I'm not getting any selection.

@Tastaturtaste
Copy link
Contributor Author

Tastaturtaste commented Dec 27, 2023

I have not yet implemented highlighting of the selection. If you hold down Shift and move the cursor to over text and afterwards press Ctrl + X you should have the text in the clipboard. At least pasting inside the terminal again worked without problem for me.

Edit: I just tested pasting outside of the terminal, that works for me, too.

@fdncred
Copy link
Collaborator

fdncred commented Dec 27, 2023

oh, i see. seems to work great with that little tidbit. 😆 thanks.

@amtoine amtoine changed the title "Added ability to select and cut text in the input buffer" Add ability to select and cut text in the input buffer Dec 27, 2023
@Tastaturtaste Tastaturtaste marked this pull request as ready for review December 28, 2023 21:12
@Tastaturtaste
Copy link
Contributor Author

Is there anything left to do before you can consider to merge it? The two failing clippy lints are not related to the code I touched, so I don't know what to do about them...

@fdncred
Copy link
Collaborator

fdncred commented Jan 6, 2024

Just change the code like the clippy lints suggest, replacing .get(0) with .first(). The CI needs to be green prior to landing.

Do you plan on making a PR for nushell based on this PR?

@Tastaturtaste
Copy link
Contributor Author

Do you plan on making a PR for nushell based on this PR?

Yeah, that was my plan

@fdncred
Copy link
Collaborator

fdncred commented Jan 6, 2024

I'd like to know/see what changes are required in nushell before landing this.

@fdncred
Copy link
Collaborator

fdncred commented Jan 13, 2024

I've looked over this several times now and I'm about ready to land it. I see you have a builder pattern to implement it in nushell (and others). How are you feeling about this PR/Do you still have things you want to do or are you ready?

@Tastaturtaste
Copy link
Contributor Author

Tastaturtaste commented Jan 13, 2024

I see you have a builder pattern to implement it in nushell

Yes, that should work just like any other EditCommand. However, the bindings Ctrl + C and Ctrl + A are used in the default config.nu for cancel_command and move_to_line_start respectively. I don't know how a differentiation between Ctrl + C to cancel a operation and Ctrl + C to copy a selection could be handled. Maybe there is some way to see if currently some text is selected and treat it as a copy command and otherwise as a cancel command?

How are you feeling about this PR/Do you still have things you want to do or are you ready?

Actually, I am currently working on making selection an option for all of the previously existing move commands. This should afford much more flexibility and I believe is better extensible.
Please take a look if you think this would be beneficial. I think it is an improvement.

@fdncred
Copy link
Collaborator

fdncred commented Jan 14, 2024

Would you mind talking a bit about how the selection, etc works in relation to graphemes? Seems like we have a lot of grapheme work here but I'm not sure all that is accommodated in your new code or not and I'd hate to break that type of thing.

@Tastaturtaste
Copy link
Contributor Author

Of course, I will try to give a brief summary of the selection logic and how it relates to grapheme boundaries.

Any EditCommand of the MoveCursor type carries with it a parameter specifying if the move should select text that is moved over. This works as follows:

  1. The Editor has a field selection_anchor of type Option<usize>, which tracks if a selection is currently happening, and if so, it carries the index of one end of the selected range into the line_buffer. The other end of the selected range is marked by the current cursor position.
  2. When a EditCommand with a selection request (select == true) is processed, a check is made if we previously already started selecting text (indicated by Some(usize) in selection_anchor). If yes, the selection_anchor remains set as it is. If no, it is set to the current cursor position before moving the cursor.
  3. When an EditCommand is processed that does anything else than select text by moving the cursor the selection_anchor is reset to None.

By this logic, the selection_anchor can only contain indices that were previously also cursor positions. Assuming

  1. Cursor positions are always valid indices at grapheme boundaries
  2. All commands that modify the line buffer also reset the selection_anchor

the indices bracketing the selected text in the line buffer are always valid indices at grapheme boundaries.
Assumption 2. is given because all MoveCursor edit commands do not modify the line buffer and conceptually probably never should. However, this could be a maintenance hazard if somehow a MoveCursor command with select == true were added that does modify the line buffer. This hazard could be contained if mutable access to the line_buffer would always have to be done through a custom type or function that could then make sure to always reset the selection_anchor.

@fdncred
Copy link
Collaborator

fdncred commented Jan 14, 2024

Thanks so much for the detailed explanation ❤️. It seems like we'd want to remove this maintenance hazard if we could, although I believe that to be outside the scope of this PR.

@fdncred
Copy link
Collaborator

fdncred commented Jan 17, 2024

ok, let's go with this then!

@fdncred fdncred merged commit 2f3eb3e into nushell:main Jan 17, 2024
8 checks passed
@fdncred
Copy link
Collaborator

fdncred commented Jan 17, 2024

now you can update your nushell PR and we can troubleshoot there. hopefully we don't have to come back here to make any changes.

fdncred pushed a commit to nushell/nushell that referenced this pull request Jan 20, 2024
This PR should close #1171

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
This PR introduces the capability to select text using the existing
move.. `EditCommand`s of `reedline`. Those commands are extended with an
optional parameter specifying if text should be selected while
navigating. This enables a workflow familiar from a wide variety of text
editors, where holding `shift` while navigating selects all text between
the initial cursor position when pressing `shift` and the current cursor
position.

Before this PR can be merged the [sibling PR for
reedline](nushell/reedline#689) has to land
first.

# User-Facing Changes
## Additional `EditCommand`s
1. `SelectAll`
2. `CutSelection`
3. `CopySelection`
## New optional parameter on existing `EditCommand`s
All `EditCommand`s of `EditType` `MoveCursor` have a new optional
parameter named `select` of type `bool`. If this parameter is not set by
a user it is treated as false, which corresponds to their behavior up to
now.

I am relatively new to `nushell` and as such may not know of existing
behavior that might change through this PR. However, I believe there
should be none. I come to this conclusion because
1. Existing commands are extended only with an *optional* additional
parameter, users who currently use these EditCommands keep their
existing behavior if they don't use it.
2. A few new commands are introduced which were previously not valid.
3. The default keybindings specified in `default_config.nu` are
untouched.

# Tests + Formatting
Tests for the new optional parameter for the move commands are included
to make sure that they truly are optional and an unused optional
parameter conforms to the previous behavior.
@fdncred
Copy link
Collaborator

fdncred commented Feb 7, 2024

@Tastaturtaste when you have a minute, could you help us figure out why these cut/copy/select_all/paste keybindings are not working in nushell when it's launched with nu -n?

@Tastaturtaste
Copy link
Contributor Author

I will have to see if I get to it tomorrow.

@Tastaturtaste
Copy link
Contributor Author

Hmm, I just cloned a fresh copy of nushell and tried to reproduce the commands not working. But for me everything works as expected. Just to be sure I did the right steps to reproduce:

git clone https://github.com/nushell/nushell.git
cd nushell
cargo run -- -n
<Test commands here>

Are there specific steps to reproduce the issue?

@fdncred
Copy link
Collaborator

fdncred commented Feb 8, 2024

@amtoine can you comment on this?

@Tastaturtaste It works on flawlessly on Windows for me with nu -n or nu -n --no-std-lib. I was having problems on mac. I can test there later. I'll try ubuntu on WSL and see in a minute.

@fdncred
Copy link
Collaborator

fdncred commented Feb 8, 2024

@Tastaturtaste on WSL Ubuntu, when I typed shift left-arrow I got this. Note that this happens when I accept an item out of my history. e.g. i typed nu and the history hint was nu -c "def table [] { \"hi\" }; table" so I right-arrowed to complete it, hit left-arrow once to get inside the trailing double quote, then hit shift left-arrow for the crash.
image

with full backtrace
image

@Tastaturtaste
Copy link
Contributor Author

Tastaturtaste commented Feb 8, 2024

I can't take a closer look today, but will look into it in the next few days. Sadly my weekend is packed already, so maybe after that.

The backtrace gives a good hint already. Somewhere in reedline::painting::styled_text::StyledText::style_range the indexing of the styled buffer (or rather of one styled fragment of the buffer) goes wrong. The idea in that function is to store each continuous fragment of the buffer with the same style as a pair of String and Style. When something is selected the style has to be updated to show the selection effect.

I can reproduce the crash with a shorter prompt on windows:

  1. Type cargo run (do not press enter)
  2. press left once (cursor is now between u and n
  3. press shift + left

Edit: Or rather a crash in that function. I get a

.../reedline-0.29.0\src\painting\styled_text.rs:61:58:
attempt to subtract with overflow

Seems I botched some logic in that function :/

@fdncred
Copy link
Collaborator

fdncred commented Feb 8, 2024

@Tastaturtaste Sounds good. We appreciate your help whenever you can get to it!

@kubouch
Copy link
Contributor

kubouch commented Feb 8, 2024

@Tastaturtaste Could you put that panic with repro steps in a separate issue and slap the "Critical" label on it? So that we can track easier in case you won't have time in the next few days.

@fdncred
Copy link
Collaborator

fdncred commented Feb 9, 2024

I think this is a similar panic in nushell #750

@Tastaturtaste
Copy link
Contributor Author

Tastaturtaste commented Feb 12, 2024

#689 (comment)
I got this fixed on this branch. Now I need to try and reproduce the error @fdncred mentions. Please also try my fixed branch on your machine.

@Tastaturtaste
Copy link
Contributor Author

@Tastaturtaste on WSL Ubuntu, when I typed shift left-arrow I got this. Note that this happens when I accept an item out of my history. e.g. i typed nu and the history hint was nu -c "def table [] { \"hi\" }; table" so I right-arrowed to complete it, hit left-arrow once to get inside the trailing double quote, then hit shift left-arrow for the crash. image

with full backtrace image

I reproduced the error on WSL. The fix for my subtraction with overflow error also fixes this one. Unless someone says otherwise I consider this bug fixed with #751.

@fdncred
Copy link
Collaborator

fdncred commented Feb 12, 2024

Thanks @Tastaturtaste. Do you have a nushell branch that I can easily test this in? I'm not quite sure how to reproduce it in reedline. I've tried but can't make it fail.

@Tastaturtaste
Copy link
Contributor Author

I don't have one pushed. Locally I tested with the nushell main branch and set reedshell patch to my git branch. Do you need me to push a nushell branch to test?

@fdncred
Copy link
Collaborator

fdncred commented Feb 12, 2024

Do you need me to push a nushell branch to test?

If it's not too much trouble. It would make it easier for us to test.

@Tastaturtaste
Copy link
Contributor Author

https://github.com/Tastaturtaste/nushell/tree/test-reedline-style-text-fix
Here, have a go. Should I make a quick PR against nushell so you can run CI tests?

@fdncred
Copy link
Collaborator

fdncred commented Feb 12, 2024

Let me try to reproduce the problem and try your branch and see how far that gets. Thanks so much! Gimme a few and I'll ping you back.

@fdncred
Copy link
Collaborator

fdncred commented Feb 12, 2024

Looks like it fixes it to me. Thanks

fdncred added a commit to nushell/nushell that referenced this pull request Feb 12, 2024
# Description

This fixes a panic with the text selection.

Reference
nushell/reedline#751
nushell/reedline#750
nushell/reedline#689 (comment)


# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
dmatos2012 pushed a commit to dmatos2012/nushell that referenced this pull request Feb 20, 2024
This PR should close nushell#1171

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->
This PR introduces the capability to select text using the existing
move.. `EditCommand`s of `reedline`. Those commands are extended with an
optional parameter specifying if text should be selected while
navigating. This enables a workflow familiar from a wide variety of text
editors, where holding `shift` while navigating selects all text between
the initial cursor position when pressing `shift` and the current cursor
position.

Before this PR can be merged the [sibling PR for
reedline](nushell/reedline#689) has to land
first.

# User-Facing Changes
## Additional `EditCommand`s
1. `SelectAll`
2. `CutSelection`
3. `CopySelection`
## New optional parameter on existing `EditCommand`s
All `EditCommand`s of `EditType` `MoveCursor` have a new optional
parameter named `select` of type `bool`. If this parameter is not set by
a user it is treated as false, which corresponds to their behavior up to
now.

I am relatively new to `nushell` and as such may not know of existing
behavior that might change through this PR. However, I believe there
should be none. I come to this conclusion because
1. Existing commands are extended only with an *optional* additional
parameter, users who currently use these EditCommands keep their
existing behavior if they don't use it.
2. A few new commands are introduced which were previously not valid.
3. The default keybindings specified in `default_config.nu` are
untouched.

# Tests + Formatting
Tests for the new optional parameter for the move commands are included
to make sure that they truly are optional and an unused optional
parameter conforms to the previous behavior.
dmatos2012 pushed a commit to dmatos2012/nushell that referenced this pull request Feb 20, 2024
# Description

This fixes a panic with the text selection.

Reference
nushell/reedline#751
nushell/reedline#750
nushell/reedline#689 (comment)


# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
kik4444 pushed a commit to kik4444/nushell-fork that referenced this pull request Feb 28, 2024
# Description

This fixes a panic with the text selection.

Reference
nushell/reedline#751
nushell/reedline#750
nushell/reedline#689 (comment)


# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use std testing; testing run-tests --path
crates/nu-std"` to run the tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants