Better UI, needs two keys to close :(
This commit is contained in:
parent
2d9b9dbf9a
commit
de6607eb25
4 changed files with 106 additions and 21 deletions
103
src/ui.rs
103
src/ui.rs
|
|
@ -2,33 +2,98 @@ use crate::message::PortDesc;
|
|||
use anyhow::Result;
|
||||
use crossterm::{
|
||||
cursor::MoveTo,
|
||||
execute,
|
||||
event::{Event, EventStream, KeyCode, KeyEvent},
|
||||
execute, queue,
|
||||
style::Stylize,
|
||||
terminal::{
|
||||
Clear, ClearType, DisableLineWrap, EnableLineWrap, EnterAlternateScreen,
|
||||
LeaveAlternateScreen,
|
||||
disable_raw_mode, enable_raw_mode, size, Clear, ClearType, DisableLineWrap, EnableLineWrap,
|
||||
EnterAlternateScreen, LeaveAlternateScreen,
|
||||
},
|
||||
};
|
||||
use std::io::stdout;
|
||||
use std::io::{stdout, Write};
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
pub async fn run_ui(port_receiver: &mut mpsc::Receiver<Vec<PortDesc>>) -> Result<()> {
|
||||
let mut stdout = stdout();
|
||||
execute!(stdout, EnterAlternateScreen, DisableLineWrap)?;
|
||||
while let Some(mut ports) = port_receiver.recv().await {
|
||||
ports.sort_by(|a, b| a.port.partial_cmp(&b.port).unwrap());
|
||||
enable_raw_mode()?;
|
||||
let result = run_ui_core(port_receiver).await;
|
||||
execute!(stdout(), EnableLineWrap, LeaveAlternateScreen)?;
|
||||
disable_raw_mode()?;
|
||||
result
|
||||
}
|
||||
|
||||
execute!(stdout, Clear(ClearType::All), MoveTo(0, 0))?;
|
||||
println!("Port Url Description");
|
||||
println!("----- ------------------------ -----------");
|
||||
for port in ports {
|
||||
println!(
|
||||
"{:5} {:24} {}",
|
||||
port.port,
|
||||
format!("http://locahost:{}/", port.port),
|
||||
port.desc
|
||||
);
|
||||
async fn run_ui_core(port_receiver: &mut mpsc::Receiver<Vec<PortDesc>>) -> Result<()> {
|
||||
let mut stdout = stdout();
|
||||
|
||||
execute!(stdout, EnterAlternateScreen, DisableLineWrap)?;
|
||||
let mut events = EventStream::new();
|
||||
|
||||
let mut ports = None;
|
||||
loop {
|
||||
tokio::select! {
|
||||
ev = events.next() => {
|
||||
match ev {
|
||||
Some(Ok(Event::Key(ev))) => {
|
||||
match ev {
|
||||
KeyEvent {code:KeyCode::Esc, ..} => { break; },
|
||||
KeyEvent {code:KeyCode::Char('q'), ..} => { break; },
|
||||
_ => ()
|
||||
}
|
||||
},
|
||||
Some(Ok(_)) => (), // Don't care about this event...
|
||||
Some(Err(_)) => (), // Hmmmmmm.....?
|
||||
None => (), // ....no events? what?
|
||||
}
|
||||
}
|
||||
pr = port_receiver.recv() => {
|
||||
match pr {
|
||||
Some(p) => { ports = Some(p); }
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (columns, rows) = size()?;
|
||||
|
||||
queue!(stdout, Clear(ClearType::All), MoveTo(0, 0))?;
|
||||
|
||||
// How wide are all the things?
|
||||
let columns: usize = columns.into();
|
||||
let padding = 1;
|
||||
let port_width = 5; // 5 characters for 16-bit number
|
||||
let url_width = "http://localhost:/".len() + port_width;
|
||||
|
||||
let description_width = columns - (padding + port_width + padding + url_width + padding);
|
||||
|
||||
print!(
|
||||
"{}",
|
||||
format!(
|
||||
" {port:>port_width$} {url:<url_width$} {description:<description_width$}\r\n",
|
||||
port = "port",
|
||||
url = "url",
|
||||
description = "description"
|
||||
)
|
||||
.negative()
|
||||
);
|
||||
if let Some(ports) = &mut ports {
|
||||
ports.sort_by(|a, b| a.port.partial_cmp(&b.port).unwrap());
|
||||
for port in ports {
|
||||
print!(
|
||||
" {:port_width$} {:url_width$} {:description_width$}\r\n",
|
||||
port.port,
|
||||
format!("http://locahost:{}/", port.port),
|
||||
port.desc
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
queue!(stdout, MoveTo(0, rows - 1))?;
|
||||
print!(
|
||||
"{}",
|
||||
format!("{:columns$}", " Press ESC or q to quit").negative()
|
||||
);
|
||||
stdout.flush()?;
|
||||
}
|
||||
execute!(stdout, EnableLineWrap, LeaveAlternateScreen)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue