mumu 0.10.0

Lava Mumu is a language for those in the now and that know
Documentation
use crate::parser::interpreter::Interpreter;
use crate::Value;
use std::io;
use std::io::Write;
use crate::modules::repl::ReadLineState;

pub fn forcibly_clear_line(stdout: &mut io::Stdout) -> Result<(), String> {
    use crossterm::queue;
    use crossterm::cursor::MoveToColumn;
    use crossterm::terminal::{Clear, ClearType};
    queue!(stdout, MoveToColumn(0), Clear(ClearType::UntilNewLine))
        .map_err(|e| e.to_string())?;
    stdout.flush().map_err(|e| e.to_string())?;
    Ok(())
}

pub fn redraw_full(
    stdout: &mut io::Stdout,
    prompt: &str,
    state: &ReadLineState,
    verbose: bool,
    _main_interp: &mut Interpreter
) -> Result<(), String> {
    use crossterm::queue;
    use crossterm::cursor::{MoveToColumn, MoveUp};
    use crossterm::style::{SetForegroundColor, ResetColor, Color};
    use crossterm::terminal::{Clear, ClearType};

    if verbose {
        eprintln!("[redraw_full] => prompt='{}', typed='{}', cursor={}",
                  prompt, state.typed_line(), state.cursor_pos);
    }
    queue!(stdout, MoveToColumn(0), Clear(ClearType::FromCursorDown))
        .map_err(|e| e.to_string())?;
    let typed_line = state.typed_line();
    print!("{}", prompt);
    print!("{}", typed_line);
    if let Some(ref eph) = state.ephemeral {
        let suffix = eph.current_suffix();
        if !suffix.is_empty() {
            queue!(stdout, SetForegroundColor(Color::DarkYellow)).ok();
            print!("{}", suffix);
            queue!(stdout, ResetColor).ok();
        }
    }
    println!();
    queue!(stdout, MoveToColumn(0)).map_err(|e| e.to_string())?;
    stdout.flush().map_err(|e| e.to_string())?;
    if !line_is_incomplete_or_command(&typed_line) {
        queue!(stdout, MoveUp(1)).map_err(|e| e.to_string())?;
    } else {
        queue!(stdout, MoveUp(1)).map_err(|e| e.to_string())?;
    }
    let final_col = prompt.chars().count() + state.cursor_pos;
    queue!(stdout, MoveToColumn(final_col as u16)).map_err(|e| e.to_string())?;
    stdout.flush().map_err(|e| e.to_string())?;
    Ok(())
}

fn line_is_incomplete_or_command(line: &str) -> bool {
    let trimmed = line.trim_start();
    if trimmed.starts_with(':') {
        return true;
    }
    let quote_count = trimmed.matches('"').count();
    if quote_count % 2 != 0 {
        return true;
    }
    false
}

pub fn short_type_name(v: &Value) -> &'static str {
    match v {
        Value::Int(_) => "int",
        Value::IntArray(_) => "int_array",
        Value::Int2DArray(_) => "int2d_array",
        Value::Float(_) => "float",
        Value::FloatArray(_) => "float_array",
        Value::Float2DArray(_) => "float2d_array",
        Value::Long(_) => "long",
        Value::Bool(_) => "bool",
        Value::BoolArray(_) => "bool_array",
        Value::Placeholder => "placeholder",
        Value::SingleString(_) => "string",
        Value::StrArray(_) => "str_array",
        Value::KeyedArray(_) => "keyed_array",
        Value::Function(_) => "function",
        Value::Stream(_) => "stream",
        Value::InkIterator(_) => "ink_iterator",
        Value::InkTransform(_) => "ink_transform",
        Value::Tensor(_) => "tensor",
        Value::MixedArray(_) => "mixed_array",
        Value::Ref(_) => "ref",
    }
}