Added projects plugin
This commit is contained in:
parent
8c5b9f9295
commit
bf443a27fd
84
tmp.txt
Normal file
84
tmp.txt
Normal file
@ -0,0 +1,84 @@
|
||||
cargo run -p waycast-gtk
|
||||
/home/javi/projects/homelab-ansible
|
||||
/home/javi/projects/gla-old
|
||||
/home/javi/projects/filebrowser-agent
|
||||
/home/javi/projects/ttrpg-cms
|
||||
/home/javi/projects/desktop-setup
|
||||
/home/javi/projects/ravensofravnica.stream
|
||||
/home/javi/projects/nix
|
||||
/home/javi/projects/demos
|
||||
/home/javi/projects/resumeforge.app
|
||||
/home/javi/projects/videos
|
||||
/home/javi/projects/authentikate.dev
|
||||
/home/javi/projects/blogimage.app
|
||||
/home/javi/projects/arch-hyprland-setup
|
||||
/home/javi/projects/laravel-dockerized
|
||||
/home/javi/projects/alex-nix-config
|
||||
/home/javi/projects/thegrind-tools
|
||||
/home/javi/projects/imgsrc-app
|
||||
/home/javi/projects/scripthost
|
||||
/home/javi/projects/foundryvtt-docker
|
||||
/home/javi/projects/launchlet.app
|
||||
/home/javi/projects/yourfluence.dev
|
||||
/home/javi/projects/thegrind.dev
|
||||
/home/javi/projects/opnsensebackup
|
||||
/home/javi/projects/project-picker
|
||||
/home/javi/projects/thegrind.dev-old-jigsaw
|
||||
/home/javi/projects/og-cli
|
||||
/home/javi/projects/do-flow
|
||||
/home/javi/projects/carti-python
|
||||
/home/javi/projects/rack-planner
|
||||
/home/javi/projects/ember-db
|
||||
/home/javi/projects/local-ai
|
||||
/home/javi/projects/zap
|
||||
/home/javi/projects/flowtodo
|
||||
/home/javi/projects/temp
|
||||
/home/javi/projects/blog-backup
|
||||
/home/javi/projects/javierfeliz.com
|
||||
/home/javi/projects/thc-demo
|
||||
/home/javi/projects/crawler-linkedin
|
||||
/home/javi/projects/vikunja-planka-transfer
|
||||
/home/javi/projects/desktop-backup
|
||||
/home/javi/projects/authentikate
|
||||
/home/javi/projects/scratchfl.com
|
||||
/home/javi/projects/cs-trade-bot
|
||||
/home/javi/projects/leetcode
|
||||
/home/javi/projects/screenshotter
|
||||
/home/javi/projects/docker-compose-builder
|
||||
/home/javi/projects/javif89
|
||||
/home/javi/projects/papibot
|
||||
/home/javi/projects/crypt
|
||||
/home/javi/projects/analysis
|
||||
/home/javi/projects/go-starter-kit
|
||||
/home/javi/projects/vue3-learning
|
||||
/home/javi/projects/homelab-docker
|
||||
/home/javi/projects/sitemapper
|
||||
/home/javi/projects/dotnet-deployment-ansible
|
||||
/home/javi/projects/planka
|
||||
/home/javi/projects/waycast-cpp
|
||||
/home/javi/projects/hubspot-assessment
|
||||
/home/javi/projects/go-doit
|
||||
/home/javi/projects/alex-demo
|
||||
/home/javi/projects/docker-laravel-base
|
||||
/home/javi/projects/staticforge
|
||||
/home/javi/projects/jigsaw
|
||||
/home/javi/projects/theresaleconcierge
|
||||
/home/javi/projects/nico-stuff
|
||||
/home/javi/projects/zold-javierfeliz.com
|
||||
/home/javi/projects/ansible-starter-kit
|
||||
/home/javi/projects/oidctester
|
||||
/home/javi/projects/waycast
|
||||
/home/javi/projects/ubuntu-setup
|
||||
/home/javi/projects/caddy-test
|
||||
/home/javi/projects/dotfiles
|
||||
/home/javi/projects/bazzitouchedhisconfig.dev
|
||||
/home/javi/projects/cs2-server-manager
|
||||
/home/javi/projects/noconfig
|
||||
/home/javi/projects/gamelineanalytics.com
|
||||
/home/javi/projects/thegrind-de
|
||||
/home/javi/projects/data-parser
|
||||
/home/javi/projects/test-dotnet-blazor-project
|
||||
/home/javi/projects/homies
|
||||
/home/javi/projects/ogimage-click
|
||||
/home/javi/projects/ansible-on-prem
|
||||
Projects plugin: Found 82 projects
|
@ -20,10 +20,17 @@ fn main() {
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mut project_plugin = waycast_plugins::projects::new();
|
||||
match project_plugin.add_search_path("/home/javi/projects") {
|
||||
Err(e) => eprintln!("{}", e),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Create the core launcher
|
||||
let launcher = WaycastLauncher::new()
|
||||
.add_plugin(Box::new(waycast_plugins::drun::new()))
|
||||
.add_plugin(Box::new(file_search_plugin))
|
||||
.add_plugin(Box::new(project_plugin))
|
||||
.init();
|
||||
|
||||
// Create and show the GTK UI
|
||||
|
@ -1,5 +1,6 @@
|
||||
pub mod drun;
|
||||
pub mod file_search;
|
||||
pub mod projects;
|
||||
|
||||
// Re-export the macros for external use
|
||||
pub use waycast_macros::{plugin, launcher_entry};
|
||||
pub use waycast_macros::{launcher_entry, plugin};
|
||||
|
182
waycast-plugins/src/projects.rs
Normal file
182
waycast-plugins/src/projects.rs
Normal file
@ -0,0 +1,182 @@
|
||||
// TODO: Use the user's preferred editor.
|
||||
// This should just be in the config when I implement
|
||||
// that eventually since figuring out every editor's
|
||||
// launch option would be a pain. The user can just
|
||||
// configure launch_command and pass a parameter.
|
||||
// Example: code -n {path}
|
||||
// and I'll just regex in the path.
|
||||
// TODO: Project type detection and icon
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use tokio::sync::Mutex;
|
||||
use waycast_core::{LaunchError, LauncherListItem, LauncherPlugin};
|
||||
use waycast_macros::{launcher_entry, plugin};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProjectEntry {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl LauncherListItem for ProjectEntry {
|
||||
launcher_entry! {
|
||||
id: self.path.to_string_lossy().to_string(),
|
||||
title: String::from(self.path.file_name().unwrap().to_string_lossy()),
|
||||
description: Some(self.path.to_string_lossy().to_string()),
|
||||
icon: {
|
||||
String::from("vscode")
|
||||
},
|
||||
execute: {
|
||||
println!("Executing: {}", self.path.display());
|
||||
|
||||
// Use xdg-open directly since it works properly with music files
|
||||
match Command::new("code").arg("-n").arg(&self.path).spawn() {
|
||||
Ok(_) => {
|
||||
println!("Successfully opened with code");
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Err(LaunchError::CouldNotLaunch("Failed to open project folder".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ProjectsPlugin {
|
||||
search_paths: Vec<PathBuf>,
|
||||
skip_dirs: Vec<String>,
|
||||
// Running list of files in memory
|
||||
files: Arc<Mutex<Vec<ProjectEntry>>>,
|
||||
}
|
||||
|
||||
impl ProjectsPlugin {
|
||||
pub fn add_search_path<P: AsRef<Path>>(&mut self, path: P) -> Result<(), String> {
|
||||
let p = path.as_ref();
|
||||
|
||||
if !p.exists() {
|
||||
return Err(format!("Path does not exist: {}", p.display()));
|
||||
}
|
||||
|
||||
if !p.is_dir() {
|
||||
return Err(format!("Path is not a directory: {}", p.display()));
|
||||
}
|
||||
|
||||
self.search_paths.push(p.to_path_buf());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_skip_dir(&mut self, directory_name: String) -> Result<(), String> {
|
||||
self.skip_dirs.push(directory_name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn should_skip_dir(dir_name: &str, skip_dirs: &[String]) -> bool {
|
||||
skip_dirs.iter().any(|skip| skip == dir_name)
|
||||
}
|
||||
|
||||
impl LauncherPlugin for ProjectsPlugin {
|
||||
plugin! {
|
||||
name: "Projects",
|
||||
priority: 800,
|
||||
description: "Search and open code projects",
|
||||
prefix: "proj",
|
||||
init: projects_init,
|
||||
default_list: projects_default_list,
|
||||
filter: projects_filter
|
||||
}
|
||||
}
|
||||
|
||||
fn projects_default_list(_plugin: &ProjectsPlugin) -> Vec<Box<dyn LauncherListItem>> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn projects_filter(plugin: &ProjectsPlugin, query: &str) -> Vec<Box<dyn LauncherListItem>> {
|
||||
if query.is_empty() {
|
||||
return projects_default_list(plugin);
|
||||
}
|
||||
|
||||
let mut entries: Vec<Box<dyn LauncherListItem>> = Vec::new();
|
||||
|
||||
// Try to get files without blocking - if indexing is still in progress, return empty
|
||||
if let Ok(files) = plugin.files.try_lock() {
|
||||
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
|
||||
}
|
||||
|
||||
fn projects_init(plugin: &ProjectsPlugin) {
|
||||
let files_clone = Arc::clone(&plugin.files);
|
||||
let search_paths = plugin.search_paths.clone();
|
||||
let skip_dirs = plugin.skip_dirs.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(async {
|
||||
let mut project_entries = Vec::new();
|
||||
|
||||
for search_path in &search_paths {
|
||||
if let Ok(entries) = fs::read_dir(search_path) {
|
||||
for entry in entries.flatten() {
|
||||
if let Ok(file_type) = entry.file_type() {
|
||||
if file_type.is_dir() {
|
||||
let path = entry.path();
|
||||
|
||||
// Skip hidden directories (starting with .)
|
||||
if let Some(file_name) = path.file_name() {
|
||||
if let Some(name_str) = file_name.to_str() {
|
||||
// Skip hidden directories
|
||||
if name_str.starts_with('.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip directories in skip list
|
||||
if should_skip_dir(name_str, &skip_dirs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
println!("{}", path.display());
|
||||
|
||||
project_entries.push(ProjectEntry { path });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the shared files collection
|
||||
let mut files_guard = files_clone.lock().await;
|
||||
*files_guard = project_entries;
|
||||
|
||||
println!("Projects plugin: Found {} projects", files_guard.len());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn new() -> ProjectsPlugin {
|
||||
ProjectsPlugin {
|
||||
search_paths: Vec::new(),
|
||||
skip_dirs: vec![
|
||||
String::from("vendor"),
|
||||
String::from("node_modules"),
|
||||
String::from("cache"),
|
||||
String::from("zig-cache"),
|
||||
String::from(".git"),
|
||||
String::from(".svn"),
|
||||
],
|
||||
files: Arc::new(Mutex::new(Vec::new())),
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user