Fix cursor position when using multibyte characters

This commit is contained in:
Dheepak Krishnamurthy 2020-11-09 10:09:06 -07:00
parent 79b9f942a9
commit 6b26643fc7
3 changed files with 54 additions and 7 deletions

1
Cargo.lock generated
View file

@ -714,6 +714,7 @@ dependencies = [
"shlex", "shlex",
"task-hookrs", "task-hookrs",
"tui", "tui",
"unicode-segmentation",
"unicode-width", "unicode-width",
"uuid", "uuid",
] ]

View file

@ -28,6 +28,7 @@ rand = "0.7"
shlex = "0.1" shlex = "0.1"
chrono = "0.4" chrono = "0.4"
unicode-width = "0.1" unicode-width = "0.1"
unicode-segmentation = "1.6"
tui = { version = "0.12", optional = true, default-features = false } tui = { version = "0.12", optional = true, default-features = false }
crossterm = { version = "0.17", optional = true, default-features = false } crossterm = { version = "0.17", optional = true, default-features = false }
rustyline = "6.3.0" rustyline = "6.3.0"

View file

@ -20,6 +20,9 @@ use task_hookrs::task::Task;
use task_hookrs::uda::UDAValue; use task_hookrs::uda::UDAValue;
use uuid::Uuid; use uuid::Uuid;
use unicode_segmentation::Graphemes;
use unicode_segmentation::UnicodeSegmentation;
use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone}; use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -283,7 +286,14 @@ impl TTApp {
match self.mode { match self.mode {
AppMode::TaskReport => self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks"), AppMode::TaskReport => self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks"),
AppMode::TaskFilter => { AppMode::TaskFilter => {
f.set_cursor(rects[1].x + self.filter.pos() as u16 + 1, rects[1].y + 1); let mut position = self.filter.as_str().graphemes(true).count();
for (i, (_i, g)) in self.filter.as_str().grapheme_indices(true).enumerate() {
if _i == self.filter.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -293,7 +303,14 @@ impl TTApp {
); );
} }
AppMode::TaskModify => { AppMode::TaskModify => {
f.set_cursor(rects[1].x + self.modify.pos() as u16 + 1, rects[1].y + 1); let mut position = self.modify.as_str().graphemes(true).count();
for (i, (_i, g)) in self.modify.as_str().grapheme_indices(true).enumerate() {
if _i == self.modify.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -306,7 +323,14 @@ impl TTApp {
); );
} }
AppMode::TaskLog => { AppMode::TaskLog => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1); let mut position = self.command.as_str().graphemes(true).count();
for (i, (_i, g)) in self.command.as_str().grapheme_indices(true).enumerate() {
if _i == self.command.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -316,7 +340,14 @@ impl TTApp {
); );
} }
AppMode::TaskSubprocess => { AppMode::TaskSubprocess => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1); let mut position = self.command.as_str().graphemes(true).count();
for (i, (_i, g)) in self.command.as_str().grapheme_indices(true).enumerate() {
if _i == self.command.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -326,7 +357,14 @@ impl TTApp {
); );
} }
AppMode::TaskAnnotate => { AppMode::TaskAnnotate => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1); let mut position = self.command.as_str().graphemes(true).count();
for (i, (_i, g)) in self.command.as_str().grapheme_indices(true).enumerate() {
if _i == self.command.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -339,7 +377,14 @@ impl TTApp {
); );
} }
AppMode::TaskAdd => { AppMode::TaskAdd => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1); let mut position = self.command.as_str().graphemes(true).count();
for (i, (_i, g)) in self.command.as_str().grapheme_indices(true).enumerate() {
if _i == self.command.pos() {
position = i;
break
}
}
f.set_cursor(rects[1].x + position as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]); f.render_widget(Clear, rects[1]);
self.draw_command( self.draw_command(
f, f,
@ -1317,7 +1362,7 @@ impl TTApp {
match self.task_current() { match self.task_current() {
Some(t) => { Some(t) => {
let s = format!("{} ", t.description()); let s = format!("{} ", t.description());
self.modify.update(&s, s.len()) self.modify.update(&s, s.as_str().graphemes(true).count())
} }
None => self.modify.update("", 0), None => self.modify.update("", 0),
} }