342 lines
11 KiB
Rust
342 lines
11 KiB
Rust
use {
|
|
crate::{
|
|
config::{Config, Profile},
|
|
get_xdg_dirs,
|
|
lib::{
|
|
SDUError,
|
|
cli::{DisplayMode, ProfileCommand, ProfileGetCommand, ProfileSwitchCommand},
|
|
get, get_sway_connection, run_sway_command, shortcuts_fn,
|
|
sway::focused_workspace_profile,
|
|
},
|
|
setup_runtime_dir,
|
|
},
|
|
log::{debug, error},
|
|
serde_json::json,
|
|
std::fs::{self, DirBuilder, write},
|
|
swayipc::Connection,
|
|
xdg::BaseDirectories,
|
|
};
|
|
|
|
pub fn profile_fn(
|
|
profile_command: &ProfileCommand,
|
|
profiles_config: Vec<Profile>,
|
|
preserve_keyboard_order: bool,
|
|
) -> Result<(), SDUError> {
|
|
let xdg_dirs = get_xdg_dirs();
|
|
setup_runtime_dir(xdg_dirs);
|
|
match profile_command {
|
|
ProfileCommand::Init => {
|
|
let active_profile_index = active_profile_index();
|
|
match switch_by_index(
|
|
profiles_config,
|
|
active_profile_index,
|
|
preserve_keyboard_order,
|
|
) {
|
|
Ok(_) => {
|
|
let _: () = debug!("successfully initialized sway-de-utils");
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
ProfileCommand::Switch { switch_command } => match switch_command {
|
|
Some(ProfileSwitchCommand::To { index, name, query }) => match index {
|
|
Some(i) => switch_by_index(profiles_config, *i, preserve_keyboard_order),
|
|
None => match name {
|
|
Some(n) => {
|
|
switch_by_name(profiles_config, n.to_string(), preserve_keyboard_order)
|
|
}
|
|
None => match query {
|
|
Some(q) => match q.parse::<usize>() {
|
|
Ok(i) => match switch_by_index(
|
|
profiles_config.clone(),
|
|
i,
|
|
preserve_keyboard_order,
|
|
) {
|
|
Ok(o) => Ok(o),
|
|
Err(_) => switch_by_name(
|
|
profiles_config,
|
|
q.to_string(),
|
|
preserve_keyboard_order,
|
|
),
|
|
},
|
|
Err(_) => switch_by_name(
|
|
profiles_config,
|
|
q.to_string(),
|
|
preserve_keyboard_order,
|
|
),
|
|
},
|
|
None => Err(SDUError {
|
|
message: "No profile index or name provided.".to_string(),
|
|
}),
|
|
},
|
|
},
|
|
},
|
|
Some(ProfileSwitchCommand::Next) => {
|
|
match next(profiles_config, preserve_keyboard_order) {
|
|
Ok(_) => {
|
|
debug!("Successfully switched to next profile");
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
Some(ProfileSwitchCommand::Prev) => {
|
|
match previous(profiles_config, preserve_keyboard_order) {
|
|
Ok(_) => {
|
|
debug!("successfully switched to previous profile");
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
None => {
|
|
for profile in profiles_config {
|
|
println!("{} {}", profile.icon, profile.name);
|
|
}
|
|
Ok(())
|
|
}
|
|
},
|
|
ProfileCommand::Get {
|
|
get_command,
|
|
monitor,
|
|
} => {
|
|
let profile_detail = get_command.clone().unwrap_or(ProfileGetCommand::Json);
|
|
println!(
|
|
"{}",
|
|
get::profile_info(profiles_config.clone(), profile_detail.clone())
|
|
);
|
|
let _: () = if monitor.unwrap_or_default() {
|
|
let _ = get::watch(
|
|
profiles_config,
|
|
profile_detail,
|
|
get_xdg_dirs()
|
|
.runtime_dir
|
|
.expect("XDG Runtime dir could not be found")
|
|
.join("sway-de-utils/active-profile.json")
|
|
.to_str()
|
|
.expect("could not create str from path")
|
|
.to_string(),
|
|
);
|
|
};
|
|
Ok(())
|
|
}
|
|
ProfileCommand::Shortcuts { shortcut_command } => {
|
|
let focused_profile = focused_workspace_profile(profiles_config);
|
|
shortcuts_fn(
|
|
shortcut_command,
|
|
focused_profile
|
|
.scripts
|
|
.expect("could not find scripts for profile"),
|
|
)
|
|
}
|
|
ProfileCommand::List { mode } => {
|
|
list_profiles(mode.unwrap_or(DisplayMode::Json), profiles_config)
|
|
}
|
|
}
|
|
}
|
|
|
|
//TODO: Consolidate this function with print_shortcuts in shortcuts.rs
|
|
fn list_profiles(mode: DisplayMode, profiles: Vec<Profile>) -> Result<(), SDUError> {
|
|
let output = match mode {
|
|
DisplayMode::Dmenu => {
|
|
let mut dmenu_entries = Vec::<String>::new();
|
|
for profile in profiles {
|
|
dmenu_entries.push(format!("{} {}", profile.icon, profile.name));
|
|
}
|
|
dmenu_entries.join("\n")
|
|
}
|
|
DisplayMode::Json => json!(profiles).to_string(),
|
|
};
|
|
println!("{}", output);
|
|
Ok(())
|
|
}
|
|
|
|
fn initialize(
|
|
mut sway_connection: Connection,
|
|
profile: Profile,
|
|
uindex: usize,
|
|
preserve_keyboard_order: bool,
|
|
) -> Result<(), SDUError> {
|
|
for i in 0..10 {
|
|
let workspace = (uindex * 10)
|
|
+ match i.eq(&0) && !preserve_keyboard_order {
|
|
true => 10,
|
|
false => i,
|
|
};
|
|
debug!("key {}: workspace {}", i, workspace);
|
|
debug!(
|
|
"bindsym $mod+{} workspace number {}:{}",
|
|
i, workspace, profile.icon
|
|
);
|
|
|
|
match run_sway_command(
|
|
&mut sway_connection,
|
|
format!(
|
|
"bindsym $mod+{} workspace number {}:{}",
|
|
i, workspace, profile.icon
|
|
),
|
|
) {
|
|
Ok(_) => (),
|
|
Err(_) => todo!(),
|
|
}
|
|
match run_sway_command(
|
|
&mut sway_connection,
|
|
format!(
|
|
"bindsym $mod+Shift+{} move container to workspace number {}:{}",
|
|
i, workspace, profile.icon
|
|
),
|
|
) {
|
|
Ok(_) => (),
|
|
Err(_) => todo!(),
|
|
}
|
|
}
|
|
|
|
let base_directories = BaseDirectories::new();
|
|
let active_profile_cache = base_directories
|
|
.get_runtime_directory()
|
|
.expect("why tf do xdg dirs not exist")
|
|
.join("sway-de-utils/active-profile.json");
|
|
let active_profile = json!(uindex);
|
|
|
|
DirBuilder::new()
|
|
.recursive(true)
|
|
.create(
|
|
active_profile_cache
|
|
.parent()
|
|
.expect("Unable to determine cache dir"),
|
|
)
|
|
.expect("Failed to create cache directory");
|
|
match write(active_profile_cache, active_profile.to_string()) {
|
|
Ok(o) => debug!("{:#?}", o),
|
|
Err(e) => debug!("{:#?}", e),
|
|
};
|
|
|
|
match run_sway_command(
|
|
&mut sway_connection,
|
|
format!("workspace number {}:{}", (uindex * 10) + 1, profile.icon),
|
|
) {
|
|
Ok(_) => Ok(()),
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
pub fn profile_from_index(profiles: Vec<Profile>, index: usize) -> Profile {
|
|
profiles
|
|
.get(index)
|
|
.expect("Profile not found for index")
|
|
.clone()
|
|
}
|
|
|
|
pub fn _profile_from_name(config: Config, name: String) -> Result<Profile, SDUError> {
|
|
match config.profiles.iter().find(|x| x.name == name) {
|
|
Some(p) => Ok(p.clone()),
|
|
None => Err(SDUError {
|
|
message: format!("Profile not found with name {}", name),
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn switch_by_index(
|
|
profiles_config: Vec<Profile>,
|
|
index: usize,
|
|
preserve_keyboard_order: bool,
|
|
) -> Result<(), SDUError> {
|
|
let profile = profile_from_index(profiles_config, index);
|
|
match initialize(
|
|
get_sway_connection(),
|
|
profile,
|
|
index,
|
|
preserve_keyboard_order,
|
|
) {
|
|
Ok(_) => {
|
|
println!("successfully switched to profile at index {}", index);
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
fn switch_by_name(
|
|
profiles_config: Vec<Profile>,
|
|
name: String,
|
|
preserve_keyboard_order: bool,
|
|
) -> Result<(), SDUError> {
|
|
match index_from_name(profiles_config.clone(), name.clone()) {
|
|
Ok(index) => match switch_by_index(profiles_config, index, preserve_keyboard_order) {
|
|
Ok(_) => {
|
|
println!("Successfully switched to profile with name {}", name);
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
},
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
pub fn active_profile_index() -> usize {
|
|
let base_directories = BaseDirectories::new();
|
|
let active_profile_cache_json = base_directories
|
|
.get_runtime_directory()
|
|
.expect("xdg dirs do not exist?")
|
|
.join("sway-de-utils/active-profile.json");
|
|
|
|
if active_profile_cache_json.exists() {
|
|
fs::File::open(active_profile_cache_json)
|
|
.ok()
|
|
.and_then(|f| serde_json::from_reader::<fs::File, usize>(f).ok())
|
|
.expect("could not parse active profile cache file")
|
|
} else {
|
|
error!("no active profile cache file");
|
|
0
|
|
}
|
|
}
|
|
|
|
pub fn _active_profile(profiles: Vec<Profile>) -> Result<Profile, SDUError> {
|
|
match profiles.get(active_profile_index()) {
|
|
Some(p) => Ok(p.clone()),
|
|
None => Err(SDUError {
|
|
message: "Could not get profile by index".to_string(),
|
|
}),
|
|
}
|
|
}
|
|
|
|
fn next(profiles_config: Vec<Profile>, preserve_keyboard_order: bool) -> Result<(), SDUError> {
|
|
let profile_count = profiles_config.len();
|
|
let mut next_profile = active_profile_index() + 1;
|
|
if next_profile.ge(&profile_count) {
|
|
next_profile = 0
|
|
}
|
|
match switch_by_index(profiles_config, next_profile, preserve_keyboard_order) {
|
|
Ok(_) => {
|
|
println!("switched to next profile ({})", next_profile);
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
fn previous(profiles_config: Vec<Profile>, preserve_keyboard_order: bool) -> Result<(), SDUError> {
|
|
let profile_index = active_profile_index();
|
|
let prev_profile: usize = if profile_index.eq(&0) {
|
|
profiles_config.len() - 1
|
|
} else {
|
|
profile_index - 1
|
|
};
|
|
match switch_by_index(profiles_config, prev_profile, preserve_keyboard_order) {
|
|
Ok(_) => {
|
|
println!("switched to prev profile ({})", prev_profile);
|
|
Ok(())
|
|
}
|
|
Err(e) => Err(e),
|
|
}
|
|
}
|
|
|
|
pub fn index_from_name(profiles_config: Vec<Profile>, name: String) -> Result<usize, SDUError> {
|
|
match profiles_config.iter().position(|x| x.name == name) {
|
|
Some(i) => Ok(i),
|
|
None => Err(SDUError {
|
|
message: "Index not found for profile?".to_string(),
|
|
}),
|
|
}
|
|
}
|