Skip to content

Commit

Permalink
feat: better error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
kabouzeid committed Mar 28, 2023
1 parent 904ff7c commit ad47d19
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 29 deletions.
31 changes: 22 additions & 9 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crossbeam::{
use std::path::PathBuf;
use std::time::Duration;

use crate::file_watcher::FileWatcherHandle;
use crate::file_watcher::{FileWatcherError, FileWatcherHandle};
use crate::job_watcher::JobWatcherHandle;

use crossterm::event::{Event, KeyCode, KeyEvent};
Expand All @@ -27,7 +27,7 @@ pub struct App {
focus: Focus,
jobs: Vec<Job>,
job_list_state: ListState,
job_stdout: Option<String>,
job_stdout: Result<String, FileWatcherError>,
job_stdout_offset: u16,
_job_watcher: JobWatcherHandle,
job_stdout_watcher: FileWatcherHandle,
Expand All @@ -52,7 +52,7 @@ pub struct Job {

pub enum AppMessage {
Jobs(Vec<Job>),
JobStdout(Option<String>),
JobStdout(Result<String, FileWatcherError>),
Key(KeyEvent),
}

Expand All @@ -64,7 +64,7 @@ impl App {
jobs: Vec::new(),
_job_watcher: JobWatcherHandle::new(sender.clone(), Duration::from_secs(2)),
job_list_state: ListState::default(),
job_stdout: None,
job_stdout: Ok("".to_string()),
job_stdout_offset: 0,
job_stdout_watcher: FileWatcherHandle::new(sender.clone(), Duration::from_secs(10)),
// sender,
Expand Down Expand Up @@ -292,16 +292,29 @@ impl App {
]);
let log_block = Block::default().title(log_title).borders(Borders::ALL);

let job_log = self.job_stdout.as_deref().map(|s| {
string_for_paragraph(
// let job_log = self.job_stdout.as_deref().map(|s| {
// string_for_paragraph(
// s,
// log_block.inner(log_area).height as usize,
// log_block.inner(log_area).width as usize,
// self.job_stdout_offset as usize,
// )
// }).unwrap_or_else(|e| {
// self.job_stdout_offset = 0;
// "".to_string()
// });

let job_log = match self.job_stdout.as_deref() {
Ok(s) => Text::raw(string_for_paragraph(
s,
log_block.inner(log_area).height as usize,
log_block.inner(log_area).width as usize,
self.job_stdout_offset as usize,
)
});
)),
Err(e) => Text::styled(e.to_string(), Style::default().fg(Color::Red)),
};

let log = Paragraph::new(job_log.unwrap_or_default()).block(log_block);
let log = Paragraph::new(job_log).block(log_block);

f.render_widget(log, log_area);
}
Expand Down
40 changes: 25 additions & 15 deletions src/file_watcher.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
fs,
fmt, fs, io,
path::{Path, PathBuf},
thread,
time::Duration,
Expand All @@ -14,9 +14,9 @@ use notify::{event::ModifyKind, RecursiveMode, Watcher};
use crate::app::AppMessage;

struct FileReader {
content_sender: Sender<Option<String>>,
content_sender: Sender<io::Result<String>>,
receiver: Receiver<()>,
file_path: Option<PathBuf>,
file_path: PathBuf,
interval: Duration,
}

Expand All @@ -35,6 +35,20 @@ pub struct FileWatcherHandle {
file_path: Option<PathBuf>,
}

pub enum FileWatcherError {
Watcher(notify::Error),
File(io::Error),
}

impl fmt::Display for FileWatcherError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FileWatcherError::Watcher(e) => write!(f, "Watcher error: {}", e),
FileWatcherError::File(e) => write!(f, "Read error: {}", e),
}
}
}

impl FileWatcher {
fn new(
app: Sender<AppMessage>,
Expand Down Expand Up @@ -62,7 +76,7 @@ impl FileWatcher {
})
.unwrap();

let (mut _content_sender, mut _content_receiver) = unbounded::<Option<String>>();
let (mut _content_sender, mut _content_receiver) = unbounded::<io::Result<String>>();
let (mut _watch_sender, mut _watch_receiver) = unbounded::<()>();
loop {
select! {
Expand All @@ -81,20 +95,19 @@ impl FileWatcher {
let res = watcher.watch(Path::new(&p), RecursiveMode::NonRecursive);
match res {
Ok(_) => {
self.file_path = Some(p);
let p = self.file_path.clone();
self.file_path = Some(p.clone());
let i = self.interval.clone();
thread::spawn(move || FileReader::new(_content_sender, _watch_receiver, p, i).run());
},
Err(e) => self.app.send(AppMessage::JobStdout(Some(format!("Failed to watch {:?}: {}", p, e)))).unwrap()
Err(e) => self.app.send(AppMessage::JobStdout(Err(FileWatcherError::Watcher(e)))).unwrap()
};
}
}
}
}
recv(watch_receiver) -> _ => { _watch_sender.send(()).unwrap(); }
recv(_content_receiver) -> msg => {
self.app.send(AppMessage::JobStdout(msg.unwrap())).unwrap();
self.app.send(AppMessage::JobStdout(msg.unwrap().map_err(|e| FileWatcherError::File(e)))).unwrap();
}
}
}
Expand All @@ -103,9 +116,9 @@ impl FileWatcher {

impl FileReader {
fn new(
content_sender: Sender<Option<String>>,
content_sender: Sender<io::Result<String>>,
receiver: Receiver<()>,
file_path: Option<PathBuf>,
file_path: PathBuf,
interval: Duration,
) -> Self {
FileReader {
Expand All @@ -129,11 +142,8 @@ impl FileReader {
}
}

fn update(&self) -> Result<(), SendError<Option<String>>> {
let s = self.file_path.as_ref().and_then(|file_path| {
// TODO: partial read only
fs::read_to_string(file_path).ok()
});
fn update(&self) -> Result<(), SendError<io::Result<String>>> {
let s = fs::read_to_string(&self.file_path); // TODO: partial read only
self.content_sender.send(s)
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ mod app;
mod file_watcher;
mod job_watcher;

use app::{App};
use crossbeam::{
channel::{unbounded, Sender},
};
use app::App;
use crossbeam::channel::{unbounded, Sender};
use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use std::{io, thread};
use tui::{
backend::{Backend, CrosstermBackend}, Terminal,
backend::{Backend, CrosstermBackend},
Terminal,
};

fn main() -> Result<(), io::Error> {
Expand Down

0 comments on commit ad47d19

Please sign in to comment.