-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from rageagainsthepc/interactive-mode
Add interactive mode
- Loading branch information
Showing
7 changed files
with
262 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use std::path::Path; | ||
|
||
use crate::errorbox; | ||
use crate::launch::launch; | ||
use crate::link::make_link; | ||
use clap::{arg, App, AppSettings, ArgMatches}; | ||
use path_absolutize::Absolutize; | ||
use stable_eyre::eyre::{bail, eyre}; | ||
use stable_eyre::Result; | ||
|
||
fn run_subcommand(matches: &ArgMatches) -> Result<()> { | ||
match matches.subcommand() { | ||
Some(("launch", sub_matches)) => { | ||
let program = Path::new( | ||
sub_matches | ||
.value_of("PROGRAM") | ||
.ok_or_else(|| eyre!("PRORGAM is required"))?, | ||
) | ||
.absolutize()?; | ||
|
||
if !program.exists() { | ||
bail!("Program must exist") | ||
} | ||
|
||
launch(&program, matches.is_present("background"))?; | ||
} | ||
Some(("link", sub_matches)) => { | ||
let target = Path::new( | ||
sub_matches | ||
.value_of("TARGET") | ||
.ok_or_else(|| eyre!("TARGET is required"))?, | ||
) | ||
.absolutize()?; | ||
let location = Path::new( | ||
sub_matches | ||
.value_of("LOCATION") | ||
.ok_or_else(|| eyre!("LOCATION is required"))?, | ||
) | ||
.absolutize()?; | ||
|
||
if !target.exists() { | ||
bail!("Target must exist") | ||
} | ||
|
||
make_link(&target, &location)?; | ||
} | ||
_ => unreachable!(), | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub(crate) fn run() -> Result<(), stable_eyre::Report> { | ||
let matches = App::new("ampsim_starter") | ||
.about("A tool for launching programs with optimized performance") | ||
.arg(arg!(-b --background "Activate background mode (errors as message boxes, hidden console window)")) | ||
.setting(AppSettings::SubcommandRequiredElseHelp) | ||
.subcommand( | ||
App::new("launch") | ||
.about("Launch a process with high performance settings") | ||
.arg(arg!(<PROGRAM> "The program to launch")) | ||
.setting(AppSettings::ArgRequiredElseHelp), | ||
) | ||
.subcommand( | ||
App::new("link") | ||
.about("Create a shortcut for a given program") | ||
.arg(arg!(<TARGET> "Location of the target program")) | ||
.arg(arg!(<LOCATION> "Location of the shortcut")) | ||
.setting(AppSettings::ArgRequiredElseHelp), | ||
) | ||
.get_matches(); | ||
let result = run_subcommand(&matches); | ||
if matches.is_present("background") { | ||
match result { | ||
Ok(()) => (), | ||
Err(ref e) => errorbox::show(format!("{:#}", e).as_str()), | ||
} | ||
} | ||
result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use inflector::Inflector; | ||
use lazy_static::lazy_static; | ||
use windows::Win32::UI::WindowsAndMessaging::{MessageBoxW, MB_ICONSTOP}; | ||
|
||
lazy_static! { | ||
static ref EXE_NAME: String = std::env::current_exe() | ||
.ok() | ||
.and_then(|p| p.file_stem().map(|s| s.to_os_string())) | ||
.and_then(|s| s.into_string().ok()) | ||
.unwrap_or_else(|| "AmpSim Launcher".to_string()) | ||
.to_title_case(); | ||
} | ||
|
||
pub(crate) fn show(message: &str) { | ||
unsafe { | ||
MessageBoxW(None, message, EXE_NAME.as_str(), MB_ICONSTOP); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
use std::{ | ||
env, io, | ||
path::{Path, PathBuf}, | ||
}; | ||
|
||
use path_absolutize::Absolutize; | ||
use stable_eyre::Result; | ||
|
||
use crate::{errorbox, link::make_link, pathext::PathExt}; | ||
|
||
fn get_target_path() -> Result<PathBuf> { | ||
let target_path = loop { | ||
let mut input_buffer = String::new(); | ||
std::io::stdin().read_line(&mut input_buffer)?; | ||
let mut line = input_buffer.lines().next().unwrap(); | ||
line = quoted_string::strip_dquotes(line).unwrap_or(line); | ||
|
||
if line.is_empty() { | ||
println!("Input required. Enter the path of a target executable:"); | ||
} else { | ||
match Path::new(line).is_file_ext() { | ||
Ok(is_file) => { | ||
if is_file { | ||
break PathBuf::from(line); | ||
} | ||
println!("Target does not exist or is not a file."); | ||
} | ||
Err(e) => println!("{}", e.to_string()), | ||
} | ||
} | ||
println!("Enter the path of a target executable:"); | ||
}; | ||
Ok(target_path) | ||
} | ||
|
||
fn get_shortcut_path(target_path: &Path) -> Result<PathBuf> { | ||
let default_shortcut_path = Path::new(&env::var("USERPROFILE")?).join("Desktop").join( | ||
Path::new(target_path) | ||
.with_extension("lnk") | ||
.file_name() | ||
.unwrap(), | ||
); | ||
println!( | ||
"Enter the path where the shortcut will be created (default: {}):", | ||
default_shortcut_path.to_string_lossy() | ||
); | ||
|
||
let shortcut_path = loop { | ||
let mut input_buffer = String::new(); | ||
std::io::stdin().read_line(&mut input_buffer)?; | ||
let mut line = input_buffer.lines().next().unwrap(); | ||
line = quoted_string::strip_dquotes(line).unwrap_or(line); | ||
|
||
if line.is_empty() { | ||
break None; | ||
} else if let Some(p) = Path::new(line).absolutize()?.parent() { | ||
match p.is_dir_ext() { | ||
Ok(is_dir) => { | ||
if is_dir { | ||
break Some(PathBuf::from(line)); | ||
} | ||
println!("Parent directory is not a directory."); | ||
} | ||
Err(e) => println!("{}", e.to_string()), | ||
} | ||
} | ||
println!("Enter a valid shortcut path:"); | ||
}; | ||
|
||
Ok(shortcut_path.unwrap_or(default_shortcut_path)) | ||
} | ||
|
||
fn create_shortcut() -> Result<()> { | ||
println!("Shortcut Creation Mode"); | ||
println!("Enter the path of a target executable:"); | ||
|
||
let target_path = get_target_path()?; | ||
let shortcut_path = get_shortcut_path(&target_path)?; | ||
|
||
make_link(target_path.as_path(), shortcut_path.as_path())?; | ||
|
||
println!("Shortcut created sucessfully. Press Enter to terminate..."); | ||
let mut finish = String::new(); | ||
io::stdin().read_line(&mut finish)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
pub(crate) fn run() -> Result<()> { | ||
let result = create_shortcut(); | ||
|
||
if let Err(ref e) = result { | ||
errorbox::show(format!("{:#}", e).as_str()) | ||
} | ||
|
||
result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,31 @@ | ||
mod cli; | ||
mod errorbox; | ||
mod interactive; | ||
mod launch; | ||
mod link; | ||
mod pathext; | ||
|
||
use std::path::Path; | ||
|
||
use crate::launch::launch; | ||
use crate::link::make_link; | ||
use clap::{arg, App, AppSettings, ArgMatches}; | ||
use path_absolutize::Absolutize; | ||
use stable_eyre::eyre::{bail, eyre}; | ||
use stable_eyre::Result; | ||
use windows::Win32::UI::WindowsAndMessaging::{MessageBoxW, MB_ICONSTOP}; | ||
|
||
fn display_error_box(message: &str) { | ||
unsafe { | ||
MessageBoxW(None, message, "AmpSim Launcher", MB_ICONSTOP); | ||
} | ||
} | ||
|
||
fn run_subcommand(matches: &ArgMatches) -> Result<()> { | ||
match matches.subcommand() { | ||
Some(("launch", sub_matches)) => { | ||
let program = Path::new( | ||
sub_matches | ||
.value_of("PROGRAM") | ||
.ok_or_else(|| eyre!("PRORGAM is required"))?, | ||
) | ||
.absolutize()?; | ||
|
||
if !program.exists() { | ||
bail!("Program must exist") | ||
} | ||
|
||
launch(&program, matches.is_present("background"))?; | ||
} | ||
Some(("link", sub_matches)) => { | ||
let target = Path::new( | ||
sub_matches | ||
.value_of("TARGET") | ||
.ok_or_else(|| eyre!("TARGET is required"))?, | ||
) | ||
.absolutize()?; | ||
let location = Path::new( | ||
sub_matches | ||
.value_of("LOCATION") | ||
.ok_or_else(|| eyre!("LOCATION is required"))?, | ||
) | ||
.absolutize()?; | ||
|
||
if !target.exists() { | ||
bail!("Target must exist") | ||
} | ||
|
||
make_link(&target, &location)?; | ||
} | ||
_ => unreachable!(), | ||
} | ||
|
||
Ok(()) | ||
use sysinfo::{ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt}; | ||
|
||
fn parent_name() -> String { | ||
let system = | ||
System::new_with_specifics(RefreshKind::new().with_processes(ProcessRefreshKind::new())); | ||
let parent_id = system | ||
.process(std::process::id().try_into().unwrap()) | ||
.unwrap() | ||
.parent() | ||
.unwrap(); | ||
let parent_name = system.process(parent_id).unwrap().name(); | ||
parent_name.to_owned() | ||
} | ||
|
||
fn main() -> Result<()> { | ||
stable_eyre::install()?; | ||
|
||
let matches = App::new("ampsim_starter") | ||
.about("A tool for launching programs with optimized performance") | ||
.arg(arg!(-b --background "Activate background mode (errors as message boxes, hidden console window)")) | ||
.setting(AppSettings::SubcommandRequiredElseHelp) | ||
.subcommand( | ||
App::new("launch") | ||
.about("Launch a process with high performance settings") | ||
.arg(arg!(<PROGRAM> "The program to launch")) | ||
.setting(AppSettings::ArgRequiredElseHelp), | ||
) | ||
.subcommand( | ||
App::new("link") | ||
.about("Create a shortcut for a given program") | ||
.arg(arg!(<TARGET> "Location of the target program")) | ||
.arg(arg!(<LOCATION> "Location of the shortcut")) | ||
.setting(AppSettings::ArgRequiredElseHelp), | ||
) | ||
.get_matches(); | ||
|
||
let result = run_subcommand(&matches); | ||
if matches.is_present("background") { | ||
match result { | ||
Ok(()) => (), | ||
Err(ref e) => display_error_box(format!("{:#}", e).as_str()), | ||
} | ||
if std::env::args().len() < 2 && parent_name() == "explorer.exe" { | ||
interactive::run() | ||
} else { | ||
cli::run() | ||
} | ||
|
||
result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use std::{fs, io, path::Path, result::Result}; | ||
|
||
pub(crate) trait PathExt { | ||
/// Like `std::path::Path::is_dir()` but returns a result object in order to | ||
/// be able to differentiate between an actual result and io errors. | ||
fn is_dir_ext(&self) -> Result<bool, io::Error>; | ||
/// Like `std::path::Path::is_file()` but returns a result object in order to | ||
/// be able to differentiate between an actual result and io errors. | ||
fn is_file_ext(&self) -> Result<bool, io::Error>; | ||
} | ||
|
||
impl PathExt for Path { | ||
fn is_dir_ext(&self) -> Result<bool, io::Error> { | ||
fs::metadata(self).map(|m| m.is_dir()) | ||
} | ||
|
||
fn is_file_ext(&self) -> Result<bool, io::Error> { | ||
fs::metadata(self).map(|m| m.is_file()) | ||
} | ||
} |