libtui 0.1.0

A crate to create TUIs.
Documentation
pub mod window;
pub mod terminal;
use std::io::Write;

use terminal::Terminal;
use window::{Config, Location, Window};

pub fn init(alternative_screen: bool) -> App {
    if alternative_screen {
        print!("\x1b[?1049h\x1b[H");
        std::io::stdout().flush().unwrap();
    }
    let term = Terminal::default();
    let wins = Vec::new();
    App { term, wins }
}

pub struct App {
    term:     Terminal,
    pub wins: Vec<Window>
}

impl App {
    pub fn push(&mut self, window: Window) {
        self.wins.push(window);
    }

    pub fn render(&self, conf: &Config) {
        print!("\x1b[2J\x1b[H");
        std::io::stdout().flush().unwrap();
        for i in &self.wins {
            // this is for starting the window content with/without the top_bar
            let mut line_number = 0;

            let mut left_side_line_num = i.left_side_line_num;
            let mut right_side_line_num = i.right_side_line_num;
            if !i.left_column {
                left_side_line_num = None;
            }
            if !i.right_column {
                right_side_line_num = None;
            }
            let size = i.dimensions.width as usize - (conf.border_len[0] + conf.border_len[1]);
            let border_h = conf.border_h.to_string();
            let border_h = &border_h[..];
            let msg = match i.title.chars().count() <= size {
                | true => match conf.title {
                    | Location::Left => format!("{}{}", &i.title, border_h.repeat(size - i.title.chars().count() + 1)),
                    | Location::Right => format!("{}{}", border_h.repeat(size - i.title.chars().count() + 1), &i.title),
                    | Location::Center => {
                        let total_spaces = size - i.title.chars().count();
                        let mod_spaces = match total_spaces % 2 {
                            | 0 => "",
                            | _ => border_h
                        };
                        format!("{}{}{}{}", border_h.repeat(total_spaces / 2 + 1), &i.title, border_h.repeat(total_spaces / 2), mod_spaces)
                    }
                },
                | false => {
                    if (i.dimensions.width as usize) <= conf.border_len[0] + conf.border_len[1] {
                        if (i.dimensions.width as usize) == conf.border_len[0] + conf.border_len[1] {
                            i.title[0 .. 1].to_string()
                        } else {
                            String::new()
                        }
                    } else {
                        i.title[0 .. size + 1].to_owned()
                    }
                },
            };
            // Write out the top bar
            if i.top_bar {
                println!("\x1b[{};{}H{}{}{}", i.pos.y + 1, i.pos.x + 1, conf.border_connector[0], msg, conf.border_connector[1]);
                line_number += 1;
            }

            // Write out the content of the  window
            let mut lines: Vec<&str> = i.content.split('\n').collect();

            let window_vert_taken_size = match (i.top_bar, i.bottom_bar) {
                | (true, true) => 2,
                | (false, false) => 0,
                | _ => 1
            };

            while lines.len() > i.dimensions.height as usize - window_vert_taken_size {
                lines.pop();
            }

            for line_num in line_number .. lines.len() + line_number {
                match left_side_line_num {
                    | Some((ln, cn)) => {
                        let sub_num = line_number;
                        let mut line_num_bar = (ln + line_num - 1).to_string();
                        while line_num_bar.len() < lines.len().to_string().len() {
                            line_num_bar.push(' ');
                        }
                        let line_num_format = match line_num_bar.replace(" ", "") == cn.to_string() {
                            | false => format!("{}{}\x1b[0m", conf.line_num.std_num_color, line_num_bar),
                            | true => format!("{}{}\x1b[0m", conf.line_num.current_num_color, line_num_bar)
                        };
                        if i.left_column {
                            print!("\x1b[{};{}H{}{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, line_num_format, lines[line_num - sub_num]);
                        } else {
                            print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, lines[line_num - sub_num]);
                        }
                        if right_side_line_num == None {
                            if i.right_column {
                                print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, size + 3 + i.pos.x as usize, conf.border_v);
                            }
                        } else if i.right_column {
                            print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, size + 4 + i.pos.x as usize - line_num_bar.len(), line_num_format);
                        }
                    },
                    | None => match right_side_line_num {
                        | None => {
                            let sub_num = line_number;
                            if i.left_column {
                                print!("\x1b[{};{}H{}{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, conf.border_v, lines[line_num - sub_num]);
                            } else {
                                print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, lines[line_num - sub_num]);
                            }
                            if i.right_column {
                                print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, size + 3 + i.pos.x as usize, conf.border_v);
                            }
                        },
                        | Some((ln, cn)) => {
                            let sub_num = line_number;
                            let mut line_num_bar = (ln + line_num).to_string();
                            while line_num_bar.len() < lines.len().to_string().len() {
                                line_num_bar.push(' ');
                            }
                            let line_num_format = match line_num_bar.replace(" ", "") == cn.to_string() {
                                | false => format!("{}{}\x1b[0m", conf.line_num.std_num_color, line_num_bar),
                                | true => format!("{}{}\x1b[0m", conf.line_num.current_num_color, line_num_bar)
                            };
                            if i.left_column {
                                print!("\x1b[{};{}H{}{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, conf.border_v, lines[line_num - sub_num]);
                            } else {
                                print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, i.pos.x + 1, lines[line_num - sub_num]);
                            }
                            if i.right_column {
                                print!("\x1b[{};{}H{}", i.pos.y as usize + line_num + 1, size + 3 + i.pos.x as usize, line_num_format);
                            }
                        }
                    }
                }
            }

            if !i.top_bar {
                line_number = 1;
            } else {
                line_number = 0;
            }

            let mut bottom_number = 0;
            if !i.bottom_bar {
                bottom_number = 1;
            }

            // Write out any lines that aren't filled by the window content
            if lines.len() - line_number < i.dimensions.height as usize - window_vert_taken_size - line_number + bottom_number {
                for j in lines.len() - line_number .. i.dimensions.height as usize - window_vert_taken_size - line_number + bottom_number {
                    if left_side_line_num == None {
                        if i.left_column {
                            print!("\x1b[{};{}H{}", i.pos.y as usize + j + 2, i.pos.x + 1, conf.border_v);
                        }
                    } else {
                        let vert_col = format!("{}{}\x1b[0m", conf.line_num.std_num_color, " ".repeat(lines.len().to_string().len()));
                        if i.left_column {
                            print!("\x1b[{};{}H{}", i.pos.y as usize + j + 2, i.pos.x + 1, vert_col);
                        }
                    }
                    if right_side_line_num == None {
                        if i.right_column {
                            print!("\x1b[{};{}H{}", i.pos.y as usize + j + 2, size + 3 + i.pos.x as usize, conf.border_v);
                        }
                    } else if i.right_column {
                        let vert_col = format!("{}{}\x1b[0m", conf.line_num.std_num_color, " ".repeat(lines.len().to_string().len()));
                        print!("\x1b[{};{}H{}", i.pos.y as usize + j + 2, size + 4 + i.pos.x as usize - lines.len().to_string().len(), vert_col);
                    }
                }
            }

            // Write out the bottom bar
            if i.bottom_bar {
                print!("\x1b[{};{}H{}{}{}", i.pos.y + i.dimensions.height, i.pos.x + 1, conf.border_connector[2], border_h.repeat(size + 1), conf.border_connector[3]);
            }
            std::io::stdout().flush().unwrap();
        }
    }
}