1#![warn(missing_docs)]
16
17use crossterm::{
18 cursor,
19 event::{self, Event, KeyCode, KeyEvent, MouseEvent, MouseEventKind},
20 execute, queue,
21 style::Print,
22 terminal::{self, disable_raw_mode, enable_raw_mode, Clear, ClearType},
23};
24use std::io::{stdin, stdout, Write};
25
26mod status_bar;
27pub use status_bar::*;
28mod state;
29pub use state::*;
30
31pub fn run(state: &mut State) -> std::io::Result<()> {
33 let mut out = stdout();
34 disable_raw_mode()?;
35 execute!(
36 out,
37 terminal::Clear(ClearType::All),
38 cursor::MoveTo(0, 0),
39 Print(state.get_visible()),
40 cursor::MoveTo(0, state.size.1 - state.status_bar.line_layouts.len() as u16),
41 Print(state.status_bar.get_visible(state))
42 )?;
43 enable_raw_mode()?;
44
45 while state.running {
46 let read_event = event::read()?;
47 let flush = match read_event {
48 Event::Key(KeyEvent { code, .. }) => match code {
49 KeyCode::Char(':') => {
50 disable_raw_mode()?;
51 execute!(
52 out,
53 cursor::MoveTo(0, state.size.1 - 1),
54 Clear(ClearType::CurrentLine),
55 cursor::Show,
56 Print(":")
57 )?;
58 let mut buf = String::new();
59 stdin().read_line(&mut buf)?;
60 let buf = buf.lines().next().unwrap();
61
62 let found = state.commands.0.clone().into_iter().find(
63 |command| matches!(command, Command { cmd, .. } if cmd.contains(&CommandType::Colon(buf.to_string()))),
64 );
65 let retrn = if let Some(Command { func, .. }) = found {
66 func(state)
67 } else {
68 false
69 };
70
71 execute!(out, Print(retrn), cursor::Hide)?;
72 enable_raw_mode()?;
73 retrn
74 }
75 code => state.match_key_event(code),
76 },
77 Event::Mouse(ev) => match ev {
78 MouseEvent {
79 kind: MouseEventKind::ScrollUp,
80 ..
81 } => state.up(),
82 MouseEvent {
83 kind: MouseEventKind::ScrollDown,
84 ..
85 } => state.down(),
86 _ => false,
87 },
88 Event::Resize(x, y) => {
89 state.size = (x, y);
90 true
91 }
92 _ => false,
93 };
94 if flush {
95 disable_raw_mode()?;
96 queue!(
97 out,
98 cursor::MoveTo(0, 0),
99 terminal::Clear(ClearType::All),
100 Print(state.get_visible()),
101 cursor::MoveTo(0, state.size.1 - state.status_bar.line_layouts.len() as u16),
102 Print(state.status_bar.get_visible(state)),
103 )?;
104 out.flush()?;
105 enable_raw_mode()?;
106 }
107 }
108
109 disable_raw_mode()?;
110
111 Ok(())
112}
113
114pub fn init() -> std::io::Result<()> {
119 let mut out = stdout();
120 execute!(
121 out,
122 terminal::EnterAlternateScreen,
123 event::EnableMouseCapture,
124 cursor::Hide,
125 )
126}
127
128pub fn finish() -> std::io::Result<()> {
131 let mut out = stdout();
132 execute!(
133 out,
134 event::DisableMouseCapture,
135 terminal::LeaveAlternateScreen,
136 cursor::Show
137 )
138}