forked from stacksjb/Shell_Command_Menu
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.rs
More file actions
134 lines (120 loc) · 5.01 KB
/
utils.rs
File metadata and controls
134 lines (120 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use rodio::{Decoder, OutputStreamBuilder, Sink};
use std::fs::File;
use std::io::{BufReader, Write, stdin, stdout};
use std::path::PathBuf;
use std::process::Command; // Importing Command struct for executing shell commands // Importing types for audio playback
use termion::{input::TermRead, raw::IntoRawMode}; // Importing IntoRawMode trait for entering raw mode
use tokio::task; // Importing task module from Tokio for asynchronous task handling // Importing stdout, stdin, and Write traits for I/O operations
//This file contains the utility functions used in the project to run shell commands and other misc functions.
// Function to run a shell command
/// Runs a shell command and prints the result, capturing stdout/stderr for cleaner output.
pub fn run_command(command: &str) {
println!("Running command: {command}"); // Printing the command being executed
let mut child = Command::new("sh") // Starting a new shell command
.arg("-c") // Passing a command to the shell
.arg(command) // The command to execute
.spawn() // Starting the command asynchronously
.expect("❌ Failed to execute command"); // Handling any errors
let status = child.wait().expect("Command wasn't running"); // Waiting for the command to finish
if status.success() {
// Checking if the command was successful
println!("✅ Command executed successfully."); // Printing success message
} else {
println!("\x07\x1b[31mError\x1b[0m: Command returned a non-zero exit status.");
// Printing error message
}
}
// Function to pause execution until user input is received
pub fn pause() {
let mut stdout = stdout().into_raw_mode().unwrap(); // Entering raw mode for stdout
stdout.flush().unwrap(); // Flushing stdout
stdin().events().next(); // Waiting for user input
}
// Function to play a sound asynchronously from filepath
pub async fn play_sound(file_path: PathBuf) {
let file_path = file_path.clone(); // Cloning the PathBuf to be owned by the closure
task::spawn_blocking(move || {
// Spawning a blocking task
match OutputStreamBuilder::open_default_stream() {
Ok(stream_handle) => {
// Trying to get the default audio output stream
match File::open(&file_path) {
Ok(file) => {
// Trying to open the audio file
match Decoder::new(BufReader::new(file)) {
Ok(source) => {
// Trying to decode the audio file
let sink = Sink::connect_new(stream_handle.mixer()); // Creating a sink for the audio stream
sink.append(source); // Appending the audio source to the sink
sink.sleep_until_end(); // Sleeping until the audio playback ends
}
_ => {
println!("❌ Failed to decode audio file: {file_path:?}");
// Printing error message if decoding fails
}
}
}
_ => {
println!("❌ Failed to open audio file: {file_path:?}");
// Printing error message if file opening fails
}
}
}
_ => {
println!("❌ Failed to initialize audio output stream"); // Printing error message if audio stream initialization fails
}
}
})
.await
.unwrap(); // Waiting for the task to finish and handling any errors
}
// Function to return the current version
pub fn get_version() -> String {
env!("CARGO_PKG_VERSION").to_string()
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
// Importing serial_test crate for running tests serially for command execution tests
#[test]
#[serial]
fn test_run_command_success() {
run_command("echo 'Hello'");
println!();
}
#[test]
#[serial]
fn test_run_command_failure() {
run_command("non_existent_command_hopefully");
println!();
}
#[tokio::test]
#[serial]
async fn test_play_sound() {
let sound_path = PathBuf::from("path/to/sound/file.wav");
play_sound(sound_path).await;
println!();
}
#[tokio::test]
#[serial]
async fn test_play_sound_invalid() {
let sound_path = PathBuf::from("invalid/path/to/sound/file.wav");
play_sound(sound_path).await;
println!();
}
#[tokio::test]
#[serial]
async fn test_play_sound_invalid_path() {
let fake_path = PathBuf::from("nonexistent_audio_file.mp3");
play_sound(fake_path).await;
println!();
}
#[tokio::test]
#[serial]
async fn test_play_sound_valid_file() {
let path = PathBuf::from("assets/silence.wav"); // Blank Sound File for testing
play_sound(path).await;
println!();
}
}