<commit_before>use std::ascii::AsciiExt;

#[cfg(not(target_os = "emscripten"))]
use std::io::{self, Write};

use direction::Direction;

#[cfg(target_os = "emscripten")]
use emscripten::{emscripten};

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Look,
  Quit,
}

type HelpInfo = &'static [(char, &'static str)];

pub trait CommandProcessor<T> {
  fn from_char(c: char) -> Option<T>;

  fn get_help() -> HelpInfo;

  fn prompt() -> &'static [u8] { b"> " }

  #[cfg(target_os = "emscripten")]
  fn show_prompt() {}

  #[cfg(not(target_os = "emscripten"))]
  fn show_prompt() {
    io::stdout().write(Self::prompt()).unwrap();
    io::stdout().flush().unwrap();
  }

  #[cfg(target_os = "emscripten")]
  fn read_input() -> Option<String> {
    if emscripten::run_script_int("has_input()") == 0 {
      None
    } else {
      Some(emscripten::run_script_string("get_input()"))
    }
  }

  #[cfg(not(target_os = "emscripten"))]
  fn read_input() -> Option<String> {
    let mut input = String::new();

    match io::stdin().read_line(&mut input) {
      Ok(_) => { return Some(input); },
      Err(error) => {
        println!("Error reading input: {}", error);
        return None;
      },
    }
  }

  fn get() -> Option<T> {
    Self::show_prompt();

    match Self::read_input() {
      Some(input) => {
        match input.chars().next() {
          Some(k) => {
            let k = k.to_ascii_lowercase();
            if k == 'h' || k == '?' {
              println!("Available commands:");

              for &(ch, desc) in Self::get_help().iter() {
                println!("{} - {}", ch, desc);
              }
              return None;
            } else if let Some(cmd) = Self::from_char(k) {
              return Some(cmd);
            }
          },
          None => {}
        }
        println!("I have no idea what you're talking about.");
        return None;
      },
      None => {
        return None;
      }
    }
  }
}

static PRIMARY_COMMAND_HELP: HelpInfo = &[
  ('n', "go north"),
  ('s', "go south"),
  ('e', "go east"),
  ('w', "go west"),
  ('l', "look around"),
  ('q', "quit"),
];

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> HelpInfo { PRIMARY_COMMAND_HELP }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'n' => { return Some(PrimaryCommand::Go(Direction::North)); },
      's' => { return Some(PrimaryCommand::Go(Direction::South)); },
      'e' => { return Some(PrimaryCommand::Go(Direction::East)); },
      'w' => { return Some(PrimaryCommand::Go(Direction::West)); },
      'l' => { return Some(PrimaryCommand::Look); },
      'q' => { return Some(PrimaryCommand::Quit); },
      _ => { return None; },
    }
  }
}
<commit_msg>Use str for prompt instead of [u8].<commit_after>use std::ascii::AsciiExt;

#[cfg(not(target_os = "emscripten"))]
use std::io::{self, Write};

use direction::Direction;

#[cfg(target_os = "emscripten")]
use emscripten::{emscripten};

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Look,
  Quit,
}

type HelpInfo = &'static [(char, &'static str)];

pub trait CommandProcessor<T> {
  fn from_char(c: char) -> Option<T>;

  fn get_help() -> HelpInfo;

  fn prompt() -> &'static str { "> " }

  #[cfg(target_os = "emscripten")]
  fn show_prompt() {}

  #[cfg(not(target_os = "emscripten"))]
  fn show_prompt() {
    io::stdout().write(Self::prompt().as_bytes()).unwrap();
    io::stdout().flush().unwrap();
  }

  #[cfg(target_os = "emscripten")]
  fn read_input() -> Option<String> {
    if emscripten::run_script_int("has_input()") == 0 {
      None
    } else {
      Some(emscripten::run_script_string("get_input()"))
    }
  }

  #[cfg(not(target_os = "emscripten"))]
  fn read_input() -> Option<String> {
    let mut input = String::new();

    match io::stdin().read_line(&mut input) {
      Ok(_) => { return Some(input); },
      Err(error) => {
        println!("Error reading input: {}", error);
        return None;
      },
    }
  }

  fn get() -> Option<T> {
    Self::show_prompt();

    match Self::read_input() {
      Some(input) => {
        match input.chars().next() {
          Some(k) => {
            let k = k.to_ascii_lowercase();
            if k == 'h' || k == '?' {
              println!("Available commands:");

              for &(ch, desc) in Self::get_help().iter() {
                println!("{} - {}", ch, desc);
              }
              return None;
            } else if let Some(cmd) = Self::from_char(k) {
              return Some(cmd);
            }
          },
          None => {}
        }
        println!("I have no idea what you're talking about.");
        return None;
      },
      None => {
        return None;
      }
    }
  }
}

static PRIMARY_COMMAND_HELP: HelpInfo = &[
  ('n', "go north"),
  ('s', "go south"),
  ('e', "go east"),
  ('w', "go west"),
  ('l', "look around"),
  ('q', "quit"),
];

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> HelpInfo { PRIMARY_COMMAND_HELP }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'n' => { return Some(PrimaryCommand::Go(Direction::North)); },
      's' => { return Some(PrimaryCommand::Go(Direction::South)); },
      'e' => { return Some(PrimaryCommand::Go(Direction::East)); },
      'w' => { return Some(PrimaryCommand::Go(Direction::West)); },
      'l' => { return Some(PrimaryCommand::Look); },
      'q' => { return Some(PrimaryCommand::Quit); },
      _ => { return None; },
    }
  }
}

{'fraction_non_alphanumeric': 0.19684611201740077, 'fraction_numerical': 0.0007250317201377561, 'mean_word_length': 2.618360655737705, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3253493', 'n_tokens_mistral': 1881, 'n_tokens_neox': 1855, 'n_words': 381}