launcher: Add calculator feature
This commit is contained in:
Generated
+7
@@ -119,6 +119,11 @@ dependencies = [
|
|||||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libivy"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/kennylevinsen/libivy.git#f0c58a9ee57fa42a79b05e73021ccc91311aa690"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@@ -414,6 +419,7 @@ dependencies = [
|
|||||||
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fuzzy-matcher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fuzzy-matcher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libivy 0.1.0 (git+https://github.com/kennylevinsen/libivy.git)",
|
||||||
"libpulse-binding 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libpulse-binding 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -452,6 +458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
||||||
"checksum libdbus-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69382cb3be797cfe62ba89ac5e594a0e3022914ff44867ffbcfc03daa24eebd7"
|
"checksum libdbus-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "69382cb3be797cfe62ba89ac5e594a0e3022914ff44867ffbcfc03daa24eebd7"
|
||||||
|
"checksum libivy 0.1.0 (git+https://github.com/kennylevinsen/libivy.git)" = "<none>"
|
||||||
"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
|
"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
|
||||||
"checksum libpulse-binding 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7378bffd76492e876a0afb9a016359379a6b5a859fecd039248f76ce719fb"
|
"checksum libpulse-binding 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7378bffd76492e876a0afb9a016359379a6b5a859fecd039248f76ce719fb"
|
||||||
"checksum libpulse-sys 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dcac117c7e9fb50fe162d5fbc6b3818819bd173922f648fae017f913de68520"
|
"checksum libpulse-sys 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dcac117c7e9fb50fe162d5fbc6b3818819bd173922f648fae017f913de68520"
|
||||||
|
|||||||
+6
-1
@@ -4,6 +4,10 @@ version = "0.1.0"
|
|||||||
authors = ["Kenny Levinsen <kl@kl.wtf>"]
|
authors = ["Kenny Levinsen <kl@kl.wtf>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
ivy = [ "libivy" ]
|
||||||
|
default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smithay-client-toolkit = "0.6.3"
|
smithay-client-toolkit = "0.6.3"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
@@ -18,4 +22,5 @@ libpulse-binding = { version = "2.6.0"}
|
|||||||
dbus = "0.6"
|
dbus = "0.6"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
fuzzy-matcher = "0.2"
|
fuzzy-matcher = "0.2"
|
||||||
lazy_static = "1.3.0"
|
lazy_static = "1.3.0"
|
||||||
|
libivy = { git = "https://github.com/kennylevinsen/libivy.git", optional = true }
|
||||||
+50
-38
@@ -6,8 +6,6 @@ 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};
|
||||||
@@ -17,7 +15,8 @@ use smithay_client_toolkit::keyboard::keysyms;
|
|||||||
pub struct Launcher {
|
pub struct Launcher {
|
||||||
options: Vec<String>,
|
options: Vec<String>,
|
||||||
matches: Vec<String>,
|
matches: Vec<String>,
|
||||||
cur: String,
|
input: String,
|
||||||
|
result: Option<String>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
font: RefCell<Font>,
|
font: RefCell<Font>,
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
@@ -27,7 +26,7 @@ impl Launcher {
|
|||||||
pub fn new() -> Result<Launcher, ::std::io::Error> {
|
pub fn new() -> Result<Launcher, ::std::io::Error> {
|
||||||
if !atty::is(Stream::Stdin) {
|
if !atty::is(Stream::Stdin) {
|
||||||
let mut inbuf = String::new();
|
let mut inbuf = String::new();
|
||||||
std::io::stdin().read_to_string(&mut inbuf).unwrap();
|
std::io::stdin().read_to_string(&mut inbuf)?;
|
||||||
let options = inbuf
|
let options = inbuf
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -38,7 +37,8 @@ impl Launcher {
|
|||||||
Ok(Launcher {
|
Ok(Launcher {
|
||||||
options: options,
|
options: options,
|
||||||
matches: vec![],
|
matches: vec![],
|
||||||
cur: "".to_string(),
|
input: "".to_string(),
|
||||||
|
result: None,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
|
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
@@ -47,7 +47,8 @@ impl Launcher {
|
|||||||
Ok(Launcher {
|
Ok(Launcher {
|
||||||
options: vec![],
|
options: vec![],
|
||||||
matches: vec![],
|
matches: vec![],
|
||||||
cur: "".to_string(),
|
input: "".to_string(),
|
||||||
|
result: None,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
|
font: RefCell::new(Font::new(&ROBOTO_REGULAR, 32.0)),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
@@ -62,13 +63,13 @@ impl 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);
|
||||||
|
|
||||||
let mut x_off = if self.cur.len() > 0 {
|
let mut x_off = if self.input.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 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(
|
let dim = self.font.borrow_mut().auto_draw_text(
|
||||||
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
bg,
|
bg,
|
||||||
&c,
|
&c,
|
||||||
&self.cur,
|
&self.input,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
dim.0 + 8
|
dim.0 + 8
|
||||||
@@ -84,9 +85,9 @@ impl Launcher {
|
|||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
let size = if idx == self.offset && self.cur.len() > 0 {
|
let size = if idx == self.offset && self.input.len() > 0 {
|
||||||
let (_, indices) =
|
let (_, indices) =
|
||||||
fuzzy_indices(&m.to_lowercase(), &self.cur.to_lowercase()).unwrap();
|
fuzzy_indices(&m.to_lowercase(), &self.input.to_lowercase()).unwrap();
|
||||||
let mut colors = Vec::with_capacity(m.len());
|
let mut colors = Vec::with_capacity(m.len());
|
||||||
for pos in 0..m.len() {
|
for pos in 0..m.len() {
|
||||||
if indices.contains(&pos) {
|
if indices.contains(&pos) {
|
||||||
@@ -125,12 +126,12 @@ impl 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);
|
||||||
|
|
||||||
let x_off = if self.cur.len() > 0 {
|
let x_off = if self.input.len() > 0 {
|
||||||
let dim = self.font.borrow_mut().auto_draw_text(
|
let dim = self.font.borrow_mut().auto_draw_text(
|
||||||
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
bg,
|
bg,
|
||||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
&self.cur,
|
&self.input,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
dim.0 + 16
|
dim.0 + 16
|
||||||
@@ -138,21 +139,13 @@ impl Launcher {
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(output) = Command::new("ivy")
|
if let Some(result) = &self.result {
|
||||||
.arg("-e")
|
self.font.borrow_mut().auto_draw_text(
|
||||||
.arg(&self.cur.chars().skip(1).collect::<String>())
|
&mut buf.subdimensions((x_off, 0, 1232-x_off, 32))?,
|
||||||
.output() {
|
bg,
|
||||||
if let Ok(stdout) = str::from_utf8(&output.stdout) {
|
&Color::new(0.75, 0.75, 0.75, 1.0),
|
||||||
let stdout = stdout.trim();
|
&format!(" = {:}", result),
|
||||||
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()])
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
@@ -169,13 +162,23 @@ impl Launcher {
|
|||||||
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
&mut buf.subdimensions((0, 0, 1232, 32))?,
|
||||||
bg,
|
bg,
|
||||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
&self.cur,
|
&self.input,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(vec![buf.get_signed_bounds()])
|
Ok(vec![buf.get_signed_bounds()])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ivy")]
|
||||||
|
fn calc(s: &str) -> Result<String, String> {
|
||||||
|
libivy::eval(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ivy"))]
|
||||||
|
fn calc(_s: &str) -> Result<String, String> {
|
||||||
|
Err("ivy not enabled".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
impl ModuleImpl for Launcher {
|
impl ModuleImpl for Launcher {
|
||||||
fn draw(
|
fn draw(
|
||||||
&self,
|
&self,
|
||||||
@@ -185,7 +188,7 @@ 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);
|
||||||
|
|
||||||
match self.cur.chars().next() {
|
match self.input.chars().next() {
|
||||||
Some('=') => self.draw_calc(buf, bg),
|
Some('=') => self.draw_calc(buf, bg),
|
||||||
Some('!') => self.draw_shell(buf, bg),
|
Some('!') => self.draw_shell(buf, bg),
|
||||||
_ => self.draw_launcher(buf, bg),
|
_ => self.draw_launcher(buf, bg),
|
||||||
@@ -196,14 +199,21 @@ impl ModuleImpl for Launcher {
|
|||||||
|
|
||||||
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 {
|
||||||
match self.cur.chars().next() {
|
match self.input.chars().next() {
|
||||||
Some('=') => (),
|
Some('=') => {
|
||||||
|
if self.input.len() > 1 {
|
||||||
|
match calc(&self.input.chars().skip(1).collect::<String>()) {
|
||||||
|
Ok(v) => self.result = Some(v),
|
||||||
|
Err(_) => self.result = None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
Some('!') => (),
|
Some('!') => (),
|
||||||
_ => {
|
_ => {
|
||||||
let mut m = self
|
let mut m = self
|
||||||
.options
|
.options
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (fuzzy_match(&x.to_lowercase(), &self.cur.to_lowercase()), x))
|
.map(|x| (fuzzy_match(&x.to_lowercase(), &self.input.to_lowercase()), x))
|
||||||
.filter(|(x, _)| x.is_some())
|
.filter(|(x, _)| x.is_some())
|
||||||
.map(|(x, y)| (x.unwrap(), y.to_string()))
|
.map(|(x, y)| (x.unwrap(), y.to_string()))
|
||||||
.collect::<Vec<(i64, String)>>();
|
.collect::<Vec<(i64, String)>>();
|
||||||
@@ -237,17 +247,18 @@ impl ModuleImpl for Launcher {
|
|||||||
match input {
|
match input {
|
||||||
Input::Keypress { key, interpreted } => match key {
|
Input::Keypress { key, interpreted } => match key {
|
||||||
keysyms::XKB_KEY_BackSpace => {
|
keysyms::XKB_KEY_BackSpace => {
|
||||||
if self.cur.len() > 0 {
|
if self.input.len() > 0 {
|
||||||
self.cur = self.cur[..self.cur.len() - 1].to_string();
|
self.input = self.input[..self.input.len() - 1].to_string();
|
||||||
self.offset = 0;
|
self.offset = 0;
|
||||||
|
self.result = None;
|
||||||
self.dirty = true
|
self.dirty = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keysyms::XKB_KEY_Return => {
|
keysyms::XKB_KEY_Return => {
|
||||||
match self.cur.chars().next() {
|
match self.input.chars().next() {
|
||||||
Some('=') => (),
|
Some('=') => (),
|
||||||
Some('!') => {
|
Some('!') => {
|
||||||
println!("{}", self.cur.chars().skip(1).collect::<String>());
|
println!("{}", self.input.chars().skip(1).collect::<String>());
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
_ => if self.matches.len() > self.offset {
|
_ => if self.matches.len() > self.offset {
|
||||||
@@ -270,9 +281,10 @@ impl ModuleImpl for Launcher {
|
|||||||
}
|
}
|
||||||
_ => match interpreted {
|
_ => match interpreted {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
self.cur += &v;
|
self.input += &v;
|
||||||
self.offset = 0;
|
self.offset = 0;
|
||||||
self.dirty = true
|
self.result = None;
|
||||||
|
self.dirty = true;
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user