launcher: Modes
This commit is contained in:
+174
-87
@@ -6,6 +6,8 @@ use crate::module::{Input, ModuleImpl};
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::str;
|
||||||
|
|
||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
@@ -29,6 +31,7 @@ impl Launcher {
|
|||||||
let options = inbuf
|
let options = inbuf
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.filter(|s| s.len() > 0)
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -41,12 +44,136 @@ impl Launcher {
|
|||||||
dirty: true,
|
dirty: true,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(::std::io::Error::new(
|
Ok(Launcher {
|
||||||
::std::io::ErrorKind::Other,
|
options: vec![],
|
||||||
"input is a tty",
|
matches: vec![],
|
||||||
))
|
cur: "".to_string(),
|
||||||
|
offset: 0,
|
||||||
|
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
|
||||||
|
dirty: true,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_launcher(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
bg: &Color,
|
||||||
|
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
|
||||||
|
buf.memset(bg);
|
||||||
|
|
||||||
|
let mut x_off = if self.cur.len() > 0 {
|
||||||
|
let c = if self.matches.len() == 0 { Color::new(1.0, 0.5, 0.5, 1.0) } else { Color::new(1.0, 1.0, 1.0, 1.0) };
|
||||||
|
let dim = self.font.borrow_mut().auto_draw_text(
|
||||||
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
|
bg,
|
||||||
|
&c,
|
||||||
|
&self.cur,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
dim.0 + 8
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let mut width_remaining: i32 = 1232 - x_off as i32;
|
||||||
|
for (idx, m) in self.matches.iter().enumerate() {
|
||||||
|
let mut b =
|
||||||
|
match buf.subdimensions((x_off, 0, width_remaining as u32, 32)) {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
|
let size = if idx == self.offset && self.cur.len() > 0 {
|
||||||
|
let (_, indices) =
|
||||||
|
fuzzy_indices(&m.to_lowercase(), &self.cur.to_lowercase()).unwrap();
|
||||||
|
let mut colors = Vec::with_capacity(m.len());
|
||||||
|
for pos in 0..m.len() {
|
||||||
|
if indices.contains(&pos) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.font
|
||||||
|
.borrow_mut()
|
||||||
|
.auto_draw_text_individual_colors(&mut b, bg, &colors, &m)?
|
||||||
|
} else {
|
||||||
|
self.font.borrow_mut().auto_draw_text(
|
||||||
|
&mut b,
|
||||||
|
bg,
|
||||||
|
&Color::new(0.5, 0.5, 0.5, 1.0),
|
||||||
|
m,
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
|
x_off += size.0 + 8;
|
||||||
|
width_remaining -= (size.0 + 8) as i32;
|
||||||
|
|
||||||
|
if width_remaining < 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_calc(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
bg: &Color,
|
||||||
|
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
|
||||||
|
buf.memset(bg);
|
||||||
|
|
||||||
|
let x_off = if self.cur.len() > 0 {
|
||||||
|
let dim = self.font.borrow_mut().auto_draw_text(
|
||||||
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
|
bg,
|
||||||
|
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
|
&self.cur,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
dim.0 + 16
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(output) = Command::new("ivy")
|
||||||
|
.arg("-e")
|
||||||
|
.arg(&self.cur.chars().skip(1).collect::<String>())
|
||||||
|
.output() {
|
||||||
|
if let Ok(stdout) = str::from_utf8(&output.stdout) {
|
||||||
|
let stdout = stdout.trim();
|
||||||
|
if stdout.len() > 0 {
|
||||||
|
self.font.borrow_mut().auto_draw_text(
|
||||||
|
&mut buf.subdimensions((x_off, 0, 1232-x_off, 32))?,
|
||||||
|
bg,
|
||||||
|
&Color::new(0.75, 0.75, 0.75, 1.0),
|
||||||
|
&format!(" = {:}", stdout),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_shell(
|
||||||
|
&self,
|
||||||
|
buf: &mut Buffer,
|
||||||
|
bg: &Color,
|
||||||
|
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
|
||||||
|
buf.memset(bg);
|
||||||
|
|
||||||
|
self.font.borrow_mut().auto_draw_text(
|
||||||
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
|
bg,
|
||||||
|
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
|
&self.cur,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleImpl for Launcher {
|
impl ModuleImpl for Launcher {
|
||||||
@@ -58,91 +185,47 @@ impl ModuleImpl for Launcher {
|
|||||||
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
|
) -> Result<Vec<(i32, i32, i32, i32)>, ::std::io::Error> {
|
||||||
buf.memset(bg);
|
buf.memset(bg);
|
||||||
|
|
||||||
self.font.borrow_mut().auto_draw_text(
|
match self.cur.chars().next() {
|
||||||
&mut buf.subdimensions((0, 0, 128, 32))?,
|
Some('=') => self.draw_calc(buf, bg),
|
||||||
bg,
|
Some('!') => self.draw_shell(buf, bg),
|
||||||
&Color::new(0.75, 0.75, 0.75, 1.0),
|
_ => self.draw_launcher(buf, bg),
|
||||||
"Run: ",
|
}?;
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut x_off: i32 = 0;
|
|
||||||
let mut width_remaining: i32 = 1232 - 64;
|
|
||||||
if self.matches.len() == 0 && self.cur.len() > 0 {
|
|
||||||
self.font.borrow_mut().auto_draw_text(
|
|
||||||
&mut buf
|
|
||||||
.subdimensions((64, 0, width_remaining as u32, 32))
|
|
||||||
.unwrap(),
|
|
||||||
bg,
|
|
||||||
&Color::new(1.0, 0.5, 0.5, 1.0),
|
|
||||||
&self.cur,
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
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 (_, indices) =
|
|
||||||
fuzzy_indices(&m.to_lowercase(), &self.cur.to_lowercase()).unwrap();
|
|
||||||
let mut colors = Vec::with_capacity(m.len());
|
|
||||||
for pos in 0..m.len() {
|
|
||||||
if indices.contains(&pos) {
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.font
|
|
||||||
.borrow_mut()
|
|
||||||
.auto_draw_text_individual_colors(&mut b, bg, &colors, &m)?
|
|
||||||
} else {
|
|
||||||
self.font.borrow_mut().auto_draw_text(
|
|
||||||
&mut b,
|
|
||||||
bg,
|
|
||||||
&Color::new(0.5, 0.5, 0.5, 1.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()])
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, _time: &DateTime<Local>, force: bool) -> Result<bool, ::std::io::Error> {
|
fn update(&mut self, _time: &DateTime<Local>, force: bool) -> Result<bool, ::std::io::Error> {
|
||||||
if self.dirty || force {
|
if self.dirty || force {
|
||||||
let mut m = self
|
match self.cur.chars().next() {
|
||||||
.options
|
Some('=') => (),
|
||||||
.iter()
|
Some('!') => (),
|
||||||
.map(|x| (fuzzy_match(&x.to_lowercase(), &self.cur.to_lowercase()), x))
|
_ => {
|
||||||
.filter(|(x, _)| x.is_some())
|
let mut m = self
|
||||||
.map(|(x, y)| (x.unwrap(), y.to_string()))
|
.options
|
||||||
.collect::<Vec<(i64, String)>>();
|
.iter()
|
||||||
|
.map(|x| (fuzzy_match(&x.to_lowercase(), &self.cur.to_lowercase()), x))
|
||||||
|
.filter(|(x, _)| x.is_some())
|
||||||
|
.map(|(x, y)| (x.unwrap(), y.to_string()))
|
||||||
|
.collect::<Vec<(i64, String)>>();
|
||||||
|
|
||||||
m.sort_by(|(x1, y1), (x2, y2)| {
|
m.sort_by(|(x1, y1), (x2, y2)| {
|
||||||
if x1 > x2 {
|
if x1 > x2 {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else if x1 < x2 {
|
} else if x1 < x2 {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
} else if y1.len() < y2.len() {
|
} else if y1.len() < y2.len() {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
} else if y1.len() > y2.len() {
|
} else if y1.len() > y2.len() {
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
} else {
|
} else {
|
||||||
y1.cmp(y2)
|
y1.cmp(y2)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.matches = m.into_iter().map(|(_, x)| x).collect();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
self.matches = m.into_iter().map(|(_, x)| x).collect();
|
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
@@ -161,13 +244,17 @@ impl ModuleImpl for Launcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
keysyms::XKB_KEY_Return => {
|
keysyms::XKB_KEY_Return => {
|
||||||
if self.matches.len() > self.offset {
|
match self.cur.chars().next() {
|
||||||
println!("{}", self.matches[self.offset]);
|
Some('=') => (),
|
||||||
std::process::exit(0);
|
Some('!') => {
|
||||||
} else {
|
println!("{}", self.cur.chars().skip(1).collect::<String>());
|
||||||
println!("{}", self.cur);
|
std::process::exit(0);
|
||||||
std::process::exit(0);
|
}
|
||||||
}
|
_ => if self.matches.len() > self.offset {
|
||||||
|
println!("{}", self.matches[self.offset]);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
keysyms::XKB_KEY_Right => {
|
keysyms::XKB_KEY_Right => {
|
||||||
if self.matches.len() > 0 && self.offset < self.matches.len() - 1 {
|
if self.matches.len() > 0 && self.offset < self.matches.len() - 1 {
|
||||||
|
|||||||
Reference in New Issue
Block a user