approaching first major release

This commit is contained in:
Penelope Gwen 2025-09-17 00:07:21 -07:00
parent 4100c0dff9
commit 9add5c827f
5 changed files with 159 additions and 56 deletions

View file

@ -1,31 +1,34 @@
use std::fs::File; use std::collections::HashMap;
//use std::io::{Write, Error}; use serde::{Deserialize, Serialize};
use xdg::BaseDirectories;
use config_file::FromConfigFile;
use serde::Deserialize;
#[derive(Deserialize,Clone)] #[derive(Serialize,Deserialize,Clone)]
pub struct WindowIcon { pub struct WindowIcon {
pub icon: String, pub icon: String,
pub substring: String pub substring: String
} }
#[derive(Deserialize, Default)] #[derive(Serialize,Deserialize,Clone,Debug)]
pub struct BrowserConf {
pub profile: String,
pub startpage: String
}
#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct Profile {
pub name: String,
pub icon: String,
pub browser: BrowserConf,
pub directory: String
}
#[derive(Serialize,Deserialize,Clone,Debug)]
pub struct Programs {
pub name: String,
pub command: String,
pub arguments: Vec<String>
}
#[derive(Serialize,Deserialize,Default)]
pub struct Config { pub struct Config {
pub title_length: usize, pub title_length: usize,
pub window_icons: Vec<WindowIcon> pub window_icons: Vec<WindowIcon>,
pub wallpaper_path: String,
pub programs: HashMap<String, Programs>,
pub profiles: HashMap<String, Profile>
} }
pub fn parse_config() -> Config {
let xdg_dirs = BaseDirectories::with_prefix("sway-profiles-rs");
let config_path = xdg_dirs
.place_config_file("config.toml")
.expect("cannot create configuration directory");
// println!("{}",config_path.exists());
if !config_path.exists() {
let _ = File::create(&config_path);
// let config_file = File::create(&config_path);
// write!(&mut config_file, "title_length = 20");
}
Config::from_config_file(config_path).unwrap()
}

View file

@ -1 +1,73 @@
use use std::{env::consts, fs::{self, exists}, io, ops::Sub, path::{Path, PathBuf}};
use walkdir::WalkDir;
use image::imageops::GaussianBlurParameters;
use serde::{Deserialize, Serialize};
use serde_json::json;
use sha2::{Sha256, Digest};
use swayipc::Connection;
use xdg::BaseDirectories;
use shellexpand::tilde;
use crate::config::Config;
#[derive(Serialize,Deserialize,Debug)]
pub struct WallpaperCache {
pub display: String,
pub hash: String
}
pub fn lock_screen(config: &Config, mut sway_connection: Connection) {
let wallpaper_root_path = tilde(&config.wallpaper_path).to_string();
let wallpaper_root_path = Path::new(&wallpaper_root_path);
let cache_dir = BaseDirectories::with_prefix("sway-profiles-rs").cache_home;
let wp_cache_dir = cache_dir.clone().unwrap().join("sway-profiles-rs/lock/");
let mut wp_hash_json: Vec<WallpaperCache> = vec![];
let hashes_json_path = wp_cache_dir.join("hashes.json");
if exists(&hashes_json_path).unwrap() {
let file = fs::File::open(&hashes_json_path).unwrap();
wp_hash_json = serde_json::from_reader(file).unwrap();
}
let mut wp_hash_array: Vec<WallpaperCache> = vec![];
for output in sway_connection.get_outputs().unwrap() {
let sway_workspaces = sway_connection.get_workspaces().unwrap().clone();
let output_ws_num = format!("{:0>2}",sway_workspaces.iter().find(|x|x.name == output.current_workspace
.clone().unwrap()).unwrap().num.sub(1)).chars().next().unwrap();
let image_path = wallpaper_root_path.join(output.name.clone()).join(format!("p_{}.jpg",output_ws_num));
let mut img_file_data = fs::File::open(&image_path).unwrap();
let mut sha256 = Sha256::new();
let _ = io::copy(&mut img_file_data, &mut sha256);
let hash = format!("{:x}",sha256.finalize());
wp_hash_array.push(WallpaperCache { display: output.name.clone(), hash: hash.clone() });
if let Some(output_saved_hash) = wp_hash_json.iter().find(|x|x.display == output.name) && output_saved_hash.hash.ne(&hash) {
let img_data = image::open(image_path).unwrap();
let blurred_img_data = img_data
.resize((img_data.width() as f64 * 0.75) as u32, (img_data.height() as f64 * 0.75) as u32, image::imageops::FilterType::Nearest)
.blur_advanced(GaussianBlurParameters::new_from_sigma(10.0));
let blurred_image_path = cache_dir.clone().unwrap().join(format!("sway-profiles-rs/lock/{}.jpg",output.name));
let _ = blurred_img_data.save(blurred_image_path);
}
}
let gtklock_modules_dir = "/usr/lib/".to_owned() + consts::ARCH + "-linux-gnu/gtklock/";
let gktlock_modules_path = Path::new(&gtklock_modules_dir);
let mut gtklock_args: Vec<String> = vec![];
for file in WalkDir::new(gktlock_modules_path).into_iter() {//.find(|x|x.as_ref().unwrap().file_name().to_str().unwrap().ends_with("-module.so")) {
if let Some(f) = file.iter().find(|&x|x.path().to_str().unwrap().ends_with("-module.so")) {
gtklock_args.push("-m".to_owned());
gtklock_args.push(f.path().to_str().unwrap().to_string());
}
}
let new_json = json!(wp_hash_array);
let _ = std::fs::write::<PathBuf, String>(hashes_json_path, new_json.to_string());
let mut gtklock_command = "exec gtklock".to_owned();
for a in gtklock_args {
gtklock_command = gtklock_command + " " + &a;
}
println!("{:?}",gtklock_command);
let _ = sway_connection.run_command(gtklock_command);
}

View file

@ -3,9 +3,10 @@ use serde_json::json;
use swayipc::Node; use swayipc::Node;
use crate::{config::Config, Cli}; use crate::{config::Config, Cli};
//#[path = "../results.rs"] #[derive(serde::Serialize)]
mod results; pub struct WindowInfo {
use results::WindowInfo; pub title: String
}
pub fn print_window_title(window_node: Node,cli: &Cli,config: &Config) { pub fn print_window_title(window_node: Node,cli: &Cli,config: &Config) {
let mut window_title_display: String = window_node.name.unwrap(); let mut window_title_display: String = window_node.name.unwrap();

View file

@ -1,9 +1,13 @@
use serde_json::json; use serde_json::json;
use swayipc::Workspace; use swayipc::Workspace;
//#[path = "../results.rs"] #[derive(serde::Serialize)]
mod results; pub struct WorkspaceInfo {
use results::WorkspaceInfo; pub num: i32,
pub name: String,
pub is_focused: bool,
pub position: char
}
pub fn print_workspace_array(workspaces: Vec<Workspace>) { pub fn print_workspace_array(workspaces: Vec<Workspace>) {
let current_ws = workspaces.iter().find(|&x| x.focused).unwrap().num; let current_ws = workspaces.iter().find(|&x| x.focused).unwrap().num;

View file

@ -1,9 +1,10 @@
use std::process::exit; use std::process::exit;
use clap::{Parser,Subcommand,ArgAction}; use clap::{Parser,Subcommand,ArgAction};
use swayipc::{Connection, Event, EventType, Fallible}; use swayipc::{Connection, Event, EventType, Fallible};
mod config; mod config;
#[path = "lib/windows.rs"] #[path = "lib/windows.rs"]
mod windows; mod windows;
@ -11,9 +12,11 @@ use windows::print_window_title;
#[path = "lib/workspaces.rs"] #[path = "lib/workspaces.rs"]
mod workspaces; mod workspaces;
use workspaces::print_workspace_array; use workspaces::print_workspace_array;
#[path = "lib/lock.rs"]
mod lock;
use lock::lock_screen;
use crate::config::Config; use config::Config;
mod monitor;
#[derive(Parser)] #[derive(Parser)]
@ -43,12 +46,16 @@ pub struct Cli {
enum Commands { enum Commands {
/// Prints the Currently Active Window Title /// Prints the Currently Active Window Title
Windows, Windows,
// Prints the Currently Active Workspace layout /// Prints the Currently Active Workspace layout
Workspaces, Workspaces,
// Launch Program with Current Profile's Configuration /// Launch Program with Current Workspace's Profile Configuration
Launch, Launch {
#[arg(short, long)]
program: String
},
/// Set up blurred wallpaper for screen lock, and load gtklock modules
Lock, Lock,
Rename, //Rename,
Profile, Profile,
Shortcuts { Shortcuts {
#[arg(short, long, action = ArgAction::SetTrue)] #[arg(short, long, action = ArgAction::SetTrue)]
@ -73,35 +80,52 @@ enum MonitorTypes {
} }
fn main() -> Fallible<()> { fn main() -> Fallible<()> {
//let xdg_dirs = BaseDirectories::with_prefix("sway-profiles-rs");
let cli = Cli::parse(); let cli = Cli::parse();
let config = config::parse_config(); // let config = config::parse_config();
if let Some(no_truncate_title) = cli.no_truncate_title { let config = confy::load("sway-profiles-rs", "config").unwrap();
println!("Value for no_truncate_title: {no_truncate_title}");
}
let mut sway_connection = Connection::new()?; let mut sway_connection = Connection::new()?;
match &cli.command { match &cli.command {
Commands::Windows => { Commands::Windows => {
print_window_title(sway_connection.get_tree().iter().find(|&x | x.focused).unwrap().clone(), &cli, &config); print_window_title(sway_connection.get_tree().unwrap().iter().find(|&x | x.focused).unwrap().clone(), &cli, &config);
if cli.monitor.unwrap() { if cli.monitor.unwrap() {
let _ = monitor_events(EventType::Window, cli, config); monitor_events(EventType::Window, cli, config);
} }
} }
Commands::Workspaces => { Commands::Workspaces => {
print_workspace_array(sway_connection.get_workspaces().unwrap()); print_workspace_array(sway_connection.get_workspaces().unwrap());
if cli.monitor.unwrap() { if cli.monitor.unwrap() {
let _ = monitor_events(EventType::Workspace, cli, config); monitor_events(EventType::Workspace, cli, config);
} }
} }
Commands::Launch => todo!(), Commands::Launch { program } => {
Commands::Lock => todo!(), if let Some(launch_program) = config.programs.iter().find(|x|x.0 == program) {
Commands::Rename => todo!(), println!("found: {:#?} {:?}",launch_program.1.command, launch_program.1.arguments);
Commands::Profile => todo!(), let mut swaymsg_command = "exec ".to_owned() + &launch_program.1.command;
Commands::Shortcuts { global } => todo!(), for a in &launch_program.1.arguments {
swaymsg_command = swaymsg_command + " " + a;
}
println!("{:#?}",swaymsg_command);
let _ = sway_connection.run_command(swaymsg_command);
}
},
Commands::Lock => {
lock_screen(&config, sway_connection);
},
//Commands::Rename => todo!(),
Commands::Profile => {
println!("{:?}", config.profiles.len());
for p in config.profiles {
println!("{:?} {:?}",p.0, p.1.name )
}
},
Commands::Shortcuts { global: _ } => todo!(),
} }
exit(0); exit(0);
} }
pub fn monitor_events(event_type: EventType, cli: Cli, config: Config) -> Fallible<()> { pub fn monitor_events(event_type: EventType, cli: Cli, config: Config) {
/* let subs = [ /* let subs = [
// Valid EventTypes: Workspace, Output, Input, Tick, Shutdown, Mode, Window, BarStateUpdate, BarConfigUpdate, Binding // Valid EventTypes: Workspace, Output, Input, Tick, Shutdown, Mode, Window, BarStateUpdate, BarConfigUpdate, Binding
//EventType::Workspace, //EventType::Workspace,
@ -109,14 +133,14 @@ pub fn monitor_events(event_type: EventType, cli: Cli, config: Config) -> Fallib
//EventType::Window, //EventType::Window,
event_type event_type
]; */ ]; */
let sway_connection = Connection::new()?; let sway_connection = Connection::new().unwrap();
for event in sway_connection.subscribe([event_type])? { for event in sway_connection.subscribe([event_type]).unwrap() {
let e = event?; let e = event.unwrap();
match e { match e {
Event::Window(w) => { Event::Window(w) => {
print_window_title(w.container, &cli, &config); print_window_title(w.container, &cli, &config);
}, },
Event::Workspace(w) => { Event::Workspace(_) => {
print_workspace_array(self::Connection::get_workspaces(&mut self::Connection::new().unwrap()).unwrap()); print_workspace_array(self::Connection::get_workspaces(&mut self::Connection::new().unwrap()).unwrap());
}, },
Event::Tick(w) => { Event::Tick(w) => {
@ -125,5 +149,4 @@ pub fn monitor_events(event_type: EventType, cli: Cli, config: Config) -> Fallib
_ => unreachable!(), _ => unreachable!(),
} }
} }
Ok(())
} }