Open urls
This commit is contained in:
parent
e7946333ad
commit
006eba0dfe
3 changed files with 59 additions and 14 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
|
@ -166,6 +166,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"log",
|
"log",
|
||||||
|
"open",
|
||||||
"procfs",
|
"procfs",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -314,6 +315,16 @@ version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "open"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4a3100141f1733ea40b53381b0ae3117330735ef22309a190ac57b9576ea716"
|
||||||
|
dependencies = [
|
||||||
|
"pathdiff",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|
@ -337,6 +348,12 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pathdiff"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ edition = "2021"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
crossterm = { version = "0.25", features = ["event-stream"] }
|
crossterm = { version = "0.25", features = ["event-stream"] }
|
||||||
|
log = { version = "0.4", features = ["std"] }
|
||||||
|
open = "3"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
log = { version = "0.4", features = ["std"] }
|
|
||||||
|
|
||||||
[target.'cfg(target_os="linux")'.dependencies]
|
[target.'cfg(target_os="linux")'.dependencies]
|
||||||
procfs = "0.14.1"
|
procfs = "0.14.1"
|
||||||
|
|
|
||||||
53
src/ui.rs
53
src/ui.rs
|
|
@ -11,6 +11,7 @@ use crossterm::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use log::{Level, Metadata, Record};
|
use log::{Level, Metadata, Record};
|
||||||
|
use open;
|
||||||
use std::collections::vec_deque::VecDeque;
|
use std::collections::vec_deque::VecDeque;
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
@ -62,20 +63,42 @@ async fn run_ui_core(
|
||||||
execute!(stdout, EnterAlternateScreen, DisableLineWrap)?;
|
execute!(stdout, EnterAlternateScreen, DisableLineWrap)?;
|
||||||
let mut events = EventStream::new();
|
let mut events = EventStream::new();
|
||||||
|
|
||||||
|
let mut selection = 0;
|
||||||
let mut show_logs = false;
|
let mut show_logs = false;
|
||||||
let mut lines: VecDeque<String> = VecDeque::with_capacity(1024);
|
let mut lines: VecDeque<String> = VecDeque::with_capacity(1024);
|
||||||
let mut ports = None;
|
let mut ports: Option<Vec<PortDesc>> = None;
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
ev = events.next() => {
|
ev = events.next() => {
|
||||||
match ev {
|
match ev {
|
||||||
Some(Ok(Event::Key(ev))) => {
|
Some(Ok(Event::Key(ev))) => {
|
||||||
match ev {
|
match ev {
|
||||||
KeyEvent {code:KeyCode::Esc, ..} => { break; },
|
KeyEvent {code:KeyCode::Esc, ..}
|
||||||
KeyEvent {code:KeyCode::Char('q'), ..} => { break; },
|
| KeyEvent {code:KeyCode::Char('q'), ..} => { break; },
|
||||||
KeyEvent {code:KeyCode::Char('l'), ..} => {
|
KeyEvent {code:KeyCode::Char('l'), ..} => {
|
||||||
show_logs = !show_logs;
|
show_logs = !show_logs;
|
||||||
}
|
}
|
||||||
|
KeyEvent { code:KeyCode::Up, ..}
|
||||||
|
| KeyEvent { code:KeyCode::Char('j'), ..} => {
|
||||||
|
if selection > 0 {
|
||||||
|
selection -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyEvent { code:KeyCode::Down, ..}
|
||||||
|
| KeyEvent { code:KeyCode::Char('k'), ..} => {
|
||||||
|
if let Some(p) = &ports {
|
||||||
|
if selection != p.len() - 1 {
|
||||||
|
selection += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyEvent { code:KeyCode::Enter, ..} => {
|
||||||
|
if let Some(p) = &ports {
|
||||||
|
if selection < p.len() {
|
||||||
|
_ = open::that(format!("http://127.0.0.1:{}/", p[selection].port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -86,7 +109,10 @@ async fn run_ui_core(
|
||||||
}
|
}
|
||||||
pr = port_receiver.recv() => {
|
pr = port_receiver.recv() => {
|
||||||
match pr {
|
match pr {
|
||||||
Some(p) => { ports = Some(p); }
|
Some(mut p) => {
|
||||||
|
p.sort_by(|a, b| a.port.partial_cmp(&b.port).unwrap());
|
||||||
|
ports = Some(p);
|
||||||
|
}
|
||||||
None => break,
|
None => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -112,28 +138,25 @@ async fn run_ui_core(
|
||||||
let columns: usize = columns.into();
|
let columns: usize = columns.into();
|
||||||
let padding = 1;
|
let padding = 1;
|
||||||
let port_width = 5; // 5 characters for 16-bit number
|
let port_width = 5; // 5 characters for 16-bit number
|
||||||
let url_width = "http://127.0.0.1:/".len() + port_width;
|
|
||||||
|
|
||||||
let description_width = columns - (padding + port_width + padding + url_width + padding);
|
let description_width = columns - (padding + padding + port_width + padding);
|
||||||
|
|
||||||
print!(
|
print!(
|
||||||
"{}",
|
"{}",
|
||||||
format!(
|
format!(
|
||||||
" {port:>port_width$} {url:<url_width$} {description:<description_width$}\r\n",
|
" {port:>port_width$} {description:<description_width$}\r\n",
|
||||||
port = "port",
|
port = "port",
|
||||||
url = "url",
|
|
||||||
description = "description"
|
description = "description"
|
||||||
)
|
)
|
||||||
.negative()
|
.negative()
|
||||||
);
|
);
|
||||||
if let Some(ports) = &mut ports {
|
if let Some(ports) = &mut ports {
|
||||||
ports.sort_by(|a, b| a.port.partial_cmp(&b.port).unwrap());
|
|
||||||
let max_ports: usize = if show_logs { (rows / 2) - 1 } else { rows - 2 }.into();
|
let max_ports: usize = if show_logs { (rows / 2) - 1 } else { rows - 2 }.into();
|
||||||
for port in ports.into_iter().take(max_ports) {
|
for (index, port) in ports.into_iter().take(max_ports).enumerate() {
|
||||||
print!(
|
print!(
|
||||||
" {:port_width$} {:url_width$} {:description_width$}\r\n",
|
"{} {:port_width$} {:description_width$}\r\n",
|
||||||
|
if index == selection { "\u{2B46}" } else { " " },
|
||||||
port.port,
|
port.port,
|
||||||
format!("http://127.0.0.1:{}/", port.port),
|
|
||||||
port.desc
|
port.desc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -158,7 +181,11 @@ async fn run_ui_core(
|
||||||
queue!(stdout, MoveTo(0, rows - 1))?;
|
queue!(stdout, MoveTo(0, rows - 1))?;
|
||||||
print!(
|
print!(
|
||||||
"{}",
|
"{}",
|
||||||
format!("{:columns$}", " Press ESC or q to quit | l - toggle log").negative()
|
format!(
|
||||||
|
"{:columns$}",
|
||||||
|
" q - quit | l - toggle log | \u{2191}/\u{2193} - select port | <enter> - browse"
|
||||||
|
)
|
||||||
|
.negative()
|
||||||
);
|
);
|
||||||
stdout.flush()?;
|
stdout.flush()?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue