From 1cade695c8aa5ca091a28513f6036e95d919ed2a Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Mon, 18 Oct 2021 00:44:32 +0200 Subject: [PATCH] Initial freedesktop applications source --- Cargo.lock | 126 ++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 5 +- src/main.rs | 3 +- src/roftl.rs | 7 ++- src/sources/apps.rs | 60 ++++++++++++++++++++ src/sources/mod.rs | 3 + src/sources/test.rs | 2 +- src/sources/windows.rs | 6 +- src/ui/painter.rs | 6 +- 9 files changed, 197 insertions(+), 21 deletions(-) create mode 100644 src/sources/apps.rs diff --git a/Cargo.lock b/Cargo.lock index 82845e6..205f58f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -17,6 +17,12 @@ version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "atty" version = "0.2.14" @@ -40,6 +46,18 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitvec" +version = "0.19.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block" version = "0.1.6" @@ -377,6 +395,22 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "freedesktop_entry_parser" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347aa21b13048c0a0a4dc3118b661eb89d73ea675eca95b6a0f11e698ff66ec1" +dependencies = [ + "nom 6.2.1", + "thiserror", +] + +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures-channel" version = "0.3.17" @@ -559,6 +593,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if 1.0.0", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.103" @@ -604,9 +651,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memmap2" @@ -712,6 +759,19 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nom" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" +dependencies = [ + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.0.0" @@ -889,6 +949,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "raw-window-handle" version = "0.3.3" @@ -934,9 +1000,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.4" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" dependencies = [ "aho-corasick", "memchr", @@ -956,14 +1022,31 @@ dependencies = [ "cairo-rs", "cairo-sys-rs", "env_logger", + "freedesktop_entry_parser", "fuzzy-matcher", "log", "rayon", + "walkdir", "winit", "xcb", "xcb-util", ] +[[package]] +name = "ryu" +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 = "scoped-tls" version = "1.0.0" @@ -1013,6 +1096,12 @@ dependencies = [ "wayland-protocols", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.9.3" @@ -1066,6 +1155,12 @@ dependencies = [ "version-compare", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "termcolor" version = "1.1.2" @@ -1137,6 +1232,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[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 = "wasm-bindgen" version = "0.2.78" @@ -1338,6 +1444,12 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "x11-dl" version = "2.19.1" @@ -1375,7 +1487,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" dependencies = [ - "nom", + "nom 7.0.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 07a6a67..618d231 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,4 +16,7 @@ cairo-sys-rs = {version = "0.14.0", features = ["xcb"]} xcb = "0.9.0" xcb-util = {version = "0.3.0", features = ["ewmh", "icccm"]} -fuzzy-matcher = "0.3.7" \ No newline at end of file +fuzzy-matcher = "0.3.7" + +walkdir = "2.3.2" +freedesktop_entry_parser = "1.2.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 50ff169..32ef83b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,7 +13,7 @@ mod ui; mod sources; mod matcher; -use roftl::{Roftl, Entry}; +use roftl::Roftl; fn main() -> Result<(), Box> { env_logger::init(); @@ -22,6 +22,7 @@ fn main() -> Result<(), Box> { let mut roftl = roftl::Roftl::new() .add_source(sources::TestSource::new("ts1")) .add_source(sources::Window::new()) + .add_source(sources::Apps::new()) .with_matcher(SkimMatcher::new()); debug!{"Source roftl sources"} diff --git a/src/roftl.rs b/src/roftl.rs index 6d7d206..86029bb 100644 --- a/src/roftl.rs +++ b/src/roftl.rs @@ -1,7 +1,8 @@ -use std::{any::type_name, collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}, usize}; +use std::{collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}, usize}; + use log::debug; -use rayon::{iter::{IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, slice::ParallelSliceMut}; +use rayon::{iter::{IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}, slice::ParallelSliceMut}; use super::matcher::PrefixMatcher; @@ -69,7 +70,7 @@ impl Roftl { .flat_map(|s| s.entries()) .collect(); - println!("Entries {:?}", self.entries); + debug!("Entries {:?}", self.entries); } pub fn narrow(&self, input: &str) -> Vec<&Entry> { diff --git a/src/sources/apps.rs b/src/sources/apps.rs new file mode 100644 index 0000000..e3ccfcf --- /dev/null +++ b/src/sources/apps.rs @@ -0,0 +1,60 @@ +use freedesktop_entry_parser as parser; +use log::debug; +use walkdir::WalkDir; + +use crate::roftl::{Action, Entry, Source}; + +pub struct Apps {} + +impl Apps { + pub fn new() -> Box + { + Box::new(Apps{}) + } +} + +impl Source for Apps { + fn name(&self) -> &'static str { + "apps" + } + + fn entries(&mut self) -> Vec { + let paths = vec![ + "/usr/share/applications/", + "~/.local/share/applications/", + "/var/lib/snapd/desktop/applications", + "/var/lib/flatpak/exports/share/applications" + ]; + + let desktop_entries: Vec = paths + .iter() + .flat_map(|p| WalkDir::new(p).into_iter()) + .filter_map(|e| e.ok()) + .filter(|e| e.path().extension().map_or(false, |ext| ext.eq("desktop"))) + .filter_map(|e| parser::parse_entry(e.path()).ok()) + .collect(); + + let mut entries: Vec = vec![]; + for entry in desktop_entries { + match entry.section("Desktop Entry").attr("Name") + { + Some(name) => entries.push( + Entry{name: name.clone().into(), + description: "".into(), + source: self.name(), + identifier: 0} + ), + + None => continue + } + } + + debug!{"Got desktop entries: {:?}", entries} + + entries + } + + fn action(&self, entry: &Entry, action: Action) { + todo!() + } +} diff --git a/src/sources/mod.rs b/src/sources/mod.rs index 314ddc8..f2ce762 100644 --- a/src/sources/mod.rs +++ b/src/sources/mod.rs @@ -3,3 +3,6 @@ pub use test::TestSource; mod windows; pub use windows::Window; + +mod apps; +pub use apps::Apps; diff --git a/src/sources/test.rs b/src/sources/test.rs index 34eb13f..653e363 100644 --- a/src/sources/test.rs +++ b/src/sources/test.rs @@ -8,7 +8,7 @@ impl TestSource { pub fn new(s: &str) -> Box { let mut ts = Box::new(TestSource { entries: vec![] }); - (1..100).for_each(|i| { + (1..1).for_each(|i| { ts.add_entry( format! {"Test {} {}", i, s}, format! {"Test {} description", i}, diff --git a/src/sources/windows.rs b/src/sources/windows.rs index 7f68d42..5b83b84 100644 --- a/src/sources/windows.rs +++ b/src/sources/windows.rs @@ -2,19 +2,19 @@ use std::collections::HashMap; use std::ptr; use crate::roftl::{Entry, Source, Action}; +use log::debug; use xcb::ffi::XCB_CURRENT_TIME; use xcb_util::ewmh; use xcb_util::ffi::ewmh::XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER; use xcb_util::icccm; pub struct Window { - windows: Vec, action_data: HashMap } impl Window { pub fn new() -> Box { - Box::new(Window { windows: vec![], action_data: HashMap::::new() }) + Box::new(Window { action_data: HashMap::::new() }) } fn is_normal_window(&self, con: &ewmh::Connection, window: u32) -> Result { @@ -73,7 +73,7 @@ impl Source for Window { let title = self.window_title(&ewmh_conn, *w).unwrap(); let category = self.window_category(&ewmh_conn, *w).unwrap(); - println!("Found window {} - {}", title, category); + debug!("Found window {} - {}", title, category); entries.push(Entry{source: self.name(), name: category, description: title, identifier: count}); self.action_data.insert(count, (*w, screen_num)); diff --git a/src/ui/painter.rs b/src/ui/painter.rs index 5c49c25..25b12b7 100644 --- a/src/ui/painter.rs +++ b/src/ui/painter.rs @@ -34,7 +34,7 @@ impl Default for Theme { input_font_size: 20.0, result_bg: (0.5, 0.5, 1.0, 1.0), - result_bg_selected: (0.5, 0.5, 0.5, 1.0), + result_bg_selected: (0.5, 0.5, 0.9, 1.0), result_font_color: (0.0, 0.0, 1.0, 1.0), result_font_selected: (0.5, 0.5, 0.5, 1.0), result_font_size: 20.0, @@ -151,10 +151,6 @@ impl<'a> Painter<'a> { self.context.device_to_user_distance(point, point).unwrap().0 } - fn user_to_device(&self, point: f64) -> f64 { - self.context.user_to_device_distance(point, point).unwrap().0 - } - fn clip_width(&self) -> f64 { let (x1,_y1,x2,_y2) = self.context.clip_extents().unwrap(); x2 - x1