File search on the way
This commit is contained in:
parent
53e45fa232
commit
47dd0c752a
98
Cargo.lock
generated
98
Cargo.lock
generated
@ -89,6 +89,27 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "directories"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"option-ext",
|
||||||
|
"redox_users",
|
||||||
|
"windows-sys 0.60.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@ -583,6 +604,16 @@ version = "0.2.175"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@ -658,6 +689,12 @@ version = "1.21.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
@ -727,6 +764,17 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4"
|
name = "relm4"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
@ -787,6 +835,15 @@ dependencies = [
|
|||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -879,6 +936,26 @@ version = "0.13.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.47.1"
|
version = "1.47.1"
|
||||||
@ -990,6 +1067,16 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
@ -1057,6 +1144,7 @@ dependencies = [
|
|||||||
name = "waycast"
|
name = "waycast"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"directories",
|
||||||
"gio",
|
"gio",
|
||||||
"glib",
|
"glib",
|
||||||
"gtk4",
|
"gtk4",
|
||||||
@ -1064,6 +1152,16 @@ dependencies = [
|
|||||||
"relm4",
|
"relm4",
|
||||||
"relm4-components",
|
"relm4-components",
|
||||||
"tracker",
|
"tracker",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
directories = "6.0.0"
|
||||||
gio = "0.21.1"
|
gio = "0.21.1"
|
||||||
glib = "0.21.1"
|
glib = "0.21.1"
|
||||||
gtk = { version = "0.10.0", package = "gtk4" }
|
gtk = { version = "0.10.0", package = "gtk4" }
|
||||||
@ -11,3 +12,4 @@ gtk4-layer-shell = "0.6.1"
|
|||||||
relm4 = "0.10.0"
|
relm4 = "0.10.0"
|
||||||
relm4-components = "0.10.0"
|
relm4-components = "0.10.0"
|
||||||
tracker = "0.2.2"
|
tracker = "0.2.2"
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
@ -15,6 +15,7 @@ pub trait LauncherListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait LauncherPlugin {
|
pub trait LauncherPlugin {
|
||||||
|
fn init(&self);
|
||||||
fn name(&self) -> String;
|
fn name(&self) -> String;
|
||||||
fn priority(&self) -> i32;
|
fn priority(&self) -> i32;
|
||||||
fn description(&self) -> Option<String>;
|
fn description(&self) -> Option<String>;
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
use std::env;
|
||||||
use waycast::plugins;
|
use waycast::plugins;
|
||||||
use waycast::ui::WaycastLauncher;
|
use waycast::ui::WaycastLauncher;
|
||||||
|
|
||||||
|
// TODO: Add an init() function to the launcher plugin spec
|
||||||
|
// that will get called when loaded. That way plugins like
|
||||||
|
// file search can index the file system on init instead
|
||||||
|
// of on the fly
|
||||||
fn main() {
|
fn main() {
|
||||||
let app = Application::builder()
|
let app = Application::builder()
|
||||||
.application_id("dev.thegrind.waycast")
|
.application_id("dev.thegrind.waycast")
|
||||||
@ -11,7 +16,7 @@ fn main() {
|
|||||||
app.connect_activate(|app| {
|
app.connect_activate(|app| {
|
||||||
let launcher = WaycastLauncher::new()
|
let launcher = WaycastLauncher::new()
|
||||||
.add_plugin(plugins::drun::DrunPlugin {})
|
.add_plugin(plugins::drun::DrunPlugin {})
|
||||||
.add_plugin(plugins::file_search::FileSearchPlugin {})
|
.add_plugin(plugins::file_search::FileSearchPlugin::new())
|
||||||
.initialize(app);
|
.initialize(app);
|
||||||
|
|
||||||
launcher.borrow().show();
|
launcher.borrow().show();
|
||||||
|
@ -85,6 +85,10 @@ pub fn get_desktop_entries() -> Vec<DesktopEntry> {
|
|||||||
pub struct DrunPlugin {}
|
pub struct DrunPlugin {}
|
||||||
|
|
||||||
impl LauncherPlugin for DrunPlugin {
|
impl LauncherPlugin for DrunPlugin {
|
||||||
|
fn init(&self) {
|
||||||
|
// TODO: Load apps into memory
|
||||||
|
// TODO: Find and cache Icons
|
||||||
|
}
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
return String::from("drun");
|
return String::from("drun");
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,128 @@
|
|||||||
|
use directories::UserDirs;
|
||||||
|
use gio::prelude::FileExt;
|
||||||
|
use glib::object::Cast;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::{cell::RefCell, env};
|
||||||
|
use walkdir::{DirEntry, WalkDir};
|
||||||
|
|
||||||
use crate::{LaunchError, LauncherListItem, LauncherPlugin};
|
use crate::{LaunchError, LauncherListItem, LauncherPlugin};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct FileEntry {
|
struct FileEntry {
|
||||||
title: String,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LauncherListItem for ExampleEntry {
|
impl FileEntry {
|
||||||
|
fn from(entry: DirEntry) -> Self {
|
||||||
|
return FileEntry {
|
||||||
|
path: entry.into_path(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LauncherListItem for FileEntry {
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
return self.title.to_string();
|
return String::from(self.path.file_name().unwrap().to_string_lossy());
|
||||||
}
|
}
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> Option<String> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&self) -> Result<(), LaunchError> {
|
fn execute(&self) -> Result<(), LaunchError> {
|
||||||
println!("Sample item clicked: {}", self.title);
|
let file_uri = gio::File::for_path(&self.path);
|
||||||
Ok(())
|
match gio::AppInfo::launch_default_for_uri(
|
||||||
|
file_uri.uri().as_str(),
|
||||||
|
None::<&gio::AppLaunchContext>,
|
||||||
|
) {
|
||||||
|
Err(_) => Err(LaunchError::CouldNotLaunch(
|
||||||
|
"Error opening file".to_string(),
|
||||||
|
)),
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn icon(&self) -> String {
|
fn icon(&self) -> String {
|
||||||
return String::from("vscode");
|
let (content_type, _) = gio::content_type_guess(Some(&self.path), None);
|
||||||
|
|
||||||
|
let icon = gio::content_type_get_icon(&content_type);
|
||||||
|
|
||||||
|
if let Some(themed_icon) = icon.downcast_ref::<gio::ThemedIcon>() {
|
||||||
|
if let Some(icon_name) = themed_icon.names().first() {
|
||||||
|
return icon_name.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String::from("text-x-generic")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileSearchPlugin {}
|
pub struct FileSearchPlugin {
|
||||||
|
search_paths: Vec<PathBuf>,
|
||||||
|
skip_dirs: Vec<String>,
|
||||||
|
// Running list of files in memory
|
||||||
|
files: RefCell<Vec<FileEntry>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileSearchPlugin {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
return FileSearchPlugin {
|
||||||
|
search_paths: Vec::new(),
|
||||||
|
skip_dirs: vec![
|
||||||
|
String::from("vendor"),
|
||||||
|
String::from("node_modules"),
|
||||||
|
String::from("cache"),
|
||||||
|
String::from("zig-cache"),
|
||||||
|
],
|
||||||
|
files: RefCell::new(Vec::new()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip_hidden(entry: &DirEntry) -> bool {
|
||||||
|
entry
|
||||||
|
.file_name()
|
||||||
|
.to_str()
|
||||||
|
.map(|s| s.starts_with("."))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skip_dir(entry: &DirEntry, dirs: &Vec<String>) -> bool {
|
||||||
|
entry
|
||||||
|
.file_name()
|
||||||
|
.to_str()
|
||||||
|
.map(|n| dirs.contains(&String::from(n)))
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
impl LauncherPlugin for FileSearchPlugin {
|
impl LauncherPlugin for FileSearchPlugin {
|
||||||
|
fn init(&self) {
|
||||||
|
// let home = env::home_dir().unwrap();
|
||||||
|
if let Some(ud) = UserDirs::new() {
|
||||||
|
let scan = [
|
||||||
|
ud.document_dir(),
|
||||||
|
ud.picture_dir(),
|
||||||
|
ud.audio_dir(),
|
||||||
|
ud.video_dir(),
|
||||||
|
];
|
||||||
|
|
||||||
|
for p in scan {
|
||||||
|
match p {
|
||||||
|
Some(path) => {
|
||||||
|
let walker = WalkDir::new(path).into_iter();
|
||||||
|
for entry in walker
|
||||||
|
.filter_entry(|e| !skip_hidden(e) && !skip_dir(e, &self.skip_dirs))
|
||||||
|
.filter_map(|e| e.ok())
|
||||||
|
{
|
||||||
|
if entry.path().is_file() {
|
||||||
|
self.files.borrow_mut().push(FileEntry::from(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> String {
|
||||||
return String::from("File search");
|
return String::from("File search");
|
||||||
}
|
}
|
||||||
@ -48,6 +148,21 @@ impl LauncherPlugin for FileSearchPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filter(&self, query: &str) -> Vec<Box<dyn LauncherListItem>> {
|
fn filter(&self, query: &str) -> Vec<Box<dyn LauncherListItem>> {
|
||||||
self.default_list()
|
if query.is_empty() {
|
||||||
|
return self.default_list();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut entries: Vec<Box<dyn LauncherListItem>> = Vec::new();
|
||||||
|
let files = self.files.borrow();
|
||||||
|
for f in files.iter() {
|
||||||
|
if let Some(file_name) = f.path.file_name() {
|
||||||
|
let cmp = file_name.to_string_lossy().to_lowercase();
|
||||||
|
if cmp.contains(&query.to_lowercase()) {
|
||||||
|
entries.push(Box::new(f.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ use gtk4_layer_shell as layerShell;
|
|||||||
use layerShell::LayerShell;
|
use layerShell::LayerShell;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
mod launcher_builder;
|
mod launcher_builder;
|
||||||
@ -155,6 +156,7 @@ impl WaycastLauncher {
|
|||||||
plugins_by_prefix,
|
plugins_by_prefix,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
model.borrow().init_plugins();
|
||||||
// Populate the list
|
// Populate the list
|
||||||
model.borrow_mut().populate_list();
|
model.borrow_mut().populate_list();
|
||||||
|
|
||||||
@ -165,7 +167,6 @@ impl WaycastLauncher {
|
|||||||
let model_clone = model.clone();
|
let model_clone = model.clone();
|
||||||
search_input.connect_changed(move |entry| {
|
search_input.connect_changed(move |entry| {
|
||||||
let query = entry.text().to_string();
|
let query = entry.text().to_string();
|
||||||
println!("query: {query}");
|
|
||||||
model_clone.borrow_mut().filter_list(&query);
|
model_clone.borrow_mut().filter_list(&query);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -263,6 +264,12 @@ impl WaycastLauncher {
|
|||||||
model
|
model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_plugins(&self) {
|
||||||
|
for plugin in &self.plugins {
|
||||||
|
plugin.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clear_list_ui(&self) {
|
pub fn clear_list_ui(&self) {
|
||||||
while let Some(child) = self.list_box.first_child() {
|
while let Some(child) = self.list_box.first_child() {
|
||||||
self.list_box.remove(&child);
|
self.list_box.remove(&child);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user