Skip to content

Commit

Permalink
Enhance the help command to print info about a given unit
Browse files Browse the repository at this point in the history
  • Loading branch information
eminence committed Nov 23, 2023
1 parent cab66a0 commit f384968
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 2 deletions.
9 changes: 9 additions & 0 deletions numbat-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ impl Cli {
println!();
}
_ => {
if let Some(keyword) = line.strip_prefix("help") {
let help = self
.context
.lock()
.unwrap()
.print_help_for_keyword(keyword.trim());
println!("{}", ansi_format(&help, true));
continue;
}
let result = self.parse_and_evaluate(
&line,
CodeSource::Text,
Expand Down
10 changes: 10 additions & 0 deletions numbat/src/bytecode_interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@ impl BytecodeInterpreter {
fn current_depth(&self) -> usize {
self.locals.len() - 1
}

pub fn get_defining_unit(&self, unit_name: &str) -> Option<&Unit> {
self.unit_name_to_constant_index
.get(unit_name)
.and_then(|idx| self.vm.constants.get(*idx as usize))
.and_then(|constant| match constant {
Constant::Unit(u) => Some(u),
_ => None,
})
}
}

impl Interpreter for BytecodeInterpreter {
Expand Down
71 changes: 71 additions & 0 deletions numbat/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,11 @@ pub use registry::BaseRepresentation;
pub use registry::BaseRepresentationFactor;
pub use typed_ast::Statement;
pub use typed_ast::Type;
use unit::BaseUnitAndFactor;
use unit_registry::UnitMetadata;

use crate::prefix_parser::PrefixParserResult;

#[derive(Debug, Error)]
pub enum NumbatError {
#[error("{0}")]
Expand Down Expand Up @@ -253,6 +256,74 @@ impl Context {
words.into_iter().filter(move |w| w.starts_with(word_part))
}

pub fn print_help_for_keyword(&mut self, keyword: &str) -> Markup {
let reg = self.interpreter.get_unit_registry();

if let PrefixParserResult::UnitIdentifier(_span, prefix, _, full_name) =
self.prefix_transformer.prefix_parser.parse(keyword)
{
if let Some(md) = reg
.inner
.get_base_representation_for_name(&full_name)
.ok()
.map(|(_, md)| md)
{
let mut help = m::unit(md.name.as_deref().unwrap_or(keyword)) + m::nl();
if let Some(url) = &md.url {
help += m::string(url) + m::nl();
}
if md.aliases.len() > 1 {
help += m::text("Aliases: ")
+ m::text(
md.aliases
.iter()
.map(|(x, _)| x.as_str())
.collect::<Vec<_>>()
.join(", "),
)
+ m::nl();
}

help += m::text("A unit of [") + md.readable_type + m::text("]") + m::nl();

if let Some(defining_info) = self.interpreter.get_defining_unit(&full_name) {
let x = defining_info
.iter()
.filter(|u| !u.unit_id.is_base())
.map(|unit_factor| unit_factor.unit_id.unit_and_factor())
.next();

if !prefix.is_none() {
help += m::nl()
+ m::value("1 ")
+ m::type_identifier(keyword)
+ m::text(" = ")
+ m::value(prefix.factor().pretty_print())
+ m::space()
+ m::type_identifier(&full_name);
}

if let Some(BaseUnitAndFactor(prod, num)) = x {
help += m::nl()
+ m::value("1 ")
+ m::type_identifier(&full_name)
+ m::text(" = ")
+ m::value(num.pretty_print())
+ m::space()
+ prod.pretty_print_with(|f| f.exponent, 'x', '/', true);
} else {
help +=
m::nl() + m::type_identifier(&full_name) + m::text(" is a base unit");
}
};

return help;
}
};

m::text("Not found")
}

pub fn list_modules(&self) -> impl Iterator<Item = String> {
let modules = self.resolver.get_importer().list_modules();
modules.into_iter().map(|m| m.0.join("::"))
Expand Down
2 changes: 1 addition & 1 deletion numbat/src/prefix_transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type Result<T> = std::result::Result<T, NameResolutionError>;

#[derive(Debug, Clone)]
pub(crate) struct Transformer {
prefix_parser: PrefixParser,
pub prefix_parser: PrefixParser,

pub variable_names: Vec<String>,
pub function_names: Vec<String>,
Expand Down
14 changes: 13 additions & 1 deletion numbat/src/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub struct UnitIdentifier {
kind: UnitKind,
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct BaseUnitAndFactor(pub Unit, pub Number);

impl std::iter::Product for BaseUnitAndFactor {
Expand All @@ -42,6 +42,18 @@ impl UnitIdentifier {
matches!(self.kind, UnitKind::Base)
}

pub fn unit_and_factor(&self) -> BaseUnitAndFactor {
match &self.kind {
UnitKind::Base => BaseUnitAndFactor(
Unit::new_base(&self.name, &self.canonical_name),
Number::from_f64(1.0),
),
UnitKind::Derived(factor, defining_unit) => {
BaseUnitAndFactor(defining_unit.clone(), *factor)
}
}
}

pub fn base_unit_and_factor(&self) -> BaseUnitAndFactor {
match &self.kind {
UnitKind::Base => BaseUnitAndFactor(
Expand Down

0 comments on commit f384968

Please sign in to comment.