Commit 0c8ffc76 authored by Daniel García Moreno's avatar Daniel García Moreno

autocomplete: Code cleanup, remove all unwraps

I've removed all unwraps that can be removed, managing the result of all
of that with the ?  operator and using the std::option::Option type.

This way we'll avoid crashes, because an unmanaged unwrap can cause a
crash so we need to check this always.

I've also removed the unicode-segmentation depencency. We can use the
.chars iterators and it seems to work correctly.
parent 586e401f
...@@ -408,7 +408,6 @@ dependencies = [ ...@@ -408,7 +408,6 @@ dependencies = [
"serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
......
...@@ -21,7 +21,6 @@ serde_json = "1.0.16" ...@@ -21,7 +21,6 @@ serde_json = "1.0.16"
url = "1.7.0" url = "1.7.0"
rand = "0.4.2" rand = "0.4.2"
html2pango = { git = "https://gitlab.gnome.org/World/html2pango" } html2pango = { git = "https://gitlab.gnome.org/World/html2pango" }
unicode-segmentation = "1.2.0"
comrak = "0.2" comrak = "0.2"
# newer stuff do not compile inside flatpak # newer stuff do not compile inside flatpak
......
extern crate gtk; extern crate gtk;
extern crate pango; extern crate pango;
extern crate gdk; extern crate gdk;
extern crate unicode_segmentation;
use self::unicode_segmentation::UnicodeSegmentation;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::collections::HashMap; use std::collections::HashMap;
...@@ -65,27 +62,33 @@ impl Autocomplete { ...@@ -65,27 +62,33 @@ impl Autocomplete {
let own = this.clone(); let own = this.clone();
this.borrow().entry.connect_property_cursor_position_notify(move |w| { this.borrow().entry.connect_property_cursor_position_notify(move |w| {
if let Ok(item) = own.try_borrow() { if let Ok(item) = own.try_borrow() {
let input = w.get_text().unwrap(); if let Some(input) = w.get_text() {
let attr = item.add_highlight(input); if let Some(attr) = item.add_highlight(input) {
w.set_attributes(&attr); w.set_attributes(&attr);
}
}
} }
}); });
let own = this.clone(); let own = this.clone();
this.borrow().entry.connect_property_selection_bound_notify(move |w| { this.borrow().entry.connect_property_selection_bound_notify(move |w| {
if let Ok(item) = own.try_borrow() { if let Ok(item) = own.try_borrow() {
let input = w.get_text().unwrap(); if let Some(input) = w.get_text() {
let attr = item.add_highlight(input); if let Some(attr) = item.add_highlight(input) {
w.set_attributes(&attr); w.set_attributes(&attr);
}
}
} }
}); });
let own = this.clone(); let own = this.clone();
this.borrow().entry.connect_changed(move |w| { this.borrow().entry.connect_changed(move |w| {
if let Ok(item) = own.try_borrow() { if let Ok(item) = own.try_borrow() {
let input = w.get_text().unwrap(); if let Some(input) = w.get_text() {
let attr = item.add_highlight(input); if let Some(attr) = item.add_highlight(input) {
w.set_attributes(&attr); w.set_attributes(&attr);
}
}
} }
}); });
...@@ -118,9 +121,12 @@ impl Autocomplete { ...@@ -118,9 +121,12 @@ impl Autocomplete {
this.borrow().entry.connect_key_press_event(move |w, ev| { this.borrow().entry.connect_key_press_event(move |w, ev| {
match ev.get_keyval() { match ev.get_keyval() {
gdk::enums::key::BackSpace => { gdk::enums::key::BackSpace => {
if w.get_text().is_none() || w.get_text().unwrap() == "" { match w.get_text() {
own.borrow_mut().autocomplete_enter(); Some(ref t) if t == "" => { own.borrow_mut().autocomplete_enter(); }
} None => { own.borrow_mut().autocomplete_enter(); }
_ => { }
};
return glib::signal::Inhibit(false); return glib::signal::Inhibit(false);
}, },
/* Tab and Enter key */ /* Tab and Enter key */
...@@ -178,7 +184,7 @@ impl Autocomplete { ...@@ -178,7 +184,7 @@ impl Autocomplete {
return Inhibit(false); return Inhibit(false);
} }
} }
/* allow popover opening with tab /* allow popover opening with tab
* don't update popover when the input didn't change */ * don't update popover when the input didn't change */
if !is_tab { if !is_tab {
if let Some(ref text) = text { if let Some(ref text) = text {
...@@ -196,14 +202,14 @@ impl Autocomplete { ...@@ -196,14 +202,14 @@ impl Autocomplete {
own.borrow_mut().popover_search = text.clone(); own.borrow_mut().popover_search = text.clone();
let pos = e.get_position(); let pos = e.get_position();
if let Some(text) = text.clone() { if let Some(text) = text.clone() {
let graphs = UnicodeSegmentation::graphemes(text.as_str(), true).collect::<Vec<&str>>(); let graphs = text.chars().collect::<Vec<char>>();
if pos as usize > graphs.len() { if pos as usize > graphs.len() {
return Inhibit(false); return Inhibit(false);
} }
let (p1, _) = graphs.split_at(pos as usize); let (p1, _) = graphs.split_at(pos as usize);
let first = p1.join(""); let first = p1.into_iter().collect::<String>();
if own.borrow().popover_position.is_none() { if own.borrow().popover_position.is_none() {
if !is_tab { if !is_tab {
if let Some(at_pos) = first.rfind("@") { if let Some(at_pos) = first.rfind("@") {
...@@ -270,40 +276,43 @@ impl Autocomplete { ...@@ -270,40 +276,43 @@ impl Autocomplete {
* because the ui changes from others are blocked as long we hold the look */ * because the ui changes from others are blocked as long we hold the look */
if let Some(input) = self.entry.get_text() { if let Some(input) = self.entry.get_text() {
self.highlighted_entry.push(alias); self.highlighted_entry.push(alias);
let attr = self.add_highlight(input); if let Some(attr) = self.add_highlight(input) {
self.entry.set_attributes(&attr); self.entry.set_attributes(&attr);
}
} }
} }
} }
pub fn autocomplete_enter(&mut self) -> bool { pub fn autocomplete_enter(&mut self) -> bool {
if let Some(input) = self.entry.get_text() { if let Some(input) = self.entry.get_text() {
let attr = self.add_highlight(input); if let Some(attr) = self.add_highlight(input) {
self.entry.set_attributes(&attr); self.entry.set_attributes(&attr);
}
} }
self.popover_position = None; self.popover_position = None;
self.popover_search = None; self.popover_search = None;
let visible = self.popover.is_visible(); let visible = self.popover.is_visible();
self.popover.popdown(); self.popover.popdown();
return visible;
visible
} }
pub fn add_highlight(&self, input: String) -> pango::AttrList { pub fn add_highlight(&self, input: String) -> Option<pango::AttrList> {
fn contains((start, end): (i32, i32), item: i32) -> bool { fn contains((start, end): (i32, i32), item: i32) -> bool {
if start <= end { match start <= end {
return start <= item && end > item; true => start <= item && end > item,
} else { false => start <= item || end > item,
return start <= item || end > item;
} }
} }
let input = input.to_lowercase(); let input = input.to_lowercase();
let bounds = self.entry.get_selection_bounds(); let bounds = self.entry.get_selection_bounds();
let context = gtk::Widget::get_style_context (&self.entry.clone().upcast::<gtk::Widget>()).unwrap(); let context = gtk::Widget::get_style_context (&self.entry.clone().upcast::<gtk::Widget>())?;
let fg = gtk::StyleContext::lookup_color (&context, "theme_selected_bg_color").unwrap(); let fg = gtk::StyleContext::lookup_color (&context, "theme_selected_bg_color")?;
let red = fg.red * 65535. + 0.5; let red = fg.red * 65535. + 0.5;
let green = fg.green * 65535. + 0.5; let green = fg.green * 65535. + 0.5;
let blue = fg.blue * 65535. + 0.5; let blue = fg.blue * 65535. + 0.5;
let color = pango::Attribute::new_foreground(red as u16, green as u16, blue as u16).unwrap(); let color = pango::Attribute::new_foreground(red as u16, green as u16, blue as u16)?;
let attr = pango::AttrList::new(); let attr = pango::AttrList::new();
for (_, alias) in self.highlighted_entry.iter().enumerate() { for (_, alias) in self.highlighted_entry.iter().enumerate() {
...@@ -313,7 +322,7 @@ impl Autocomplete { ...@@ -313,7 +322,7 @@ impl Autocomplete {
let mut found = false; let mut found = false;
while input.contains(alias) { while input.contains(alias) {
let pos = { let pos = {
let start = input.find(alias).unwrap() as i32; let start = input.find(alias)? as i32;
(start, start + alias.len() as i32) (start, start + alias.len() as i32)
}; };
let mut color = color.clone(); let mut color = color.clone();
...@@ -333,12 +342,12 @@ impl Autocomplete { ...@@ -333,12 +342,12 @@ impl Autocomplete {
attr.insert(color); attr.insert(color);
} else { } else {
/* The alias starts inside a selection */ /* The alias starts inside a selection */
if contains(bounds.unwrap(), mark_start) { if contains(bounds?, mark_start) {
final_pos = Some((bounds_end, final_pos.unwrap().1)); final_pos = Some((bounds_end, final_pos?.1));
} }
/* The alias ends inside a selection */ /* The alias ends inside a selection */
if contains(bounds.unwrap(), mark_end - 1) { if contains(bounds?, mark_end - 1) {
final_pos = Some((final_pos.unwrap().0, bounds_start)); final_pos = Some((final_pos?.0, bounds_start));
} }
} }
} }
...@@ -361,7 +370,7 @@ impl Autocomplete { ...@@ -361,7 +370,7 @@ impl Autocomplete {
} }
} }
return attr; Some(attr)
} }
pub fn autocomplete_arrow(&mut self, direction: i32) -> Option<gtk::Widget> { pub fn autocomplete_arrow(&mut self, direction: i32) -> Option<gtk::Widget> {
...@@ -374,12 +383,12 @@ impl Autocomplete { ...@@ -374,12 +383,12 @@ impl Autocomplete {
None => { None => {
if let Some(row) = self.listbox.get_row_at_index(0) { if let Some(row) = self.listbox.get_row_at_index(0) {
self.listbox.select_row(&row); self.listbox.select_row(&row);
result = Some(row.get_children().first().unwrap().clone()); result = Some(row.get_children().first()?.clone());
} }
} }
Some(row) => { Some(row) => {
self.listbox.select_row(&row); self.listbox.select_row(&row);
result = Some(row.get_children().first().unwrap().clone()); result = Some(row.get_children().first()?.clone());
} }
}; };
} }
...@@ -387,7 +396,7 @@ impl Autocomplete { ...@@ -387,7 +396,7 @@ impl Autocomplete {
if let Some(row) = self.listbox.get_children().last() { if let Some(row) = self.listbox.get_children().last() {
if let Ok(row) = row.clone().downcast::<gtk::ListBoxRow>() { if let Ok(row) = row.clone().downcast::<gtk::ListBoxRow>() {
self.listbox.select_row(&row); self.listbox.select_row(&row);
result = Some(row.get_children().first().unwrap().clone()); result = Some(row.get_children().first()?.clone());
} }
} }
} }
...@@ -395,7 +404,7 @@ impl Autocomplete { ...@@ -395,7 +404,7 @@ impl Autocomplete {
else { else {
if let Some(row) = self.listbox.get_row_at_index(0) { if let Some(row) = self.listbox.get_row_at_index(0) {
self.listbox.select_row(&row); self.listbox.select_row(&row);
result = Some(row.get_children().first().unwrap().clone()); result = Some(row.get_children().first()?.clone());
} }
} }
return result; return result;
...@@ -430,12 +439,13 @@ impl Autocomplete { ...@@ -430,12 +439,13 @@ impl Autocomplete {
if let Some(text_index) = self.popover_position { if let Some(text_index) = self.popover_position {
let offset = self.entry.get_layout_offsets().0; let offset = self.entry.get_layout_offsets().0;
let layout = self.entry.get_layout().unwrap(); if let Some(layout) = self.entry.get_layout() {
let layout_index = self.entry.text_index_to_layout_index(text_index); let layout_index = self.entry.text_index_to_layout_index(text_index);
let (_, index) = layout.get_cursor_pos(layout_index); let (_, index) = layout.get_cursor_pos(layout_index);
pango::extents_to_pixels(Some(&index), None); pango::extents_to_pixels(Some(&index), None);
self.popover.set_pointing_to(&gdk::Rectangle{x: index.x + offset + 10, y: 0, width: 0, height: 0}); self.popover.set_pointing_to(&gdk::Rectangle{x: index.x + offset + 10, y: 0, width: 0, height: 0});
}
} }
if let Some(row) = self.listbox.get_row_at_index(0) { if let Some(row) = self.listbox.get_row_at_index(0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment