mirror of
https://github.com/Noratrieb/service-manager.git
synced 2026-01-16 17:35:05 +01:00
broken :(
This commit is contained in:
parent
2910482b03
commit
b52292f667
3 changed files with 62 additions and 17 deletions
|
|
@ -10,7 +10,7 @@ use std::collections::HashMap;
|
||||||
use std::io::{ErrorKind, Write};
|
use std::io::{ErrorKind, Write};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::{mpsc, Arc, Mutex};
|
use std::sync::{mpsc, Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::{Duration, Instant};
|
||||||
use std::{io, thread};
|
use std::{io, thread};
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
use tui::backend::Backend;
|
use tui::backend::Backend;
|
||||||
|
|
@ -27,9 +27,7 @@ pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> SmResult
|
||||||
loop {
|
loop {
|
||||||
terminal.draw(|f| view::render_ui(f, &mut app))?;
|
terminal.draw(|f| view::render_ui(f, &mut app))?;
|
||||||
|
|
||||||
app.recv_stdouts();
|
if event::poll(Duration::from_secs(0))? {
|
||||||
|
|
||||||
if event::poll(Duration::from_millis(10))? {
|
|
||||||
if let Event::Key(key) = event::read()? {
|
if let Event::Key(key) = event::read()? {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') => match app.selected {
|
KeyCode::Char('q') => match app.selected {
|
||||||
|
|
@ -40,14 +38,22 @@ pub fn run_app<B: Backend>(terminal: &mut Terminal<B>, mut app: App) -> SmResult
|
||||||
},
|
},
|
||||||
KeyCode::Char('r') => app.run_service()?,
|
KeyCode::Char('r') => app.run_service()?,
|
||||||
KeyCode::Char('k') => app.kill_service()?,
|
KeyCode::Char('k') => app.kill_service()?,
|
||||||
KeyCode::Down => app.next(),
|
KeyCode::Down => match app.selected {
|
||||||
KeyCode::Up => app.previous(),
|
Some(_) => app.scroll_down(),
|
||||||
|
None => app.next(),
|
||||||
|
},
|
||||||
|
KeyCode::Up => match app.selected {
|
||||||
|
Some(_) => app.scroll_up(),
|
||||||
|
None => app.previous(),
|
||||||
|
},
|
||||||
KeyCode::Enter => app.select_service(),
|
KeyCode::Enter => app.select_service(),
|
||||||
KeyCode::Esc => app.leave_service(),
|
KeyCode::Esc => app.leave_service(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.recv_stdouts(Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminate the child processes
|
// terminate the child processes
|
||||||
|
|
@ -80,6 +86,7 @@ impl App {
|
||||||
env: service.env.unwrap_or_else(HashMap::new),
|
env: service.env.unwrap_or_else(HashMap::new),
|
||||||
status: Arc::new(Mutex::new(ServiceStatus::NotStarted)),
|
status: Arc::new(Mutex::new(ServiceStatus::NotStarted)),
|
||||||
std_io_buf: Vec::new(),
|
std_io_buf: Vec::new(),
|
||||||
|
std_io_line_cache: Vec::new(),
|
||||||
stdout: StdIoStream {
|
stdout: StdIoStream {
|
||||||
recv: stdout_recv,
|
recv: stdout_recv,
|
||||||
send: stdout_send,
|
send: stdout_send,
|
||||||
|
|
@ -89,6 +96,7 @@ impl App {
|
||||||
.collect::<io::Result<_>>()?,
|
.collect::<io::Result<_>>()?,
|
||||||
},
|
},
|
||||||
selected: None,
|
selected: None,
|
||||||
|
scroll_pos: None,
|
||||||
thread_terminates: HashMap::new(),
|
thread_terminates: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -97,13 +105,30 @@ impl App {
|
||||||
self.selected.is_none()
|
self.selected.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv_stdouts(&mut self) {
|
fn recv_stdouts(&mut self, duration: Duration) {
|
||||||
for service in self.table.services.iter_mut() {
|
for service in self.table.services.iter_mut() {
|
||||||
while let Ok((buf, n)) = service.stdout.recv.try_recv() {
|
let start = Instant::now();
|
||||||
service.std_io_buf.extend(&buf[0..n]);
|
let buf = &mut service.std_io_buf;
|
||||||
|
|
||||||
if service.std_io_buf.len() > 2_000_000 {
|
while let Ok((new_buf, n)) = service.stdout.recv.try_recv() {
|
||||||
service.std_io_buf.clear(); // todo don't
|
let len_before = buf.len();
|
||||||
|
buf.extend(&new_buf[0..n]);
|
||||||
|
|
||||||
|
let new_newline_positions = new_buf
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, &byte)| byte == b'\n')
|
||||||
|
.map(|(position, _)| position + len_before);
|
||||||
|
|
||||||
|
service.std_io_line_cache.extend(new_newline_positions);
|
||||||
|
|
||||||
|
if buf.len() > 2_000_000 {
|
||||||
|
buf.clear(); // todo don't
|
||||||
|
service.std_io_line_cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if start.elapsed() > duration {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,6 +174,14 @@ impl App {
|
||||||
self.table.table_state.select(Some(i));
|
self.table.table_state.select(Some(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scroll_up(&mut self) {
|
||||||
|
self.scroll_pos = self.scroll_pos.map(|pos| pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_down(&mut self) {
|
||||||
|
self.scroll_pos = self.scroll_pos.map(|pos| pos - 1);
|
||||||
|
}
|
||||||
|
|
||||||
fn run_service(&mut self) -> SmResult {
|
fn run_service(&mut self) -> SmResult {
|
||||||
let index = self.selected.or_else(|| self.table.table_state.selected());
|
let index = self.selected.or_else(|| self.table.table_state.selected());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ pub use error::{SmError, SmResult};
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub table: AppState,
|
pub table: AppState,
|
||||||
pub selected: Option<usize>,
|
pub selected: Option<usize>,
|
||||||
|
pub scroll_pos: Option<usize>,
|
||||||
pub thread_terminates: HashMap<usize, mpsc::Sender<()>>,
|
pub thread_terminates: HashMap<usize, mpsc::Sender<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,6 +28,8 @@ pub struct Service {
|
||||||
pub env: HashMap<String, String>,
|
pub env: HashMap<String, String>,
|
||||||
pub status: Arc<Mutex<ServiceStatus>>,
|
pub status: Arc<Mutex<ServiceStatus>>,
|
||||||
pub std_io_buf: Vec<u8>,
|
pub std_io_buf: Vec<u8>,
|
||||||
|
/// The start position of every line number
|
||||||
|
pub std_io_line_cache: Vec<usize>,
|
||||||
pub stdout: StdIoStream,
|
pub stdout: StdIoStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
21
src/view.rs
21
src/view.rs
|
|
@ -41,12 +41,21 @@ fn render_full_view<B: Backend>(f: &mut Frame<B>, state: &mut AppState, index: u
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title("service".as_ref());
|
.title("service".as_ref());
|
||||||
|
|
||||||
let len = service.std_io_buf.len();
|
let height = area.height - 2; // the block takes up 2 lines
|
||||||
let stdout = if len > 10000 {
|
let buf_len = service.std_io_buf.len();
|
||||||
String::from_utf8_lossy(&service.std_io_buf[len - 10000..len])
|
|
||||||
} else {
|
let display_start_pos = service
|
||||||
String::from_utf8_lossy(&service.std_io_buf)
|
.std_io_line_cache
|
||||||
};
|
.get(
|
||||||
|
service
|
||||||
|
.std_io_line_cache
|
||||||
|
.len()
|
||||||
|
.saturating_sub(usize::from(height)),
|
||||||
|
)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(0);
|
||||||
|
|
||||||
|
let stdout = String::from_utf8_lossy(&service.std_io_buf[display_start_pos..buf_len]);
|
||||||
|
|
||||||
let paragraph = Paragraph::new(stdout.as_ref()).block(block.clone());
|
let paragraph = Paragraph::new(stdout.as_ref()).block(block.clone());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue