Files
wldash/src/launcher.rs
T

183 lines
5.5 KiB
Rust
Raw Normal View History

2019-08-02 15:59:10 +02:00
use crate::buffer::Buffer;
use crate::color::Color;
2019-08-03 10:39:48 +02:00
use crate::draw::{draw_text, draw_text_individual_colors, ROBOTO_REGULAR};
2019-08-02 15:59:10 +02:00
use crate::module::{Input, ModuleImpl};
use std::io::Read;
2019-08-02 19:11:39 +02:00
use std::cmp::Ordering;
2019-08-02 15:59:10 +02:00
use atty::Stream;
use chrono::{DateTime, Local};
use smithay_client_toolkit::keyboard::keysyms;
pub struct Launcher {
options: Vec<String>,
matches: Vec<String>,
cur: String,
offset: usize,
dirty: bool
}
impl Launcher {
pub fn new() -> Result<Launcher, ::std::io::Error> {
if !atty::is(Stream::Stdin) {
let mut inbuf = String::new();
std::io::stdin().read_to_string(&mut inbuf).unwrap();
let options = inbuf.split("\n").into_iter().map(|s| s.to_string()).collect();
Ok(Launcher {
options: options,
matches: vec![],
cur: "".to_string(),
offset: 0,
dirty: true,
})
} else {
Err(::std::io::Error::new(::std::io::ErrorKind::Other, "input is a tty"))
}
}
}
impl ModuleImpl for Launcher {
fn draw(
&self,
buf: &mut Buffer,
bg: &Color,
_time: &DateTime<Local>,
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
buf.memset(bg);
draw_text(
ROBOTO_REGULAR,
&mut buf.subdimensions((0, 0, 128, 32))?,
bg,
2019-08-03 01:03:57 +02:00
&Color::new(0.75, 0.75, 0.75, 1.0),
2019-08-02 15:59:10 +02:00
32.0,
2019-08-02 16:06:51 +02:00
"Run: ",
2019-08-02 15:59:10 +02:00
)?;
let mut x_off: i32 = 0;
let mut width_remaining: i32 = 1280 - 64;
for (idx, m) in self.matches.iter().enumerate() {
let mut b = match buf.subdimensions((64 + x_off as u32, 0, width_remaining as u32, 32)) {
Ok(b) => b,
Err(_) => break,
};
let size = if idx == self.offset && self.cur.len() > 0 {
let l = self.cur.len();
2019-08-02 19:03:40 +02:00
let off = m.to_lowercase().find(&self.cur.to_lowercase()).unwrap();
2019-08-03 10:39:48 +02:00
let mut colors = Vec::with_capacity(m.len());
for pos in 0..m.len() {
if pos >= off && pos < off + l {
colors.push(Color::new(1.0, 1.0, 1.0, 1.0));
} else {
colors.push(Color::new(0.75, 0.75, 0.75, 1.0));
}
}
draw_text_individual_colors(
2019-08-02 15:59:10 +02:00
ROBOTO_REGULAR,
&mut b,
bg,
2019-08-03 10:39:48 +02:00
&colors,
2019-08-02 15:59:10 +02:00
32.0,
2019-08-03 10:39:48 +02:00
&m)?
2019-08-02 15:59:10 +02:00
} else {
draw_text(
ROBOTO_REGULAR,
&mut b,
bg,
&Color::new(0.5, 0.5, 0.5, 1.0),
32.0,
m,
)?
};
x_off += (size.0 + 8) as i32;
width_remaining -= (size.0 + 8) as i32;
if width_remaining < 0 {
break;
}
}
Ok(vec![buf.get_signed_bounds()])
}
fn update(&mut self, _time: &DateTime<Local>, force: bool) -> Result<bool, ::std::io::Error> {
if self.dirty || force {
2019-08-02 19:11:39 +02:00
let mut m = self
2019-08-02 15:59:10 +02:00
.options
.iter()
2019-08-02 19:11:39 +02:00
.map(|x| (x.to_lowercase().find(&self.cur.to_lowercase()), x))
.filter(|(x, _)| x.is_some())
.map(|(x, y)| (x.unwrap(), y.to_string()))
.collect::<Vec<(usize, String)>>();
2019-08-02 15:59:10 +02:00
2019-08-02 19:11:39 +02:00
m.sort_by(|(x1, y1), (x2, y2)| {
if x1 < x2 {
Ordering::Less
} else if x1 > x2 {
Ordering::Greater
} else if y1.len() < y2.len() {
Ordering::Less
} else if y1.len() > y2.len() {
Ordering::Greater
} else {
y1.cmp(y2)
}
});
self.matches = m.into_iter().map(|(_, x)| x).collect();
2019-08-02 15:59:10 +02:00
self.dirty = false;
Ok(true)
} else {
Ok(false)
}
}
fn input(&mut self, input: Input) {
match input {
Input::Keypress { key, interpreted } => match key {
keysyms::XKB_KEY_BackSpace => {
if self.cur.len() > 0 {
self.cur = self.cur[..self.cur.len()-1].to_string();
self.offset = 0;
self.dirty = true
}
},
keysyms::XKB_KEY_Return => {
if self.matches.len() > self.offset {
println!("{}", self.matches[self.offset]);
std::process::exit(0);
}
},
keysyms::XKB_KEY_Right => {
if self.matches.len() > 0 && self.offset < self.matches.len() - 1{
self.offset += 1;
self.dirty = true;
}
},
keysyms::XKB_KEY_Left => {
if self.matches.len() > 0 && self.offset > 0 {
self.offset -= 1;
self.dirty = true;
}
},
_ => match interpreted {
Some(v) => {
self.cur += &v;
self.offset = 0;
self.dirty = true
},
None => {}
}
}
_ => {}
}
}
}