-
Notifications
You must be signed in to change notification settings - Fork 25
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
Implement IME primitives for PlainEditor. #136
base: main
Are you sure you want to change the base?
Conversation
#[derive(Clone, Default)] | ||
struct ComposeState { | ||
selection: Option<(usize, usize)>, | ||
text: Arc<str>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this should be a String
. Then:
- We could mutate it and re-use the allocation when updating the pre-edit
- Setting it to empty would be allocation free
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Setting it to empty would be allocation free
it may not matter, but it's never empty
examples/vello_editor/src/text.rs
Outdated
// Winit on some platforms delivers an empty Preedit after Commit | ||
// so don't lock into compose when preedit is empty. | ||
Ime::Preedit(text, None) if text.is_empty() => vec![ | ||
PlainEditorOp::SetCompose("".into(), None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A dedicated ClearCompose
Op for setting to empty might be nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's fair, and definitely the ergonomic choice when moving to methods instead of ops.
9a6f8f6
to
d400210
Compare
parley/src/layout/editor.rs
Outdated
CommitCompose => { | ||
if let Some(ComposeState { text, .. }) = self.compose.clone() { | ||
let new_insert = self.selection.insertion_index() + text.len(); | ||
self.selection = if new_insert == self.buffer.len() { | ||
Selection::from_index( | ||
&self.layout, | ||
new_insert.saturating_sub(1), | ||
Affinity::Upstream, | ||
) | ||
} else { | ||
Selection::from_index(&self.layout, new_insert, Affinity::Downstream) | ||
}; | ||
} | ||
self.compose = None; | ||
layout_after = true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may not matter too much, but this does some additional work on each commit, as Winit delivers a Preedit("", None)
before sending Commit
. On commit, vello_editor in this PR currently clears the compose state, to immediately set it again, to then commit it. If CommitCompose
takes the committed text, some of those buffer operations become unnecessary.
There also appear to be some IMEs that commit without going into compose first, so perhaps it makes sense to have SetCompose(Arc<str>, Option<(usize, usize)>)
, ClearCompose
, and Commit(Arc<str>)
.
Commit(Arc<str>)
would guarantee it also clears the compose state. Otherwise it's effectively the same as InsertOrReplaceSelection(Arc<str>)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, that will be the final command set as it has been requested by both you and Nico, and it clearly makes sense.
b8c7909
to
3ce25f2
Compare
3ce25f2
to
c151875
Compare
No description provided.