17 Commits
Author SHA1 Message Date
Kenny Levinsen 3eb7cddb6c Bump version to 0.3.0 2022-01-15 18:40:38 +01:00
Kenny Levinsen 2813ae0eff clock: Adjust to new font advance 2022-01-14 00:39:23 +01:00
Kenny Levinsen 1b1ffc4435 Update example config 2022-01-14 00:38:02 +01:00
Tadeo Kondrak cf9fabb052 draw: Use font's horizontal advance value 2022-01-14 00:36:50 +01:00
Cyril Levis 43fe73bf09 feat: add ranking based on usage to launcher widget
Signed-off-by: Cyril Levis <git@levis.name>
2022-01-02 17:08:18 +01:00
Cyril Levis d291e36b3f feat: allow choosing recent app with tabs 2021-12-30 22:22:01 +01:00
Cyril Levis fe37c15f95 feat: deduplicate desktop entries
We don't want duplicate entries because there are not distinguishable by Name.

People will sometimes override in there HOME dir some desktop files entries
in order to do some modifications.

The actual reading order is good and so `unique_by` name do the job.
2021-12-30 22:10:51 +01:00
Cyril Levis d4f62da6f5 feat: recurse deeper in applications folder
max recursion 2 levels
2021-12-30 22:04:19 +01:00
Tadeo Kondrak 1edefd9cad main: only bind up to version 3 of wl_output 2021-12-25 18:32:37 +01:00
Maxim Baz 90ffa7df27 Lex exec even when using custom opener
This fixes a few bugs I found related to custom opener.

Instead of sending the entire exec as a single argument, this properly
splits the command, trims trailing whitespaces, and lets the receiving
opener iterate over terms.
2021-12-25 17:59:45 +01:00
Kenny Levinsen d69e941ec1 Remove old FUNDING link 2021-10-15 22:47:10 +02:00
Kenny Levinsen 5e5e8876f6 cargo fmt 2021-09-02 21:15:35 +02:00
Kenny Levinsen 886d595f91 launcher: Migrate to SkimMatcherV2 2021-09-02 21:14:08 +02:00
Kenny Levinsen e04237b928 Use format string with panic 2021-09-02 21:13:57 +02:00
Kenny Levinsen ef84c519a2 app: Migrate to compare_exchange 2021-09-02 21:13:33 +02:00
Kenny Levinsen 1e647c7036 readme: Update discuss section 2021-05-19 17:51:27 +02:00
Kenny Levinsen 56f6b1668d cargo fmt 2021-03-04 00:23:09 +01:00
20 changed files with 242 additions and 105 deletions
-1
View File
@@ -1,4 +1,3 @@
# These are supported funding model platforms
liberapay: kennylevinsen
custom: https://donate.kl.wtf/
Generated
+46
View File
@@ -152,6 +152,12 @@ version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "fake-simd"
version = "0.1.2"
@@ -185,6 +191,15 @@ dependencies = [
"typenum",
]
[[package]]
name = "itertools"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.7"
@@ -520,6 +535,15 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.123"
@@ -663,6 +687,17 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@@ -744,6 +779,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -762,6 +806,7 @@ dependencies = [
"dlib",
"fontconfig",
"fuzzy-matcher",
"itertools",
"lazy_static",
"libpulse-binding",
"memmap",
@@ -776,6 +821,7 @@ dependencies = [
"shlex",
"timerfd",
"unicode-segmentation",
"walkdir",
"wayland-client",
"wayland-protocols",
]
+3 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "wldash"
version = "0.2.0"
version = "0.3.0"
authors = ["Kenny Levinsen <kl@kl.wtf>"]
edition = "2018"
@@ -37,6 +37,8 @@ rcalc_lib = "0.9"
rust-ini = "0.14"
shlex = "0.1"
timerfd = "1.0.0"
walkdir = "2.3.2"
itertools = "0.10.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", optional = true }
+4
View File
@@ -66,3 +66,7 @@ The launcher also accepts prefix operators to change its mode:
- Configurability
- Cleanup and reorganization
- Proper line editor for the launcher
## How to discuss
Go to #kennylevinsen @ irc.libera.chat to discuss, or use [~kennylevinsen/public-inbox@lists.sr.ht](https://lists.sr.ht/~kennylevinsen/public-inbox).
+3 -3
View File
@@ -37,8 +37,8 @@
{"launcher": {
"font_size": 32.0,
"length": 1200,
"app_opener": "swaymsg exec ",
"term_opener": "alacritty -e ",
"app_opener": "swaymsg exec -- ",
"term_opener": "foot --",
"url_opener": "xdg-open "
}}
]}
@@ -52,4 +52,4 @@
"blue": 0,
"opacity": 0.9
}
}
}
+2 -2
View File
@@ -45,6 +45,6 @@ widget:
- launcher:
font_size: 32.0
length: 1200
app_opener: "swaymsg exec "
term_opener: "alacritty -e "
app_opener: "swaymsg exec --"
term_opener: "foot --"
url_opener: "xdg-open "
+40 -40
View File
@@ -5,11 +5,9 @@ use std::sync::{Arc, Mutex};
use chrono::{Duration, Local, NaiveDateTime};
use crate::keyboard::{
keysyms, map_keyboard, Event as KbEvent, KeyState, ModifiersState,
};
use crate::keyboard::{keysyms, map_keyboard, Event as KbEvent, KeyState, ModifiersState};
use wayland_client::protocol::{wl_compositor, wl_output, wl_pointer, wl_shm, wl_surface, wl_seat};
use wayland_client::protocol::{wl_compositor, wl_output, wl_pointer, wl_seat, wl_shm, wl_surface};
use wayland_client::{Display, EventQueue, GlobalEvent, GlobalManager, Main};
use wayland_protocols::wlr::unstable::layer_shell::v1::client::{
zwlr_layer_shell_v1, zwlr_layer_surface_v1,
@@ -17,7 +15,7 @@ use wayland_protocols::wlr::unstable::layer_shell::v1::client::{
use crate::buffer::Buffer;
use crate::color::Color;
use crate::widget::{WaitContext, DrawContext, Widget};
use crate::widget::{DrawContext, WaitContext, Widget};
use crate::cmd::Cmd;
use crate::doublemempool::DoubleMemPool;
@@ -68,28 +66,29 @@ impl AppInner {
Main<wl_surface::WlSurface>,
Main<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
) {
let surface = compositor
.create_surface();
let surface = compositor.create_surface();
let this_is_stupid = AtomicBool::new(false);
let shell_surface = shell
.get_layer_surface(
&surface,
output,
zwlr_layer_shell_v1::Layer::Overlay,
"".to_string());
shell_surface.quick_assign(move |layer, event, _| match event {
zwlr_layer_surface_v1::Event::Configure { serial, .. } => {
if !this_is_stupid.compare_and_swap(false, true, Ordering::SeqCst) {
*(configured_surfaces.lock().unwrap()) += 1;
layer.ack_configure(serial);
tx.send(Cmd::ForceDraw).unwrap();
}
}
_ => unreachable!(),
},
let shell_surface = shell.get_layer_surface(
&surface,
output,
zwlr_layer_shell_v1::Layer::Overlay,
"".to_string(),
);
shell_surface.quick_assign(move |layer, event, _| match event {
zwlr_layer_surface_v1::Event::Configure { serial, .. } => {
if this_is_stupid
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
{
*(configured_surfaces.lock().unwrap()) += 1;
layer.ack_configure(serial);
tx.send(Cmd::ForceDraw).unwrap();
}
}
_ => unreachable!(),
});
shell_surface.set_keyboard_interactivity(1);
shell_surface.set_size(1, 1);
@@ -401,8 +400,7 @@ impl<'a> App<'a> {
version,
} => {
if let "wl_output" = &interface[..] {
let output = registry
.bind(version, id);
let output = registry.bind(std::cmp::min(version, 3), id);
inner_global.lock().unwrap().add_output(id, output);
}
}
@@ -415,8 +413,8 @@ impl<'a> App<'a> {
// double sync to retrieve the global list
// and the globals metadata
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
// wl_compositor
let compositor = manager
@@ -435,10 +433,8 @@ impl<'a> App<'a> {
//
// Get our seat
//
let seat: Main<wl_seat::WlSeat> = manager
.instantiate_range(1, 6)
.unwrap();
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
let seat: Main<wl_seat::WlSeat> = manager.instantiate_range(1, 6).unwrap();
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
//
// Keyboard processing
@@ -453,7 +449,7 @@ impl<'a> App<'a> {
num_lock: false,
}));
let keyboard = Arc::new(Mutex::new(AppKeyboard{
let keyboard = Arc::new(Mutex::new(AppKeyboard {
current: None,
delay: 0,
rate: 0,
@@ -485,7 +481,10 @@ impl<'a> App<'a> {
let mut kbd = kb2.lock().unwrap();
kbd.current = Some(ev.clone());
kbd.next = if kbd.delay > 0 {
Some(Local::now().naive_local() + Duration::milliseconds(kbd.delay.into()))
Some(
Local::now().naive_local()
+ Duration::milliseconds(kbd.delay.into()),
)
} else {
None
};
@@ -496,10 +495,10 @@ impl<'a> App<'a> {
} else {
kb2.lock().unwrap().next = None;
}
},
}
KbEvent::Leave { .. } => {
kb2.lock().unwrap().next = None;
},
}
KbEvent::RepeatInfo { delay, rate } => {
let mut kbd = kb2.lock().unwrap();
kbd.delay = delay;
@@ -513,15 +512,16 @@ impl<'a> App<'a> {
//
// Prepare shell so that we can create our shell surface
//
inner.lock().unwrap().set_shell(Some(
if let Ok(layer) = manager.instantiate_exact(1) {
inner
.lock()
.unwrap()
.set_shell(Some(if let Ok(layer) = manager.instantiate_exact(1) {
layer
} else {
panic!("server didn't advertise `zwlr_layer_shell_v1`");
},
));
}));
event_queue.sync_roundtrip(&mut(), |_, _, _|{}).unwrap();
event_queue.sync_roundtrip(&mut (), |_, _, _| {}).unwrap();
//
// Cursor processing
+1 -1
View File
@@ -345,6 +345,6 @@ impl Default for Config {
fn get_font<'a>(name: &str, map: &'a FontMap) -> FontRef<'a> {
match map.get(name) {
Some(f) => f,
None => panic!(format!("Font {} is missing from the config", name)),
None => panic!("Font {} is missing from the config", name),
}
}
+57
View File
@@ -0,0 +1,57 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::fs::{create_dir_all, File, OpenOptions};
use std::path::PathBuf;
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
pub struct Data {
pub entries: HashMap<String, i64>,
}
impl Data {
pub fn load() -> Result<Data, Box<dyn Error>> {
Ok(serde_yaml::from_reader(Self::read_file()?)?)
}
pub fn save(&self) -> Result<(), Box<dyn Error>> {
Ok(serde_yaml::to_writer(Self::write_file()?, self)?)
}
fn read_file() -> Result<File, Box<dyn Error>> {
Ok(OpenOptions::new()
.create(true)
.write(true)
.read(true)
.open(Self::path()?)?)
}
fn write_file() -> Result<File, Box<dyn Error>> {
Ok(OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(Self::path()?)?)
}
fn path() -> Result<PathBuf, Box<dyn Error>> {
let xdg_cache = match env::var_os("XDG_CACHE_HOME") {
Some(s) => s
.into_string()
.map_err(|_| "Unable to resolve $XDG_CACHE_HOME")?,
None => format!(
"{}/.cache",
env::var_os("HOME")
.ok_or("Unable to resolve $HOME")?
.into_string()
.map_err(|_| "Unable to resolve $HOME")?
),
};
let cache_dir = PathBuf::from(xdg_cache).join("wldash");
create_dir_all(&cache_dir)?;
Ok(cache_dir.join("data.yaml"))
}
}
+4 -2
View File
@@ -1,11 +1,12 @@
extern crate ini;
use ini::{Ini, ParseOption};
use itertools::Itertools;
use std::cmp::Ordering;
use std::env;
use std::error::Error;
use std::fs;
use std::io::Error as io_error;
use std::io::ErrorKind;
use walkdir::WalkDir;
#[derive(Clone, Debug, Eq, Hash)]
pub struct Desktop {
@@ -56,7 +57,7 @@ impl Desktop {
fn parse_dir(d: &str) -> Result<Vec<Desktop>, Box<dyn Error>> {
let mut files: Vec<Desktop> = Vec::with_capacity(16);
for entry in fs::read_dir(d)? {
for entry in WalkDir::new(d) {
let entry = entry?;
let path = entry.path();
@@ -107,5 +108,6 @@ pub fn load_desktop_files() -> Vec<Desktop> {
.filter(|d| {
!d.hidden && !d.no_display && (d.entry_type == "Application" || d.entry_type == "Link")
})
.unique_by(|x| x.name.clone())
.collect()
}
+2 -3
View File
@@ -209,9 +209,9 @@ fn create_shm_fd() -> io::Result<RawFd> {
Err(nix::Error::Sys(errno)) => match unistd::close(fd) {
Ok(_) => return Err(io::Error::from(errno)),
Err(nix::Error::Sys(errno)) => return Err(io::Error::from(errno)),
Err(err) => panic!(err),
Err(err) => panic!("{}", err),
},
Err(err) => panic!(err),
Err(err) => panic!("{}", err),
},
Err(nix::Error::Sys(Errno::EEXIST)) => {
// If a file with that handle exists then change the handle
@@ -228,7 +228,6 @@ fn create_shm_fd() -> io::Result<RawFd> {
}
}
pub struct DoubleMemPool {
pool1: MemPool,
pool2: MemPool,
+11 -9
View File
@@ -8,16 +8,16 @@ struct CachedGlyph {
dimensions: (u32, u32),
origin: (i32, i32),
render: Vec<f32>,
advance: i32,
}
impl CachedGlyph {
fn new(font: FontRef, size: f32, ch: char) -> CachedGlyph {
let scale = Scale::uniform(size);
let v_metrics = font.v_metrics(scale);
let glyph = font
.glyph(ch)
.scaled(scale)
.positioned(point(0.0, v_metrics.ascent));
let glyph = font.glyph(ch).scaled(scale);
let advance = glyph.h_metrics().advance_width as i32;
let glyph = glyph.positioned(point(0.0, v_metrics.ascent));
if let Some(bounding_box) = glyph.pixel_bounding_box() {
let origin = (bounding_box.min.x, bounding_box.min.y);
@@ -35,12 +35,14 @@ impl CachedGlyph {
origin,
dimensions,
render,
advance,
}
} else {
CachedGlyph {
origin: (0, 0),
dimensions: ((size / 4.0) as u32, 0),
dimensions: (0, 0),
render: Vec::new(),
advance: (size / 4.0) as i32,
}
}
}
@@ -118,7 +120,7 @@ impl<'a> Font<'a> {
}
for glyph in glyphs {
glyph.draw(buf, (x_off, -off), bg, c);
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
x_off += glyph.advance;
}
Ok((x_off as u32, self.size as u32))
@@ -157,7 +159,7 @@ impl<'a> Font<'a> {
self.draw_cursor(buf, c, x_off as u32, height)?;
}
glyph.draw(buf, (x_off, -off), bg, c);
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
x_off += glyph.advance;
}
if cursor == glyphs.len() {
self.draw_cursor(buf, c, x_off as u32, height)?;
@@ -193,7 +195,7 @@ impl<'a> Font<'a> {
))
}
};
let width = glyph.dimensions.0 as i32 + glyph.origin.0;
let width = glyph.advance;
if width > max {
max = width
}
@@ -285,7 +287,7 @@ impl<'a> Font<'a> {
}
for (idx, glyph) in glyphs.into_iter().enumerate() {
glyph.draw(buf, (x_off, -off), bg, &color[idx]);
x_off += glyph.dimensions.0 as i32 + glyph.origin.0;
x_off += glyph.advance;
}
Ok((x_off as u32, self.size as u32))
+14 -14
View File
@@ -1,17 +1,17 @@
#![allow(missing_docs, non_upper_case_globals, unused_parens, clippy::all)]
pub const XKB_KEY_BackSpace :u32 = 0xff08; /* Back space, back char */
pub const XKB_KEY_Tab :u32 = 0xff09;
pub const XKB_KEY_Return :u32 = 0xff0d; /* Return, enter */
pub const XKB_KEY_Escape :u32 = 0xff1b;
pub const XKB_KEY_Delete :u32 = 0xffff; /* Delete, rubout */
pub const XKB_KEY_Home :u32 = 0xff50;
pub const XKB_KEY_Left :u32 = 0xff51; /* Move left, left arrow */
pub const XKB_KEY_Right :u32 = 0xff53; /* Move right, right arrow */
pub const XKB_KEY_End :u32 = 0xff57; /* EOL */
pub const XKB_KEY_BackSpace: u32 = 0xff08; /* Back space, back char */
pub const XKB_KEY_Tab: u32 = 0xff09;
pub const XKB_KEY_Return: u32 = 0xff0d; /* Return, enter */
pub const XKB_KEY_Escape: u32 = 0xff1b;
pub const XKB_KEY_Delete: u32 = 0xffff; /* Delete, rubout */
pub const XKB_KEY_Home: u32 = 0xff50;
pub const XKB_KEY_Left: u32 = 0xff51; /* Move left, left arrow */
pub const XKB_KEY_Right: u32 = 0xff53; /* Move right, right arrow */
pub const XKB_KEY_End: u32 = 0xff57; /* EOL */
pub const XKB_KEY_ISO_Left_Tab :u32 = 0xfe20;
pub const XKB_KEY_e :u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */
pub const XKB_KEY_a :u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */
pub const XKB_KEY_c :u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */
pub const XKB_KEY_u :u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */
pub const XKB_KEY_ISO_Left_Tab: u32 = 0xfe20;
pub const XKB_KEY_e: u32 = 0x0065; /* U+0065 LATIN SMALL LETTER E */
pub const XKB_KEY_a: u32 = 0x0061; /* U+0061 LATIN SMALL LETTER A */
pub const XKB_KEY_c: u32 = 0x0063; /* U+0063 LATIN SMALL LETTER C */
pub const XKB_KEY_u: u32 = 0x0075; /* U+0075 LATIN SMALL LETTER U */
+14 -8
View File
@@ -23,8 +23,8 @@ use wayland_client::{
};
mod ffi;
mod state;
pub mod keysyms;
mod state;
use self::state::KbState;
pub use self::state::{ModifiersState, RMLVO};
@@ -118,10 +118,7 @@ where
let callback = Rc::new(RefCell::new(callback));
// prepare the handler
let mut kbd_handler = KbdHandler {
callback,
state,
};
let mut kbd_handler = KbdHandler { callback, state };
keyboard.quick_assign(move |keyboard, event, data| {
kbd_handler.event(keyboard.detach(), event, data)
@@ -331,8 +328,17 @@ impl KbdHandler {
}
}
fn repeat_info(&mut self, object: wl_keyboard::WlKeyboard, rate: i32, delay: i32, dispatch_data: wayland_client::DispatchData) {
(&mut *self.callback.borrow_mut())(Event::RepeatInfo { rate, delay }, object, dispatch_data);
fn repeat_info(
&mut self,
object: wl_keyboard::WlKeyboard,
rate: i32,
delay: i32,
dispatch_data: wayland_client::DispatchData,
) {
(&mut *self.callback.borrow_mut())(
Event::RepeatInfo { rate, delay },
object,
dispatch_data,
);
}
}
-1
View File
@@ -398,4 +398,3 @@ impl Drop for KbState {
}
}
}
+7 -3
View File
@@ -12,15 +12,16 @@ use timerfd::{SetTimeFlags, TimerFd, TimerState};
mod app;
mod buffer;
mod keyboard;
mod cmd;
mod color;
mod config;
mod configfmt;
mod data;
mod desktop;
mod doublemempool;
mod draw;
mod fonts;
mod keyboard;
mod widget;
mod widgets;
@@ -206,7 +207,10 @@ fn main() {
});
let mut timer = TimerFd::new().unwrap();
let ev_fd = PollFd::new(app.event_queue().display().get_connection_fd(), PollFlags::POLLIN);
let ev_fd = PollFd::new(
app.event_queue().display().get_connection_fd(),
PollFlags::POLLIN,
);
let rx_fd = PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN);
let tm_fd = PollFd::new(timer.as_raw_fd(), PollFlags::POLLIN);
let ipc_fd = PollFd::new(listener.as_raw_fd(), PollFlags::POLLIN);
@@ -323,7 +327,7 @@ fn main() {
}
app.event_queue()
.dispatch_pending(&mut (), |_, _, _|{})
.dispatch_pending(&mut (), |_, _, _| {})
.expect("Failed to dispatch all messages.");
}
+1 -1
View File
@@ -1,8 +1,8 @@
use crate::buffer::Buffer;
use crate::color::Color;
pub use crate::keyboard::{KeyState, ModifiersState};
use chrono::NaiveDateTime;
use nix::poll::PollFd;
pub use crate::keyboard::{KeyState, ModifiersState};
pub struct DrawContext<'a> {
pub buf: &'a mut Buffer<'a>,
+3 -3
View File
@@ -99,7 +99,7 @@ impl BarWidgetImpl for Alsa {
fn value(&self) -> f32 {
match self.get_master_volume() {
Ok(v) => v,
Err(e) => panic!(e),
Err(e) => panic!("{}", e),
}
}
fn color(&self) -> Color {
@@ -107,12 +107,12 @@ impl BarWidgetImpl for Alsa {
}
fn inc(&mut self, diff: f32) {
if let Err(e) = self.inc_master_volume(diff) {
panic!(e)
panic!("{}", e)
}
}
fn set(&mut self, abs: f32) {
if let Err(e) = self.set_master_volume(abs) {
panic!(e)
panic!("{}", e)
}
}
fn toggle(&mut self) {}
+1 -1
View File
@@ -21,7 +21,7 @@ impl<'a> Clock<'a> {
clock_cache.add_str_to_cache("0123456789:");
let digit = clock_cache.auto_widest("123456789")?;
let colon = (clock_cache.auto_widest(":")? as f32 * 1.25) as u32;
let colon = clock_cache.auto_widest(":")?;
Ok(Box::new(Clock {
cur_time: time,
+29 -12
View File
@@ -14,8 +14,10 @@ use std::collections::HashMap;
use std::process::Command;
use std::sync::mpsc::Sender;
use fuzzy_matcher::skim::{fuzzy_indices, fuzzy_match};
use crate::data::Data;
use crate::keyboard::keysyms;
use fuzzy_matcher::skim::SkimMatcherV2;
use fuzzy_matcher::FuzzyMatcher;
use unicode_segmentation::UnicodeSegmentation;
pub struct Launcher<'a> {
@@ -33,6 +35,7 @@ pub struct Launcher<'a> {
length: u32,
dirty: bool,
tx: Sender<Cmd>,
counter: Data,
}
impl<'a> Launcher<'a> {
@@ -60,6 +63,7 @@ impl<'a> Launcher<'a> {
length,
dirty: true,
tx: listener,
counter: Data::load().unwrap_or_default(),
})
}
@@ -90,15 +94,17 @@ impl<'a> Launcher<'a> {
};
let mut width_remaining: i32 = (width - x_off) as i32;
let fuzzy_matcher = SkimMatcherV2::default();
for (idx, m) in self.matches.iter().enumerate() {
let mut b = match buf.offset((x_off, 0)) {
Ok(b) => b,
Err(_) => break,
};
let size = if idx == self.offset && !self.input.is_empty() {
let (_, indices) =
fuzzy_indices(&m.name.to_lowercase(), &self.input.to_lowercase())
.unwrap_or((0, vec![]));
let size = if idx == self.offset {
let (_, indices) = fuzzy_matcher
.fuzzy_indices(&m.name.to_lowercase(), &self.input.to_lowercase())
.unwrap_or((0, vec![]));
let mut colors = Vec::with_capacity(m.name.len());
for pos in 0..m.name.len() {
if indices.contains(&pos) {
@@ -213,17 +219,20 @@ fn wlcopy(s: &str) -> Result<(), String> {
struct Matcher {
matches: HashMap<Desktop, i64>,
counter: Data,
}
impl Matcher {
fn new() -> Self {
fn new(counter: Data) -> Self {
Self {
matches: HashMap::new(),
counter,
}
}
fn try_match(&mut self, dtop: Desktop, val: &str, input: &str, prio: f32) {
if let Some(ma) = fuzzy_match(val, input) {
let fuzzy_matcher = SkimMatcherV2::default();
if let Some(ma) = fuzzy_matcher.fuzzy_match(val, input) {
let ma = ((ma as f32) * prio) as i64;
if let Some(ma_old) = self.matches.get(&dtop) {
// Skip over new matches for the same program that are worse
@@ -245,9 +254,12 @@ impl Matcher {
.collect::<Vec<(i64, Desktop)>>();
m.sort_by(|(ma1, d1), (ma2, d2)| {
if ma1 > ma2 {
let count1 = self.counter.entries.get(&d1.name).unwrap_or(&0);
let count2 = self.counter.entries.get(&d2.name).unwrap_or(&0);
if ma1 + count1 > ma2 + count2 {
Ordering::Less
} else if ma1 < ma2 {
} else if ma1 + count1 < ma2 + count2 {
Ordering::Greater
} else if d1.name.len() < d2.name.len() {
Ordering::Less
@@ -303,7 +315,7 @@ impl<'a> Widget for Launcher<'a> {
}
Some('!') => (),
_ => {
let mut matcher = Matcher::new();
let mut matcher = Matcher::new(self.counter.clone());
for desktop in self.options.iter() {
matcher.try_match(
@@ -417,13 +429,18 @@ impl<'a> Widget for Launcher<'a> {
&self.app_opener
};
let mut lexed = shlex::split(&exec).unwrap();
let lexed = if !prefix.is_empty() {
let mut prefix = shlex::split(prefix).unwrap();
prefix.push(exec);
prefix.append(&mut lexed);
prefix
} else {
shlex::split(&exec).unwrap()
lexed
};
*self.counter.entries.entry(d.name.clone()).or_insert(0) += 1;
self.counter.save().expect("Unable to save data");
if !lexed.is_empty() {
let _ =
Command::new(lexed[0].clone()).args(&lexed[1..]).spawn();