feat: add the test command (incomplete!)

This commit is contained in:
Teesh 2025-03-24 15:46:05 +02:00
parent c16858fd8d
commit 47f5cfb674
3 changed files with 224 additions and 0 deletions

View file

@ -13,3 +13,4 @@ command!(dd::Dd);
command!(nproc::Nproc);
command!(r#true::True);
command!(r#false::False);
command!(test::Test);

View file

@ -0,0 +1,218 @@
use boxutils::args::ArgParser;
use boxutils::commands::Command;
// TODO: Add filetype operations
//
// This is not done yet because file operations are
// quite tricky to implement in a way that is both
// platform-independent and safe.
const STRING_TESTS: &[&str] = &["-z", "-n", "=", "!="];
const NUMBER_TESTS: &[&str] = &["-eq", "-ne", "-lt", "-le", "-gt", "-ge"];
const OTHER_FLAGS: &[&str] = &["]"];
fn exit_false() {
std::process::exit(1);
}
fn exit_true() {
std::process::exit(0);
}
pub struct Test {
bracket: bool,
}
impl Test {
pub fn with_bracket() -> Test {
Test { bracket: true }
}
pub fn without_bracket() -> Test {
Test { bracket: false }
}
fn do_string_ops(args: &ArgParser) {
if args.get_flag("-z") {
let args = args.get_normal_args();
let string = args.get(0).unwrap_or(&String::from("")).clone();
if string.is_empty() {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-n") {
let args = args.get_normal_args();
let string = args.get(0).unwrap_or(&String::from("")).clone();
if !string.is_empty() {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("=") {
let args = args.get_normal_args();
let string1 = args.get(0).unwrap_or(&String::from("")).clone();
let string2 = args.get(1).unwrap_or(&String::from("")).clone();
if string1 == string2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("!=") {
let args = args.get_normal_args();
let string1 = args.get(0).unwrap_or(&String::from("")).clone();
let string2 = args.get(1).unwrap_or(&String::from("")).clone();
if string1 != string2 {
exit_true();
} else {
exit_false();
}
}
}
fn do_number_ops(args: &ArgParser) {
if args.get_flag("-eq") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 == number2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-ne") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 != number2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-lt") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 < number2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-le") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 <= number2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-gt") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 > number2 {
exit_true();
} else {
exit_false();
}
}
if args.get_flag("-ge") {
let args = args.get_normal_args();
let number1 = args
.get(0)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
let number2 = args
.get(1)
.unwrap_or(&String::from(""))
.parse::<i64>()
.unwrap_or(0);
if number1 >= number2 {
exit_true();
} else {
exit_false();
}
}
}
}
impl Command for Test {
fn execute(&self) {
let args = ArgParser::builder()
.add_flags(STRING_TESTS.into())
.add_flags(NUMBER_TESTS.into())
.add_flags(OTHER_FLAGS.into())
.parse_args(if self.bracket { "[" } else { "test" });
if self.bracket && !args.get_flag("]") {
panic!("[: missing ]");
}
if STRING_TESTS.iter().any(|&x| args.get_flag(x)) {
Test::do_string_ops(&args);
}
if NUMBER_TESTS.iter().any(|&x| args.get_flag(x)) {
Test::do_number_ops(&args);
}
exit_false();
}
}

View file

@ -13,6 +13,11 @@ pub fn get_registry() -> CommandRegistry {
registry.register("nproc", Box::new(coreutils::commands::Nproc));
registry.register("true", Box::new(coreutils::commands::True));
registry.register("false", Box::new(coreutils::commands::False));
registry.register(
"test",
Box::new(coreutils::commands::Test::without_bracket()),
);
registry.register("[", Box::new(coreutils::commands::Test::with_bracket()));
registry.register("box", Box::new(Boxcmd));
registry