Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Fix prompt for multi-byte characters. #41

Merged
merged 2 commits into from
Apr 4, 2024
Merged

Conversation

frederictobiasc
Copy link
Contributor

Before this contribution, entering characters that consists of multiple bytes lead to undesired behaviour such as panics.
This results from the position previous position handling inside the prompt.
The String::len() returns the size of the string in bytes. Since a single unicode scalar value may consist of multiple bytes, this is not useful to determine the position inside the prompt. The panic occured in the State::push() method and resulted from the attempt to insert at a byte index that does not represent a character boundary.
See:
https://doc.rust-lang.org/stable/std/primitive.str.html#method.len https://doc.rust-lang.org/stable/std/string/struct.String.html#method.insert

Fixes #40

Copy link
Owner

@joshka joshka left a comment

Choose a reason for hiding this comment

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

Thanks for fixing this. There's a couple of small things to fix if you don't mind.

src/prompt.rs Outdated
Comment on lines 165 to 170
*self.value_mut() = self
.value()
.chars()
.take(self.position())
.chain(std::iter::once(c).chain(self.value().chars().skip(self.position())))
.collect();
Copy link
Owner

Choose a reason for hiding this comment

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

#The following is a bit easier to read (uses the Itertools::chain macro):

Suggested change
*self.value_mut() = self
.value()
.chars()
.take(self.position())
.chain(std::iter::once(c).chain(self.value().chars().skip(self.position())))
.collect();
*self.value_mut() = chain![
self.value().chars().take(self.position()),
once(c),
self.value().chars().skip(self.position())
]
.collect();

Also a small comment here about why this is necessary would be handy for a future reader to understand the intent.

Comment on lines 96 to 116
#[test]
fn multi_byte_characters() {
let mut test = TextState::new();
test.push('Ö');
test.push('a');
}
Copy link
Owner

Choose a reason for hiding this comment

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

Can you please add a couple of tests to cover insertion at the start, middle and end, and assert the expected values of each?

src/prompt.rs Outdated
@@ -114,23 +114,23 @@ pub trait State {

fn delete(&mut self) {
let position = self.position();
if position == self.value().len() {
if position == self.value().chars().count() {
Copy link
Owner

Choose a reason for hiding this comment

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

What about extracting this to a function named len()?

@frederictobiasc
Copy link
Contributor Author

frederictobiasc commented Apr 4, 2024

Hi, thanks for your quick response! I addressed your review and rebased.
There are, however, two tests that fail:

    text_prompt::tests::draw_no_wrap
    text_prompt::tests::draw_wrapped

Edit: During investigation, I just noticed they fail as well on the current main, so that's unrelated to my PR.

Before this contribution, entering characters that consists of multiple
bytes lead to undesired behaviour such as panics.
This results from the position previous position handling inside the
prompt.
The String::len() returns the size of the string in bytes. Since a
single unicode scalar value may consist of multiple bytes, this is not
useful to determine the position inside the prompt.
The panic occured in the State::push() method and resulted from the
attempt to insert at a byte index that does not represent a character
boundary.
See:
https://doc.rust-lang.org/stable/std/primitive.str.html#method.len
https://doc.rust-lang.org/stable/std/string/struct.String.html#method.insert
@joshka
Copy link
Owner

joshka commented Apr 4, 2024

There are, however, two tests that fail:

I've been meaning to look at them but haven't done so yet: joshka/tui-widgets#9

Copy link
Owner

@joshka joshka left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for fixing this up!

@joshka joshka merged commit 79b32d4 into joshka:main Apr 4, 2024
10 of 11 checks passed
@github-actions github-actions bot mentioned this pull request Apr 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multi-Byte-Characters
2 participants