From f5fb20e98334b86547025096ce880e27377eaa90 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Thu, 4 Jul 2024 15:33:44 -0700 Subject: [PATCH] COLUMNS COLUMNS is part of the [POSIX standard](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03). --- README.md | 10 ++++++++++ src/app.rs | 20 ++++++++++++++++++-- src/exec.rs | 14 +++++++++++--- src/main.rs | 9 ++++++++- src/view.rs | 6 ++++-- src/watch.rs | 1 + 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ce84622..22d3550 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,16 @@ the following to your `.bashrc`: export HWATCH="--no-title --color --no-help-banner --border --with-scrollbar" ``` +## Execution environment + +When running a command, `hwatch` sets the `COLUMNS`. Many commands recognize it +automatically (try `git diff --stat`), some others accept column width as a +command-line argument. + +TODO: Link to standard. + +Some versions of `bash` might reset the value of `COLUMNS`; for this reason the `HWATCH_COLUMNS` environment variable is set to the same value. + ## Example ### interval 10 second diff --git a/src/app.rs b/src/app.rs index d31e95e..583d84d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -49,9 +49,9 @@ use crate::{ }; // local const -use crate::Interval; use crate::DEFAULT_TAB_SIZE; use crate::HISTORY_WIDTH; +use crate::{Interval, OutputWidthShared}; /// #[derive(Clone, Copy, PartialEq, Eq)] @@ -196,6 +196,9 @@ pub struct App<'a> { /// interval: Interval, + /// + output_width: OutputWidthShared, + /// tab_size: u16, @@ -237,7 +240,12 @@ pub struct App<'a> { /// Trail at watch view window. impl<'a> App<'a> { /// - pub fn new(tx: Sender, rx: Receiver, interval: Interval) -> Self { + pub fn new( + tx: Sender, + rx: Receiver, + interval: Interval, + output_width: OutputWidthShared, + ) -> Self { // method at create new view trail. Self { keymap: default_keymap(), @@ -275,6 +283,7 @@ impl<'a> App<'a> { enable_summary_char: false, interval: interval.clone(), + output_width, tab_size: DEFAULT_TAB_SIZE, header_area: HeaderArea::new(*interval.read().unwrap()), @@ -388,8 +397,15 @@ impl<'a> App<'a> { /// pub fn draw(&mut self, f: &mut Frame) { + // !! self.define_subareas(f.area()); + { + let mut cur_output_width = self.output_width.write().unwrap(); + // TODO: Account for the border + *cur_output_width = Some(self.watch_area.get_pane_width() as usize); + } + if self.show_header { // Draw header area. self.header_area.draw(f); diff --git a/src/exec.rs b/src/exec.rs index f16256b..2115f19 100644 --- a/src/exec.rs +++ b/src/exec.rs @@ -173,6 +173,7 @@ pub struct ExecuteCommand { pub command: Vec, pub is_exec: bool, pub is_compress: bool, + pub output_width: Option, pub tx: Sender, } @@ -184,6 +185,7 @@ impl ExecuteCommand { command: vec![], is_exec: false, is_compress: false, + output_width: None, tx, } } @@ -203,11 +205,17 @@ impl ExecuteCommand { // exec command... let length = exec_commands.len(); - let child_result = Command::new(&exec_commands[0]) + let mut child_command = Command::new(&exec_commands[0]); + child_command .args(&exec_commands[1..length]) .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); + .stderr(Stdio::piped()); + if let Some(cols) = self.output_width { + child_command + .env("COLUMNS", cols.to_string()) + .env("HWATCH_COLUMNS", cols.to_string()); + } + let child_result = child_command.spawn(); // merge stdout and stderr let mut vec_output = Vec::new(); diff --git a/src/main.rs b/src/main.rs index da0e1ab..66ee87e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -109,7 +109,9 @@ pub const DEFAULT_TAB_SIZE: u16 = 4; pub const HISTORY_WIDTH: u16 = 25; pub const SHELL_COMMAND_EXECCMD: &str = "{COMMAND}"; pub const HISTORY_LIMIT: &str = "5000"; +// TODO: Change to mutex? Rename to ...Mutex? type Interval = Arc>; +type OutputWidthShared = Arc>>; // const at Windows #[cfg(windows)] @@ -487,6 +489,7 @@ fn main() { .get_one::("interval") .unwrap_or(&DEFAULT_INTERVAL); let interval = Interval::new(override_interval.into()); + let output_width = OutputWidthShared::new(None.into()); // history limit let default_limit: u32 = HISTORY_LIMIT.parse().unwrap(); @@ -564,6 +567,7 @@ fn main() { let command: Vec<_> = command_line; let is_exec = m.get_flag("exec"); let interval = interval.clone(); + let output_width = output_width.clone(); let _ = thread::spawn(move || loop { // Create cmd.. let mut exe = exec::ExecuteCommand::new(tx.clone()); @@ -580,9 +584,12 @@ fn main() { // Set is exec flag. exe.is_exec = is_exec; + exe.output_width = *output_width.read().unwrap(); + // Exec command exe.exec_command(); + // ! let sleep_interval = *interval.read().unwrap(); std::thread::sleep(Duration::from_secs_f64(sleep_interval)); }); @@ -592,7 +599,7 @@ fn main() { if !batch { // is watch mode // Create view - let mut view = view::View::new(interval.clone()) + let mut view = view::View::new(interval.clone(), output_width) // Set interval on view.header .set_interval(interval) .set_tab_size(tab_size) diff --git a/src/view.rs b/src/view.rs index 347ccfd..ca5c4ff 100644 --- a/src/view.rs +++ b/src/view.rs @@ -39,6 +39,7 @@ use crate::DEFAULT_TAB_SIZE; pub struct View { after_command: String, interval: Interval, + output_width: Arc>>, tab_size: u16, limit: u32, keymap: Keymap, @@ -60,10 +61,11 @@ pub struct View { /// impl View { - pub fn new(interval: Interval) -> Self { + pub fn new(interval: Interval, output_width: Arc>>) -> Self { Self { after_command: "".to_string(), interval, + output_width, tab_size: DEFAULT_TAB_SIZE, limit: 0, keymap: default_keymap(), @@ -207,7 +209,7 @@ impl View { } // Create App - let mut app = App::new(tx, rx, self.interval.clone()); + let mut app = App::new(tx, rx, self.interval.clone(), self.output_width.clone()); // set keymap app.set_keymap(self.keymap.clone()); diff --git a/src/watch.rs b/src/watch.rs index 8a06c75..ced10b1 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -111,6 +111,7 @@ impl<'a> WatchArea<'a> { } /// + // TODO: Rename to get_area_height? pub fn get_area_size(&mut self) -> i16 { let height = self.area.height as i16;