mirror of
https://github.com/apognu/tuigreet.git
synced 2024-12-02 10:05:01 +03:00
Fix behavior on ^A and unicode support.
^A now correctly takes the user to the beginning of the current field. The strategy initially used for string indexing was pretty naive and did not take Unicode into account (and characters spanning multiple bytes). This would mess up cursor offset calculations and overall string indexing (leading to crashes).
This commit is contained in:
parent
413689bf80
commit
0bd8dde043
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@ -44,6 +44,7 @@ jobs:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- run: rm -rf .git/
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
|
@ -148,8 +148,8 @@ impl Greeter {
|
||||
self.config = match opts.parse(&env::args().collect::<Vec<String>>()) {
|
||||
Ok(matches) => Some(matches),
|
||||
|
||||
Err(usage) => {
|
||||
println!("{}", usage);
|
||||
Err(error) => {
|
||||
println!("{}", error);
|
||||
print_usage(opts);
|
||||
process::exit(1);
|
||||
}
|
||||
|
@ -46,7 +46,15 @@ pub fn handle(greeter: &mut Greeter, events: &Events) -> Result<(), Box<dyn Erro
|
||||
}
|
||||
}
|
||||
|
||||
Key::Ctrl('a') => greeter.cursor_offset = -(greeter.username.len() as i16),
|
||||
Key::Ctrl('a') => {
|
||||
let value = match greeter.mode {
|
||||
Mode::Username => &greeter.username,
|
||||
_ => &greeter.answer,
|
||||
};
|
||||
|
||||
greeter.cursor_offset = -(value.chars().count() as i16);
|
||||
}
|
||||
|
||||
Key::Ctrl('e') => greeter.cursor_offset = 0,
|
||||
|
||||
Key::Char('\n') | Key::Char('\t') => match greeter.mode {
|
||||
@ -102,9 +110,11 @@ fn insert_key(greeter: &mut Greeter, c: char) {
|
||||
Mode::Sessions => return,
|
||||
};
|
||||
|
||||
let index = value.len() as i16 + greeter.cursor_offset;
|
||||
let index = (value.chars().count() as i16 + greeter.cursor_offset) as usize;
|
||||
let left = value.chars().take(index);
|
||||
let right = value.chars().skip(index);
|
||||
|
||||
value.insert(index as usize, c);
|
||||
*value = left.chain(vec![c].into_iter()).chain(right).collect();
|
||||
}
|
||||
|
||||
fn delete_key(greeter: &mut Greeter, key: Key) {
|
||||
@ -116,13 +126,16 @@ fn delete_key(greeter: &mut Greeter, key: Key) {
|
||||
};
|
||||
|
||||
let index = match key {
|
||||
Key::Backspace => value.len() as i16 + greeter.cursor_offset - 1,
|
||||
Key::Delete => value.len() as i16 + greeter.cursor_offset,
|
||||
Key::Backspace => (value.chars().count() as i16 + greeter.cursor_offset - 1) as usize,
|
||||
Key::Delete => (value.chars().count() as i16 + greeter.cursor_offset) as usize,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if value.chars().nth(index as usize).is_some() {
|
||||
value.remove(index as usize);
|
||||
let left = value.chars().take(index);
|
||||
let right = value.chars().skip(index + 1);
|
||||
|
||||
*value = left.chain(right).collect();
|
||||
|
||||
if let Key::Delete = key {
|
||||
greeter.cursor_offset += 1;
|
||||
|
@ -45,7 +45,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
|
||||
f.render_widget(command_label, chunks[0]);
|
||||
f.render_widget(command_value, Rect::new(1 + chunks[0].x + COMMAND.len() as u16, chunks[0].y, get_input_width(greeter, COMMAND), 1));
|
||||
|
||||
let offset = get_cursor_offset(greeter, greeter.new_command.len());
|
||||
let offset = get_cursor_offset(greeter, greeter.new_command.chars().count());
|
||||
|
||||
Ok((2 + cursor.x + COMMAND.len() as u16 + offset as u16, cursor.y + 1))
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
|
||||
f.render_widget(
|
||||
answer_value,
|
||||
Rect::new(
|
||||
chunks[ANSWER_INDEX].x + greeter.prompt.len() as u16,
|
||||
chunks[ANSWER_INDEX].x + greeter.prompt.chars().count() as u16,
|
||||
chunks[ANSWER_INDEX].y,
|
||||
get_input_width(greeter, &greeter.prompt),
|
||||
1,
|
||||
@ -114,18 +114,18 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
|
||||
|
||||
match greeter.mode {
|
||||
Mode::Username => {
|
||||
let offset = get_cursor_offset(greeter, greeter.username.len());
|
||||
let offset = get_cursor_offset(greeter, greeter.username.chars().count());
|
||||
|
||||
Ok((2 + cursor.x + USERNAME.len() as u16 + offset as u16, USERNAME_INDEX as u16 + cursor.y))
|
||||
}
|
||||
|
||||
Mode::Password => {
|
||||
let offset = get_cursor_offset(greeter, greeter.answer.len());
|
||||
let offset = get_cursor_offset(greeter, greeter.answer.chars().count());
|
||||
|
||||
if greeter.secret {
|
||||
Ok((1 + cursor.x + greeter.prompt.len() as u16, ANSWER_INDEX as u16 + prompt_padding + cursor.y))
|
||||
Ok((1 + cursor.x + greeter.prompt.chars().count() as u16, ANSWER_INDEX as u16 + prompt_padding + cursor.y))
|
||||
} else {
|
||||
Ok((1 + cursor.x + greeter.prompt.len() as u16 + offset as u16, ANSWER_INDEX as u16 + prompt_padding + cursor.y))
|
||||
Ok((1 + cursor.x + greeter.prompt.chars().count() as u16 + offset as u16, ANSWER_INDEX as u16 + prompt_padding + cursor.y))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ pub fn get_height(greeter: &Greeter) -> u16 {
|
||||
}
|
||||
|
||||
pub fn get_input_width(greeter: &Greeter, label: &str) -> u16 {
|
||||
greeter.width() - label.len() as u16 - 4 - 1
|
||||
greeter.width() - label.chars().count() as u16 - 4 - 1
|
||||
}
|
||||
|
||||
pub fn get_cursor_offset(greeter: &mut Greeter, length: usize) -> i16 {
|
||||
|
Loading…
Reference in New Issue
Block a user