bettertui_engine 0.1.0

High-performance terminal UI framework
Documentation
use bettertui_engine::syntax::*;
use bettertui_engine::tree::{Color, Style};

#[test]
fn highlighter_new() {
    let sh = SyntaxHighlighter::new();
    assert!(sh.has_language("javascript"));
    assert!(sh.has_language("rust"));
    assert!(sh.has_language("python"));
    assert!(sh.has_language("json"));
    assert!(sh.has_language("html"));
    assert!(sh.has_language("css"));
}

#[test]
fn has_language_unknown() {
    let sh = SyntaxHighlighter::new();
    assert!(!sh.has_language("foobar"));
}

#[test]
fn highlight_rust_code() {
    let mut sh = SyntaxHighlighter::new();
    let code = "fn main() {\n    println!(\"hello\");\n}\n";
    let result = sh.highlight(code, "rust");
    assert!(result.is_some());
    let lines = result.unwrap();
    assert_eq!(lines.len(), 4);
    let first_line = &lines[0];
    assert!(!first_line.segments.is_empty());
}

#[test]
fn highlight_javascript_code() {
    let mut sh = SyntaxHighlighter::new();
    let code = "const x = 42;\n";
    let result = sh.highlight(code, "javascript");
    assert!(result.is_some());
    let lines = result.unwrap();
    assert!(!lines.is_empty());
}

#[test]
fn highlight_unknown_language() {
    let mut sh = SyntaxHighlighter::new();
    let result = sh.highlight("code", "unknown_lang");
    assert!(result.is_none());
}

#[test]
fn highlight_empty_code() {
    let mut sh = SyntaxHighlighter::new();
    let result = sh.highlight("", "javascript");
    assert!(result.is_some());
    let lines = result.unwrap();
    assert_eq!(lines.len(), 1);
    assert_eq!(lines[0].text(), "");
}

#[test]
fn highlight_python_code() {
    let mut sh = SyntaxHighlighter::new();
    let code = "def hello():\n    print('world')\n";
    let result = sh.highlight(code, "python");
    assert!(result.is_some());
    let lines = result.unwrap();
    assert!(!lines.is_empty());
}

#[test]
fn highlight_json() {
    let mut sh = SyntaxHighlighter::new();
    let code = "{\"key\": \"value\"}\n";
    let result = sh.highlight(code, "json");
    assert!(result.is_some());
    let lines = result.unwrap();
    assert!(!lines.is_empty());
}

#[test]
fn specificity_counts_dots() {
    assert_eq!(SyntaxHighlighter::specificity("keyword"), 0);
    assert_eq!(SyntaxHighlighter::specificity("keyword.control"), 1);
    assert_eq!(SyntaxHighlighter::specificity("markup.heading.1"), 2);
}

#[test]
fn info_string_js() {
    assert_eq!(info_string_to_filetype("javascript"), Some("javascript"));
    assert_eq!(info_string_to_filetype("js"), Some("javascript"));
    assert_eq!(info_string_to_filetype("jsx"), Some("javascript"));
}

#[test]
fn info_string_rust() {
    assert_eq!(info_string_to_filetype("rust"), Some("rust"));
    assert_eq!(info_string_to_filetype("rs"), Some("rust"));
}

#[test]
fn info_string_unknown() {
    assert_eq!(info_string_to_filetype("foobar"), None);
}

#[test]
fn info_string_empty() {
    assert_eq!(info_string_to_filetype(""), None);
}

#[test]
fn info_string_with_args() {
    assert_eq!(info_string_to_filetype("rust ignore me"), Some("rust"));
}

#[test]
fn highlight_resolves_language_alias() {
    let mut sh = SyntaxHighlighter::new();
    let result = sh.highlight("const x = 1;", "jsx");
    assert!(result.is_some(), "jsx should resolve to javascript");

    let result = sh.highlight("echo hello", "zsh");
    assert!(result.is_some(), "zsh should resolve to bash");

    let result = sh.highlight(".a { color: red; }", "scss");
    assert!(result.is_some(), "scss should resolve to css");
}

#[test]
fn theme_github_dark_has_keywords() {
    let theme = SyntaxTheme::github_dark();
    assert!(theme.get("keyword").is_some());
    assert!(theme.get("keyword.control").is_some());
}

#[test]
fn theme_falls_back_to_parent_scope() {
    let theme = SyntaxTheme::github_dark();
    let style = theme.get("keyword.control.foo");
    assert!(style.is_some());
    assert_eq!(style.unwrap().fg, Some(Color::rgb(255, 123, 114)));
}

#[test]
fn theme_returns_none_for_unknown() {
    let theme = SyntaxTheme::github_dark();
    assert!(theme.get("nonexistent").is_none());
}

#[test]
fn theme_github_light_has_keywords() {
    let theme = SyntaxTheme::github_light();
    assert!(theme.get("keyword").is_some());
    assert_eq!(theme.get("keyword").unwrap().fg, Some(Color::rgb(215, 58, 73)));
}

#[test]
fn theme_with_preset_dark() {
    let theme = SyntaxTheme::with_preset(ThemePreset::GitHubDark);
    assert!(theme.get("keyword").is_some());
}

#[test]
fn theme_with_preset_light() {
    let theme = SyntaxTheme::with_preset(ThemePreset::GitHubLight);
    assert!(theme.get("keyword").is_some());
}

#[test]
fn theme_convert_from_scopes() {
    let scopes = vec![ThemeScope {
        scopes: vec!["keyword".into(), "keyword.control".into()],
        fg: Some(Color::rgb(255, 0, 0)),
        bg: None,
        bold: Some(true),
        italic: None,
        underline: None,
        dim: None,
    }];
    let theme = SyntaxTheme::convert_from_theme(scopes);
    assert_eq!(theme.get("keyword").unwrap().fg, Some(Color::rgb(255, 0, 0)));
    assert!(theme.get("keyword").unwrap().bold.unwrap());
    assert!(theme.get("keyword.control").is_some());
}

#[test]
fn theme_markdown_groups() {
    let theme = SyntaxTheme::github_dark();
    assert!(theme.get("markup.heading.1").is_some());
    assert!(theme.get("markup.raw.block").is_some());
    assert!(theme.get("markup.link.url").is_some());
    assert!(theme.get("markup.list").is_some());
}

#[test]
fn merge_child_overrides_parent() {
    let parent = Style { fg: Some(Color::rgb(255, 0, 0)), bold: Some(true), ..Style::default() };
    let child = Style { fg: Some(Color::rgb(0, 255, 0)), ..Style::default() };
    let merged = SyntaxTheme::merge(&parent, &child);
    assert_eq!(merged.fg, Some(Color::rgb(0, 255, 0)));
    assert_eq!(merged.bold, Some(true));
}