rmux-server 0.1.0

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
use super::*;

#[test]
fn tree_preview_layout_matches_tmux_gutters_when_not_all_items_fit() {
    let layout = tree_preview_layout(5, 2, 60).expect("layout");
    assert_eq!(layout.start, 1);
    assert_eq!(layout.end, 3);
    assert!(layout.left);
    assert!(layout.right);
    assert_eq!(layout.each, 27);
    assert_eq!(layout.remaining, 0);
}

#[test]
fn render_tree_columns_preview_draws_real_columns_and_label_boxes() {
    let utf8 = Utf8Config::default();
    let inactive = Style::parse("fg=blue").expect("style parses");
    let active = Style::parse("fg=red").expect("style parses");
    let lines = render_tree_columns_preview(
        vec![
            PreviewColumn {
                label: " 0:alpha ".to_owned(),
                label_area_width: 29,
                lines: vec!["left".to_owned(); 7],
            },
            PreviewColumn {
                label: " 1:beta ".to_owned(),
                label_area_width: 30,
                lines: vec!["right".to_owned(); 7],
            },
        ],
        0,
        60,
        7,
        &inactive,
        &active,
        &utf8,
    );

    assert_eq!(lines.len(), 7);
    assert!(lines.iter().any(|line| line.contains("left")));
    assert!(lines.iter().any(|line| line.contains("right")));
    assert!(lines.iter().any(|line| line.contains('')));
    assert!(lines.iter().any(|line| line.contains("0:alpha")));
    assert!(lines.iter().any(|line| line.contains("1:beta")));
    assert!(
        lines.iter().any(|line| line.contains("#[fg=red] 0:alpha ")),
        "active preview label should carry display-panes-active-colour"
    );
}

#[test]
fn preview_lines_for_screen_preserves_cell_colours() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 5 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"\x1b[32mRMUXHOST\x1b[0m\r\n", &mut screen);

    let lines = preview_lines_for_screen(&screen, 3, 20, &Utf8Config::default());
    assert!(
        lines
            .iter()
            .any(|line| line.contains("#[fg=green]RMUXHOST#[default]")),
        "screen preview should preserve shell prompt colours"
    );
}

#[test]
fn preview_vertical_offset_follows_tmux_cursor_bias() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 10 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n", &mut screen);

    assert_eq!(preview_vertical_offset(&screen, 4), 6);
}

#[test]
fn preview_horizontal_offset_follows_tmux_cursor_bias() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 3 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"0123456789abcdef", &mut screen);

    assert_eq!(preview_horizontal_offset(&screen, 8), 12);
}

#[test]
fn preview_lines_for_screen_uses_tmux_horizontal_cursor_window() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 3 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"0123456789abcdef", &mut screen);

    let lines = preview_lines_for_screen(&screen, 2, 8, &Utf8Config::default());

    assert!(
        lines[0].contains("cdef"),
        "preview should follow tmux and show the tail near the cursor, got {:?}",
        lines[0]
    );
    assert!(
        !lines[0].contains("0123"),
        "preview should not stay pinned to the far left once the cursor is to the right, got {:?}",
        lines[0]
    );
}

#[test]
fn render_preview_segment_row_pads_empty_preview_rows_to_full_width() {
    let inactive = Style::default();
    let column = PreviewColumn {
        label: " 0 ".to_owned(),
        label_area_width: 8,
        lines: vec![String::new()],
    };

    let rendered = render_preview_segment_row(
        &column,
        0,
        8,
        column.label_area_width,
        5,
        &inactive,
        &Utf8Config::default(),
    );

    assert_eq!(rendered, "        ");
}

#[test]
fn render_preview_segment_row_preserves_formatted_preview_lines() {
    let inactive = Style::default();
    let column = PreviewColumn {
        label: " 0 ".to_owned(),
        label_area_width: 6,
        lines: vec!["#[fg=green]abcdef#[default]".to_owned()],
    };

    let rendered = render_preview_segment_row(
        &column,
        0,
        6,
        column.label_area_width,
        5,
        &inactive,
        &Utf8Config::default(),
    );

    assert_eq!(rendered, "#[fg=green]abcdef#[default]");
}

#[test]
fn tree_window_preview_label_matches_tmux_padding() {
    assert_eq!(tree_window_preview_label(3), " 3 ");
}

#[test]
fn render_preview_segment_row_uses_tmux_ceiling_centre_for_box_labels() {
    let inactive = Style::default();
    let column = PreviewColumn {
        label: " 3 ".to_owned(),
        label_area_width: 8,
        lines: Vec::new(),
    };

    let rendered = render_preview_segment_row(
        &column,
        3,
        7,
        column.label_area_width,
        5,
        &inactive,
        &Utf8Config::default(),
    );

    assert!(
        rendered.starts_with(""),
        "tmux centres the pane box label with div_ceil, got {rendered:?}"
    );
}

#[test]
fn preview_lines_for_screen_marks_cursor_cell_reverse_like_tmux() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 3 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"prompt> ", &mut screen);

    let lines = preview_lines_for_screen(&screen, 1, 10, &Utf8Config::default());

    assert!(
        lines[0].contains("reverse"),
        "preview should reverse the cursor cell like tmux, got {:?}",
        lines[0]
    );
}

#[test]
fn preview_lines_for_screen_shows_top_content_instead_of_blank_tail() {
    let mut screen = Screen::new(TerminalSize { cols: 20, rows: 10 }, 0);
    let mut parser = InputParser::new();
    parser.parse(b"top\r\n", &mut screen);

    let lines = preview_lines_for_screen(&screen, 4, 20, &Utf8Config::default());

    assert!(
        lines.iter().any(|line| line.contains("top")),
        "cursor-anchored preview should keep top content visible"
    );
}

#[test]
fn mode_tree_list_rows_disables_preview_when_terminal_is_too_small() {
    assert_eq!(mode_tree_list_rows(3, 20, PreviewMode::Normal), 3);
    assert_eq!(mode_tree_list_rows(5, 20, PreviewMode::Normal), 5);
}

#[test]
fn mode_tree_list_rows_uses_all_rows_when_preview_is_off() {
    assert_eq!(mode_tree_list_rows(100, 20, PreviewMode::Off), 100);
    assert_eq!(mode_tree_list_rows(0, 20, PreviewMode::Off), 0);
}