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
use crate::Package;
use chalk_rs::Chalk;
use std::collections::HashMap;

use super::{Heap, Options};

//pub trait DynPackageCallback = FnMut(&Args, &mut Heap, &mut bool);
pub type Args = Vec<String>;
pub type PackageCallback = fn(&Args, &mut Heap, &String, &mut Options) -> ();

pub type DynMethodRes = Vec<(&'static str, &'static str, PackageCallback)>;
pub type MethodRes = &'static [(&'static str, &'static str, PackageCallback)];

pub enum MethodData<'a> {
  Static(&'a str, PackageCallback),
}

pub struct LanguagePackages<'a> {
  pub inner: HashMap<&'static str, MethodData<'a>>,
  pub docs: HashMap<&'static str, &'static str>,
}

impl<'a> LanguagePackages<'a> {
  pub fn new() -> Self {
    Self {
      inner: HashMap::new(),
      docs: HashMap::new(),
    }
  }

  pub fn import<T: Package>(&mut self, func: T) -> &mut Self {
    let name = String::from_utf8_lossy(func.name());
    let name: &'static mut str = name.to_string().leak::<'static>();
    for (key, doc, val) in func.methods() {
      self.inner.insert(key, MethodData::Static(name, *val));
      self.docs.insert(key, doc);
    }
    for (k, doc, v) in func.dyn_methods() {
      self.inner.insert(k, MethodData::Static(name, v));
      self.docs.insert(k, doc);
    }
    self
  }

  pub fn list(&self, chalk: &mut Chalk) {
    println!(
      "{} {}",
      chalk.reset_weight().blue().string(&"Total Commands:"),
      self.inner.len()
    );
    chalk.reset_weight().green().println(&"Commands:");

    self
      .inner
      .iter()
      .enumerate()
      .for_each(|(no, (syntax, mt))| match mt {
        MethodData::Static(name, _) => {
          chalk.red().print(&format!("{}- ", no + 1));
          chalk.yellow().bold().print(&syntax);
          print!(" from ");
          chalk.reset_weight().blue().println(&name);
        }
      });
  }
}