cic/
lib.rs

1use crossterm::terminal;
2
3pub mod input;
4mod render;
5pub use render::Renderer;
6mod table;
7pub use table::Table;
8pub use input::{Dir, PromptAction, Action};
9
10use std::fmt;
11
12#[derive(Clone, Copy, Debug)]
13pub enum Mode {
14    Prompt(PromptType),
15    Table,
16    Insert,
17    Exit,  // could remove and use option<mode> otherwise
18}
19
20impl fmt::Display for Mode {
21    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
22        use Mode::*;
23        let s = match self {
24            Insert => "Insert Mode",
25            Table => "Movement Mode",
26            Prompt(_) => "Prompt",
27            _ => "",
28        };
29        write!(f, "{}", s)
30    }
31}
32
33#[derive(Clone, Copy, Debug)]
34pub enum PromptType {
35    EditReplace,
36    EditAppend,
37    Command,
38}
39
40impl PromptType {
41    fn ps2(self) -> String {
42        use PromptType::*;
43        match self {
44            EditReplace => "edit: ",
45            EditAppend => "edit: ",
46            Command => ":",
47        }.to_string()
48    }
49}
50
51/// needs a table for context (also usize)
52#[derive(Clone, Copy, Debug)]
53pub struct Cursor {
54    pub x: usize,
55    pub y: usize,
56}
57
58impl Cursor {
59    pub fn new() -> Self {
60        Self { x: 0, y: 0 }
61    }
62
63    pub fn move_dir(&mut self, dir: Dir, table: &Table) {
64        use Dir::*;
65        match dir {
66            Up => if self.y > 0 {
67                self.y -= 1;
68            }
69            Down => if self.y < table.dims().1 - 1 {
70                self.y += 1;
71            }
72            Left => if self.x > 0 {
73                self.x -= 1;
74            }
75            Right => if self.x < table.dims().0 - 1 {
76                self.x += 1;
77            }
78            Top => {
79                self.y = 0;
80            }
81            Bottom => {
82                self.y = table.dims().1 - 1;
83            }
84            Start => {
85                self.x = 0;
86            }
87            End => {
88                self.x = table.dims().0 - 1;
89            }
90        }
91    }
92}
93
94pub fn align_anchor(anchor: &mut Cursor, c: Cursor) {
95    let (w, hs) = terminal::size().unwrap();
96    let h = hs as usize;
97    
98    // is cursor above anchor?
99    if anchor.y > c.y {
100        anchor.y = c.y;
101    }
102
103    // is cursor below screen?
104    // -2 is for padding
105    if anchor.y + h - 3 < c.y {
106        anchor.y = c.y + 3 - h; // order matters with usize
107    }
108}