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::io::{Write, Error};
use xdg::BaseDirectories;
use config_file::FromConfigFile;
use serde::Deserialize;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Deserialize,Clone)]
#[derive(Serialize,Deserialize,Clone)]
pub struct WindowIcon {
pub icon: 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 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 crate::{config::Config, Cli};
//#[path = "../results.rs"]
mod results;
use results::WindowInfo;
#[derive(serde::Serialize)]
pub struct WindowInfo {
pub title: String
}
pub fn print_window_title(window_node: Node,cli: &Cli,config: &Config) {
let mut window_title_display: String = window_node.name.unwrap();

View file

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

View file

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