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

Fix undo/redo for multi byte runes #5010

Merged

Conversation

NicolasPerrenoud
Copy link
Contributor

Description:

The position in entry is the index in a rune slice. But the implementation of the undo/redo use it as an index in a string. This works for runes that are 1 byte long. But It was broken for longer runes.

I fixed the implementation of undo/redo to index a rune slices instead of the string directly

Fixes #5001

Checklist:

  • Tests included.
  • Lint and formatter run with no errors.
  • Tests all pass.

@coveralls
Copy link

coveralls commented Jul 19, 2024

Coverage Status

coverage: 66.054% (+0.03%) from 66.029%
when pulling 411c1e1 on NicolasPerrenoud:fix-undo-with-multi-byte-rune
into d696fdd on fyne-io:develop.

Copy link
Contributor

@dweymouth dweymouth left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for looking into this! One comment for efficiency

widget/entry.go Outdated
@@ -792,7 +790,7 @@ func (e *Entry) Undo() {
}
pos := modify.Position
if modify.Delete {
pos += len(modify.Text)
pos += len([]rune(modify.Text))
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and anywhere else you want the length of a string in runes, it should be more efficient to use utf8.RuneCountInString(modify.Text) which avoids an allocation

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

Thanks so much for this excellent catch.
I wonder if it might be more efficient to store the []rune instead of string in the undo action, and probably could change deleteFromTo to avoid the string conversion as well. Should reduce allocations.

@andydotxyz
Copy link
Member

Please base pull requests off the develop branch, not master.

@NicolasPerrenoud NicolasPerrenoud changed the base branch from master to develop July 26, 2024 14:28
@NicolasPerrenoud
Copy link
Contributor Author

Thank you for your feedback. I implemented your proposals. Also I fixed text replacement that had similar issue.

@@ -2308,12 +2305,14 @@ func (i *entryModifyAction) Redo(s string) string {

// Inserts Text
func (i *entryModifyAction) add(s string) string {
Copy link
Contributor

Choose a reason for hiding this comment

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

We have casting to strings that result in allocations here and in sub now. Would refactoring these to receive and return []rune result in fewer castings still?

Copy link
Member

Choose a reason for hiding this comment

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

It looks like that opens a can of worms. as the undo/redo stack passes it up and down, with the source being Entry.Text which is string. I agree it would be a good improvement but probably could be another PR.

Copy link
Member

@andydotxyz andydotxyz left a comment

Choose a reason for hiding this comment

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

Looks good to me, I think we need @dweymouth OK as well so I dropped a comment in.

@andydotxyz andydotxyz merged commit b1506ae into fyne-io:develop Aug 17, 2024
12 checks passed
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.

Typing Chinese characters in widget.Entry and perform undo/redo crashes the app.
4 participants