Skip to content

Commit

Permalink
feat: Command execution log (ChrisTitusTech#898)
Browse files Browse the repository at this point in the history
* feat: option to save logs

* refact: use time crate

* fix: panics

* hints

* update roadmap
  • Loading branch information
jeevithakannan2 authored Nov 8, 2024
1 parent 17ff412 commit 8639da3
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 8 deletions.
72 changes: 68 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
### Q4 2024
- [x] Finish the foundation of the project's CLI
- [x] Implement CLI arguments and configuration support
- [ ] Add an option for logging script executions
- [x] Add an option for logging script executions

### Q1 2025
- [ ] GUI Brainstorming and Planning
Expand Down
1 change: 1 addition & 0 deletions tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ portable-pty = "0.8.1"
ratatui = "0.29.0"
tui-term = "0.2.0"
temp-dir = "0.1.14"
time = { version = "0.3.36", features = ["local-offset", "macros", "formatting"] }
unicode-width = "0.2.0"
rand = { version = "0.8.5", optional = true }
linutil_core = { path = "../core", version = "24.9.28" }
Expand Down
42 changes: 39 additions & 3 deletions tui/src/running_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ use std::{
sync::{Arc, Mutex},
thread::JoinHandle,
};
use time::{macros::format_description, OffsetDateTime};
use tui_term::{
vt100::{self, Screen},
widget::PseudoTerminal,
};

pub struct RunningCommand {
/// A buffer to save all the command output (accumulates, until the command exits)
buffer: Arc<Mutex<Vec<u8>>>,
Expand All @@ -37,6 +37,7 @@ pub struct RunningCommand {
writer: Box<dyn Write + Send>,
/// Only set after the process has ended
status: Option<ExitStatus>,
log_path: Option<String>,
scroll_offset: usize,
}

Expand Down Expand Up @@ -79,10 +80,20 @@ impl FloatContent for RunningCommand {
.style(Style::default()),
);

Block::default()
let mut block = Block::default()
.borders(Borders::ALL)
.border_set(ratatui::symbols::border::ROUNDED)
.title_top(title_line.centered())
.title_top(title_line.centered());

if let Some(log_path) = &self.log_path {
block =
block.title_bottom(Line::from(format!(" Log saved: {} ", log_path)).centered());
} else {
block =
block.title_bottom(Line::from(" Press 'l' to save command log ").centered());
}

block
};

// Process the buffer and create the pseudo-terminal widget
Expand Down Expand Up @@ -111,6 +122,11 @@ impl FloatContent for RunningCommand {
KeyCode::PageDown => {
self.scroll_offset = self.scroll_offset.saturating_sub(10);
}
KeyCode::Char('l') if self.is_finished() => {
if let Ok(log_path) = self.save_log() {
self.log_path = Some(log_path);
}
}
// Pass other key events to the terminal
_ => self.handle_passthrough_key_event(key),
}
Expand All @@ -134,6 +150,7 @@ impl FloatContent for RunningCommand {
Shortcut::new("Close window", ["Enter", "q"]),
Shortcut::new("Scroll up", ["Page up"]),
Shortcut::new("Scroll down", ["Page down"]),
Shortcut::new("Save log", ["l"]),
]),
)
} else {
Expand Down Expand Up @@ -237,6 +254,7 @@ impl RunningCommand {
pty_master: pair.master,
writer,
status: None,
log_path: None,
scroll_offset: 0,
}
}
Expand Down Expand Up @@ -284,6 +302,24 @@ impl RunningCommand {
}
}

fn save_log(&self) -> std::io::Result<String> {
let mut log_path = std::env::temp_dir();
let date_format = format_description!("[year]-[month]-[day]-[hour]-[minute]-[second]");
log_path.push(format!(
"linutil_log_{}.log",
OffsetDateTime::now_local()
.unwrap_or(OffsetDateTime::now_utc())
.format(&date_format)
.unwrap()
));

let mut file = std::fs::File::create(&log_path)?;
let buffer = self.buffer.lock().unwrap();
file.write_all(&buffer)?;

Ok(log_path.to_string_lossy().into_owned())
}

/// Convert the KeyEvent to pty key codes, and send them to the virtual terminal
fn handle_passthrough_key_event(&mut self, key: &KeyEvent) {
let input_bytes = match key.code {
Expand Down

0 comments on commit 8639da3

Please sign in to comment.