|
|
@ -1,7 +1,7 @@
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
|
|
|
|
|
|
|
|
use web_sys::KeyboardEvent;
|
|
|
|
|
|
|
|
use web_sys::Element;
|
|
|
|
use web_sys::Element;
|
|
|
|
|
|
|
|
use web_sys::KeyboardEvent;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::State;
|
|
|
|
use crate::State;
|
|
|
|
|
|
|
|
|
|
|
@ -10,14 +10,14 @@ pub enum Key {
|
|
|
|
Space,
|
|
|
|
Space,
|
|
|
|
Backspace,
|
|
|
|
Backspace,
|
|
|
|
Return,
|
|
|
|
Return,
|
|
|
|
Ctrl(Box<Key>)
|
|
|
|
Ctrl(Box<Key>),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub fn parse_key_event(event: &KeyboardEvent, ignore_ctrl: bool) -> Option<Key> {
|
|
|
|
pub fn parse_key_event(event: &KeyboardEvent, ignore_ctrl: bool) -> Option<Key> {
|
|
|
|
if event.ctrl_key() && !ignore_ctrl {
|
|
|
|
if event.ctrl_key() && !ignore_ctrl {
|
|
|
|
let base = parse_key_event(event, true)?;
|
|
|
|
let base = parse_key_event(event, true)?;
|
|
|
|
|
|
|
|
|
|
|
|
return Some(Key::Ctrl(Box::new(base)))
|
|
|
|
return Some(Key::Ctrl(Box::new(base)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let key = event.key();
|
|
|
|
let key = event.key();
|
|
|
@ -42,25 +42,26 @@ pub fn handle_key_event(state : &mut State, key : Key) -> Option<String> {
|
|
|
|
match key {
|
|
|
|
match key {
|
|
|
|
Key::Return => {
|
|
|
|
Key::Return => {
|
|
|
|
let input = std::mem::replace(&mut state.input, String::new());
|
|
|
|
let input = std::mem::replace(&mut state.input, String::new());
|
|
|
|
state.output.push_back(format!("{} {}", state.prompt, input));
|
|
|
|
state
|
|
|
|
|
|
|
|
.output
|
|
|
|
|
|
|
|
.push_back(format!("{} {}", state.prompt, input));
|
|
|
|
if state.output.len() > state.max_rows {
|
|
|
|
if state.output.len() > state.max_rows {
|
|
|
|
state.output.pop_front();
|
|
|
|
state.output.pop_front();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Some(input);
|
|
|
|
return Some(input);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
Key::Backspace => {
|
|
|
|
Key::Backspace => {
|
|
|
|
if state.input.len() > 0 {
|
|
|
|
if state.input.len() > 0 {
|
|
|
|
state.input.remove(state.input.len() - 1);
|
|
|
|
state.input.remove(state.input.len() - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
Key::Space => state.input += " ",
|
|
|
|
Key::Space => state.input += " ",
|
|
|
|
Key::Letter(letter) => {
|
|
|
|
Key::Letter(letter) => {
|
|
|
|
let mut tmp = [0; 4];
|
|
|
|
let mut tmp = [0; 4];
|
|
|
|
state.input += letter.encode_utf8(&mut tmp)
|
|
|
|
state.input += letter.encode_utf8(&mut tmp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Key::Ctrl(letter) =>
|
|
|
|
Key::Ctrl(letter) => match letter.as_ref() {
|
|
|
|
match letter.as_ref() {
|
|
|
|
|
|
|
|
Key::Letter(letter) => {
|
|
|
|
Key::Letter(letter) => {
|
|
|
|
if *letter == 'c' {
|
|
|
|
if *letter == 'c' {
|
|
|
|
let mut input = std::mem::replace(&mut state.input, String::new());
|
|
|
|
let mut input = std::mem::replace(&mut state.input, String::new());
|
|
|
@ -71,21 +72,27 @@ pub fn handle_key_event(state : &mut State, key : Key) -> Option<String> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return None
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[wasm_bindgen(inline_js = "const ansi_up = new AnsiUp; export function format_html(text) { return ansi_up.ansi_to_html(text).replace(/(https:[^ )]*)/g, '<a href=\"$1\" target=\"_blank\">$1</a>') }")]
|
|
|
|
#[wasm_bindgen(
|
|
|
|
|
|
|
|
inline_js = "const ansi_up = new AnsiUp; export function format_html(text) { return ansi_up.ansi_to_html(text).replace(/(https:[^ )]*)/g, '<a href=\"$1\" target=\"_blank\">$1</a>') }"
|
|
|
|
|
|
|
|
)]
|
|
|
|
extern "C" {
|
|
|
|
extern "C" {
|
|
|
|
fn format_html(text: String) -> String;
|
|
|
|
fn format_html(text: String) -> String;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn print_state(target: &mut Element, state: &State) {
|
|
|
|
pub fn print_state(target: &mut Element, state: &State) {
|
|
|
|
let mut output = state.output.iter().map(|s| (*s).clone()).collect::<Vec<String>>().join("\n");
|
|
|
|
let mut output = state
|
|
|
|
|
|
|
|
.output
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.map(|s| (*s).clone())
|
|
|
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
|
|
|
.join("\n");
|
|
|
|
|
|
|
|
|
|
|
|
if state.output.len() > 0 {
|
|
|
|
if state.output.len() > 0 {
|
|
|
|
output += "\n";
|
|
|
|
output += "\n";
|
|
|
@ -123,5 +130,5 @@ pub fn build_prompt(state : &State) -> String {
|
|
|
|
prompt += "\x1b[2;37m";
|
|
|
|
prompt += "\x1b[2;37m";
|
|
|
|
prompt += "$";
|
|
|
|
prompt += "$";
|
|
|
|
|
|
|
|
|
|
|
|
return prompt
|
|
|
|
return prompt;
|
|
|
|
}
|
|
|
|
}
|