This commit is contained in:
Ivan Bushchik 2023-03-19 06:30:17 +00:00 committed by GitHub
parent b616ffce1d
commit f96e9b8be6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 25 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "smurf" name = "smurf"
version = "0.1.1" version = "0.2.0"
edition = "2021" edition = "2021"
authors = ["Ivan Bushchik <ivabus@ivabus.dev>"] authors = ["Ivan Bushchik <ivabus@ivabus.dev>"]
description = "SMall Useful Rust Functions" description = "SMall Useful Rust Functions"

View file

@ -2,12 +2,51 @@
> SMall Useful Rust Functions > SMall Useful Rust Functions
## Components ## Components
### IO
- macros input!(T) and input_vec!(T), that could be used to simplify stdin process
- read_file_to_str() basically reads file to string (yes.)
### Shell ### Shell
- macro `shell!` - macros shell!()
## Usage
### File Add this to your `Cargo.toml`:
- function `read_to_str` ```toml
[dependencies]
smurf = "0.2"
```
and this to your crate root:
```rust
extern crate smurf;
```
## Example
```rust
use smurf;
use std::io::Write;
fn main() {
print!("What is your name? ");
std::io::stdout().flush().unwrap();
let user_name = input!(String);
print!("What is your age? ");
std::io::stdout().flush().unwrap();
let user_age = input!(u8);
let shell_output = shell!("echo Hello {} of age {}", user_name, user_age); // Returns ShellResult {code: i32, stdout: String, stderr: String}
println!("Shell output: {}", shell_output.stdout);
println!("Shell stderr: {}", shell_output.stderr);
println!("Shell exit code: {}", shell_output.code);
}
```
## License
[MIT](LICENSE-MIT)

View file

@ -1,17 +0,0 @@
use std::fs::File;
use std::io::{prelude::*, BufReader};
pub fn read_to_str(path: &std::path::PathBuf) -> String {
let file = File::open(&path);
let file = match file {
Ok(data) => data,
Err(_) => {
eprintln!("Cannot open file \"{}\"", path.display());
std::process::exit(2)
}
};
let mut buf_reader = BufReader::new(file);
let mut content = String::new();
buf_reader.read_to_string(&mut content).unwrap();
content
}

40
src/io.rs Normal file
View file

@ -0,0 +1,40 @@
use std::fs::File;
use std::io::{prelude::*, BufReader};
pub fn read_file_to_str(path: &std::path::PathBuf) -> Option<String> {
let file = File::open(&path);
let file = match file {
Ok(data) => data,
Err(_) => {
eprintln!("Cannot open file \"{}\"", path.display());
return None
}
};
let mut buf_reader = BufReader::new(file);
let mut content = String::new();
buf_reader.read_to_string(&mut content).unwrap();
Some(content)
}
#[macro_export]
macro_rules! input {
($t:ty) => {
{
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
input.trim().parse::<$t>().unwrap()
}
}
}
#[macro_export]
macro_rules! input_vec {
($t:ty) => {
{
let mut input = String::new();
std::io::stdin().read_line(&mut input).unwrap();
input.trim().split_whitespace().map(|x| x.parse::<$t>().unwrap()).collect::<Vec<$t>>()
}
}
}

View file

@ -1,2 +1,2 @@
pub mod file; pub mod io;
pub mod shell; pub mod shell;

View file

@ -12,8 +12,7 @@ pub struct ShellResult {
pub stdout: String, pub stdout: String,
pub stderr: String, pub stderr: String,
} }
#[allow(dead_code)]
pub fn run(command: String) -> ShellResult { pub fn run(command: String) -> ShellResult {
let mut iter = command.split_whitespace(); let mut iter = command.split_whitespace();
let mut current = iter.next(); let mut current = iter.next();
@ -24,6 +23,7 @@ pub fn run(command: String) -> ShellResult {
} }
let command = Command::new(&words[0]) let command = Command::new(&words[0])
.args(&words[1..]) .args(&words[1..])
.env("PATH", "/bin:/usr/bin") // TODO: Make this configurable
.output() .output()
.expect(&format!("Failed to execute '{}'", command)); .expect(&format!("Failed to execute '{}'", command));
return ShellResult { return ShellResult {
@ -32,3 +32,44 @@ pub fn run(command: String) -> ShellResult {
stderr: String::from_utf8(command.stderr).unwrap(), stderr: String::from_utf8(command.stderr).unwrap(),
}; };
} }
#[cfg(test)]
mod tests {
#[test]
fn test_shell_macro() {
let result = shell!("echo hello");
assert_eq!(result.code, 0);
assert_eq!(result.stdout, "hello\n");
assert_eq!(result.stderr, "");
}
/* You literally can't use pipe using std::process::Command */
// TODO: figure out how to test this
#[ignore]
#[test]
fn test_shell_macro_with_stderr() {
let result = shell!("echo hello 1>&2");
assert_eq!(result.code, 0);
assert_eq!(result.stdout, "");
assert_eq!(result.stderr, "hello\n");
}
#[test]
fn test_shell_macro_with_args() {
let result = shell!("echo {} {}", "hello", "world");
assert_eq!(result.code, 0);
assert_eq!(result.stdout, "hello world\n");
assert_eq!(result.stderr, "");
}
// TODO: figure out how to test this
#[ignore]
#[test]
fn test_shell_macro_with_code() {
let result = shell!("sh -c exit 1");
assert_eq!(result.code, 1);
assert_eq!(result.stdout, "");
assert_eq!(result.stderr, "");
}
}