daisy/src/command/mod.rs
2023-09-21 13:53:46 -07:00

274 lines
7.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::context::Context;
use crate::parser::Constant;
use crate::parser::substitute;
use crate::formattedtext::FormattedText;
pub fn is_command(
s: &String
) -> bool {
let args: Vec<&str> = s.split(" ").collect();
let first = args[0];
match first {
"help" | "clear"
| "ops" | "operators"
| "fns" | "functions"
| "vars"
| "consts" | "constants"
| "del" | "delete"
| "flags"
=> true,
_ => false
}
}
#[inline(always)]
fn greeter() -> FormattedText {
return FormattedText::new(
format!(
concat!(
"[a] ###### [n] @@@@@@\n",
"[a] # ##[n]@@ @\n",
"[a] ## #[n]@ @@\n",
"[a] [n]@@@@@@@@@@@@@[a]\n",
"[n] @@ @[a]# ##\n",
"[n] @ @@[a]## #\n",
"[n] @@@@@@ [a] ###### [n]\n",
" [t]Daisy[n] [i]v{ver}[n]\n",
"\n"
),
ver = env!("CARGO_PKG_VERSION")
)
);
}
#[inline(always)]
pub fn do_command(
context: &mut Context,
s: &String,
) -> FormattedText {
let args: Vec<&str> = s.split(" ").collect();
let first = args[0];
match first {
"help" => {
let mut t = greeter();
t.push(
concat!(
"Daisy is a high-precision, general-purpose\n",
"scientific calculator.\n",
"\n",
" - Use Up/Down arrows to navigate history.\n",
" - Use Ctrl-C or Ctrl-D to quit.\n",
" - Use [c]ans[n] to reference the last result.\n",
" - Use [c]var = 1337[n] to define varibles.\n",
"\n",
"╞═══════════════ [t]Commands[n] ═══════════════╡\n",
" [c]help[n] Show this help\n",
" [c]flags[n] Show command-line options\n",
" [c]clear[n] Clear the terminal\n",
" [c]quit[n] Exit daisy\n",
//" [c]units[n] List available units\n",
" [c]consts[n] List built-in constants\n",
" [c]ops[n] List built-in operators\n",
" [c]fns[n] List built-in functions\n",
" [c]vars[n] List user-defined variables\n",
" [c]del[n] Delete a variable\n",
"\n\n",
)
);
return t;
},
"flags" => {
return FormattedText::new(
concat!(
"\n",
"A list of command-line arguments is below\n",
"\n",
"╞════ [t]Flag[n] ════╪════════════════ [t]Function[n] ════════════════╡\n",
" [c]--help[n] Show help\n",
" [c]--version[n] Show version\n",
" [c]--info[n] Show system information\n",
" [c]--256color[n] Use full color support (default)\n",
" [c]--8color[n] Use reduced colors (ANSI, no styling)\n",
" [c]--nocolor[n] Do not use colors and styling\n",
" [c]--nosub[n] Disable inline substitution\n",
" [c]--nosuper[n] Disable superscript powers\n",
" [c]--nooneover[n] Disable \"one-over\" fractions as -1 power\n",
"\n\n"
).to_string()
);
},
"clear" => {
return FormattedText::new("[clear]".to_string());
},
"ops" | "operators" => {
return FormattedText::new(
concat!(
"\n",
"Operators, sorted by priority (high to low).\n",
"High-piority operators are applied first.\n\n",
"╞═════ [t]Operator[n] ═════╪═════ [t]Syntax[n] ═════╡\n",
" function [c]sin, cos, etc[n]\n",
" factorial [c]![n]\n",
" powers [c]^, **[n]\n",
" implicit multiply [c]3π, 3(2+1), etc[n]\n",
" square root [c]sqrt, rt, √[n]\n",
" negate [c]-3, -(1 + 2)[n]\n",
" modulo (short) [c]%[n]\n",
" multiply, divide [c]*, /, ×, ÷[n]\n",
" add, subtract [c]+, -[n]\n",
" unit conversion [c]to[n]\n",
" division (long) [c]per[n]\n",
" modulo (long) [c]mod[n]\n",
"\n\n"
).to_string()
);
},
"fns" | "functions" => {
return FormattedText::new(
concat!(
"\n╞═══════ [t]Function[n] ═══════╪══════ [t]Syntax[n] ══════╡\n",
" absolute value [c]abs[n]\n",
" floor, ceiling, round [c]floor, ceil, round[n]\n",
" log base e [c]ln[n]\n",
" log base 10 [c]log[n]\n",
" sin, arcsin, cosecant [c]sin, asin, csc[n]\n",
" cos, arccos, secant [c]cos, acos, secant[n]\n",
" tan, arctan, cotan [c]tan, atan, cot[n]\n",
" hyperbolic sin, etc [c]sinh, asinh, csch[n]\n",
" hyperbolic cos, etc [c]cosh, acosh, sech[n]\n",
" hyperbolic tan, etc [c]tanh, atanh, coth[n]\n",
"\n",
" Celsius to Kelvin [c]fromC, fromCelsius[n]\n",
" Kelvin to Celsius [c]toC, toCelsius[n]\n",
" Fahrenheit to Kelvin [c]fromF, fromFahrenheit[n]\n",
" Kelvin to Fahrenheit [c]toF, toFahrenheit[n]\n",
"\n",
" convert to base unit [c]tobase[n]\n",
" remove units [c]nounit[n]\n",
"\n\n"
).to_string()
);
},
"vars" => {
let v = context.get_variables();
let f = context.get_functions();
if v.len() + f.len() == 0 {
return FormattedText::new(
"You have not defined any variables\n\n".to_string()
);
}
let mut t = FormattedText::new("".to_string());
let mut longest = 0;
for (key, _) in v {
if key.len() > longest {
longest = key.len();
}
}
for (key, (args, _exp)) in f {
let s = format!("{key}({})", args.join(", "));
if s.len() > longest {
longest = s.len();
}
}
if v.len() != 0 {
t.push("\n╞═══ [t]User-Defined Variables[n] ═══╡\n");
for (key, value) in v {
let padding = " ".repeat(longest - key.len());
t.push(&format!(
" {key}{padding} = [c]{v}[n]\n",
v = value.display(context),
));
}
}
if f.len() != 0 {
t.push("\n╞═══ [t]User-Defined Functions[n] ═══╡\n");
for (key, (args, exp)) in f {
let s = format!("{key}({})", args.join(", "));
let padding = " ".repeat(longest - s.len());
t.push(&format!(
" {s}{padding} = [c]{v}[n]\n",
v = exp.display(context),
));
}
}
t.push("\n\n");
return t;
},
"consts" | "constants" => {
let a = Constant::all_consts();
let mut t = FormattedText::new(
"\n╞═══ [t]Built-in Constants[n] ═══╡\n".to_string()
);
for c in a {
let Some(p) = c.pretty_name() else { continue };
// If you subtract with overflow here,
// your padding length is too short.
let padding = " ".repeat(25 - p.chars().count());
t.push(&format!(
" {p}{padding}: [c]{s}[n]",
s = c.source_strings().join(", "),
));
t.push(&"\n");
}
t.push(&"\n\n");
return t;
},
"del" | "delete" => {
if args.len() != 2 {
return FormattedText::new(
format!(
"[c]{first}[n] [t]takes exactly one argument.[n]\n\n",
)
);
}
let v = args[1].to_string();
let v = substitute(context, &v);
let r = context.delete(&v);
return match r {
Ok(()) => { FormattedText::new("".to_string()) },
Err(()) => {
FormattedText::new(
format!(
"[c]{v}[n] [t]isn't a variable.[n]\n\n",
)
)
}
};
},
_ => unreachable!("Bad command!")
};
}