Skip to content

Commit 504f430

Browse files
committed
fix: delete and backspace behavior for multi-byte characters (#57)
Fixes: joshka/tui-prompts#56
1 parent d3de6d0 commit 504f430

File tree

2 files changed

+79
-14
lines changed

2 files changed

+79
-14
lines changed

tui-prompts/src/prompt.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,24 @@ pub trait State {
131131
if position == self.len() {
132132
return;
133133
}
134-
self.value_mut().remove(position);
134+
*self.value_mut() = chain!(
135+
self.value().chars().take(position),
136+
self.value().chars().skip(position + 1)
137+
)
138+
.collect();
135139
}
136140

137141
fn backspace(&mut self) {
138-
let position = self.position().saturating_sub(1);
139-
if position == self.len() {
142+
let position = self.position();
143+
if position == 0 {
140144
return;
141145
}
142-
*self.position_mut() = position;
143-
self.value_mut().remove(position);
146+
*self.value_mut() = chain!(
147+
self.value().chars().take(position.saturating_sub(1)),
148+
self.value().chars().skip(position)
149+
)
150+
.collect();
151+
*self.position_mut() = position.saturating_sub(1);
144152
}
145153

146154
fn move_right(&mut self) {

tui-prompts/src/text_state.rs

+66-9
Original file line numberDiff line numberDiff line change
@@ -95,23 +95,80 @@ mod tests {
9595

9696
#[test]
9797
fn insert_multibyte_start() {
98-
let mut test = TextState::new().with_value("ää");
98+
let mut test = TextState::new().with_value("äë");
9999
test.move_start();
100-
test.push('Ö');
101-
assert_eq!(test.value(), "Öää");
100+
test.push('Ï');
101+
assert_eq!(test.value(), "Ïäë");
102+
assert_eq!(test.position(), 1);
102103
}
103104
#[test]
104105
fn insert_multibyte_middle() {
105-
let mut test = TextState::new().with_value("ää");
106+
let mut test = TextState::new().with_value("äë");
106107
test.move_right();
107-
test.push('Ö');
108-
assert_eq!(test.value(), "äÖä");
108+
test.push('Ï');
109+
assert_eq!(test.value(), "äÏë");
110+
assert_eq!(test.position(), 2);
109111
}
110112
#[test]
111113
fn insert_multibyte_end() {
112-
let mut test = TextState::new().with_value("ää");
114+
let mut test = TextState::new().with_value("äë");
113115
test.move_end();
114-
test.push('Ö');
115-
assert_eq!(test.value(), "ääÖ");
116+
test.push('Ï');
117+
assert_eq!(test.value(), "äëÏ");
118+
assert_eq!(test.position(), 3);
119+
}
120+
121+
#[test]
122+
fn delete_multibyte_start() {
123+
let mut test = TextState::new().with_value("äë");
124+
test.move_start();
125+
test.delete();
126+
assert_eq!(test.value(), "ë");
127+
assert_eq!(test.position(), 0);
128+
}
129+
130+
#[test]
131+
fn delete_multibyte_middle() {
132+
let mut test = TextState::new().with_value("äë");
133+
test.move_right();
134+
test.delete();
135+
assert_eq!(test.value(), "ä");
136+
assert_eq!(test.position(), 1);
137+
}
138+
139+
#[test]
140+
fn delete_multibyte_end() {
141+
let mut test = TextState::new().with_value("äë");
142+
test.move_end();
143+
test.delete();
144+
assert_eq!(test.value(), "äë");
145+
assert_eq!(test.position(), 2);
146+
}
147+
148+
#[test]
149+
fn backspace_multibyte_start() {
150+
let mut test = TextState::new().with_value("äë");
151+
test.move_start();
152+
test.backspace();
153+
assert_eq!(test.value(), "äë");
154+
assert_eq!(test.position(), 0);
155+
}
156+
157+
#[test]
158+
fn backspace_multibyte_middle() {
159+
let mut test = TextState::new().with_value("äë");
160+
test.move_right();
161+
test.backspace();
162+
assert_eq!(test.value(), "ë");
163+
assert_eq!(test.position(), 0);
164+
}
165+
166+
#[test]
167+
fn backspace_multibyte_end() {
168+
let mut test = TextState::new().with_value("äë");
169+
test.move_end();
170+
test.backspace();
171+
assert_eq!(test.value(), "ä");
172+
assert_eq!(test.position(), 1);
116173
}
117174
}

0 commit comments

Comments
 (0)