Skip to content

Commit

Permalink
input: Take care of index and width separately
Browse files Browse the repository at this point in the history
This resolves #26, where inserting into a string outside character
boundary leads to a panic (ref:
https://doc.rust-lang.org/std/string/struct.String.html#method.insert)
""Panics if idx is larger than the String's length, or
if it does not lie on a char boundary.""

We use `char_indices` to find the correct position to insert into
and `unicode_width` crate to find out the width of characters.
  • Loading branch information
fangyi-zhou committed Oct 17, 2019
1 parent 1bdc396 commit 804764d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.8"
dirs = "2.0.2"
clap = "2.33.0"
unicode-width = "0.1.5"

[[bin]]
bench = false
Expand Down
2 changes: 2 additions & 0 deletions src/app.rs
Expand Up @@ -201,6 +201,7 @@ pub struct App {
pub current_playback_context: Option<FullPlayingContext>,
pub devices: Option<DevicePayload>,
pub input: String,
pub input_idx: usize,
pub input_cursor_position: u16,
pub large_search_limit: u32,
pub library: Library,
Expand Down Expand Up @@ -250,6 +251,7 @@ impl App {
current_playback_context: None,
devices: None,
input: String::new(),
input_idx: 0,
input_cursor_position: 0,
playlist_tracks: vec![],
playlists: None,
Expand Down
44 changes: 33 additions & 11 deletions src/handlers/input.rs
@@ -1,28 +1,42 @@
extern crate unicode_width;

use super::super::app::{ActiveBlock, App, RouteId};
use std::convert::TryInto;
use termion::event::Key;
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};

// Handle events when the search input block is active
pub fn handler(key: Key, app: &mut App) {
match key {
Key::Ctrl('u') => {
app.input = String::new();
app.input_idx = 0;
app.input_cursor_position = 0;
}
Key::Ctrl('e') => {
app.input_cursor_position = app.input.len().try_into().unwrap();
app.input_idx = app.input.len();
app.input_cursor_position = UnicodeWidthStr::width(app.input.as_str())
.try_into()
.unwrap();
}
Key::Ctrl('a') => {
app.input_idx = 0;
app.input_cursor_position = 0;
}
Key::Left => {
if !app.input.is_empty() && app.input_cursor_position > 0 {
app.input_cursor_position -= 1;
if !app.input.is_empty() && app.input_idx > 0 {
let last_c = app.input.chars().nth(app.input_idx - 1).unwrap();
app.input_idx -= 1;
let width: u16 = UnicodeWidthChar::width(last_c).unwrap().try_into().unwrap();
app.input_cursor_position -= width;
}
}
Key::Right => {
if app.input_cursor_position < app.input.len().try_into().unwrap() {
app.input_cursor_position += 1;
let next_c = app.input.chars().nth(app.input_idx).unwrap();
app.input_idx += 1;
let width: u16 = UnicodeWidthChar::width(next_c).unwrap().try_into().unwrap();
app.input_cursor_position += width;
}
}
Key::Esc => {
Expand Down Expand Up @@ -94,15 +108,23 @@ pub fn handler(key: Key, app: &mut App) {
}
}
Key::Char(c) => {
app.input
.insert(app.input_cursor_position.try_into().unwrap(), c);
app.input_cursor_position += 1;
let (insert_idx, _) = app
.input
.char_indices()
.nth(app.input_idx)
.unwrap_or((app.input.len(), ' '));
app.input.insert(insert_idx, c);
app.input_idx += 1;
let width: u16 = UnicodeWidthChar::width(c).unwrap().try_into().unwrap();
app.input_cursor_position += width;
}
Key::Backspace => {
if !app.input.is_empty() && app.input_cursor_position > 0 {
app.input
.remove((app.input_cursor_position - 1).try_into().unwrap());
app.input_cursor_position -= 1;
if !app.input.is_empty() && app.input_idx > 0 {
let (remove_idx, last_c) = app.input.char_indices().nth(app.input_idx - 1).unwrap();
app.input_idx -= 1;
app.input.remove(remove_idx);
let width: u16 = UnicodeWidthChar::width(last_c).unwrap().try_into().unwrap();
app.input_cursor_position -= width;
}
}
_ => {}
Expand Down

0 comments on commit 804764d

Please sign in to comment.