From 8924af3c5175e6f8ce26d2cdcc1d6a10138ba850 Mon Sep 17 00:00:00 2001 From: graelo Date: Sat, 27 Mar 2021 14:13:04 +0100 Subject: [PATCH] refactor: capture as method on Pane --- src/bin/tmux_copyrat.rs | 4 +- src/tmux.rs | 103 +++++++++++++++++++--------------------- 2 files changed, 52 insertions(+), 55 deletions(-) diff --git a/src/bin/tmux_copyrat.rs b/src/bin/tmux_copyrat.rs index df8b672..49e5d66 100644 --- a/src/bin/tmux_copyrat.rs +++ b/src/bin/tmux_copyrat.rs @@ -9,14 +9,14 @@ fn main() -> Result<(), error::ParseError> { let config = ConfigExt::initialize()?; // Identify active pane and capture its content. - let panes: Vec = tmux::list_panes()?; + let panes: Vec = tmux::available_panes()?; let active_pane = panes .into_iter() .find(|p| p.is_active) .expect("Exactly one tmux pane should be active in the current window."); - let buffer = tmux::capture_pane(&active_pane, &config.capture_region)?; + let buffer = active_pane.capture(&config.capture_region)?; let lines = buffer.split('\n').collect::>(); // We have to dance a little with Panes, because this process' i/o streams diff --git a/src/tmux.rs b/src/tmux.rs index 4e5c459..e019526 100644 --- a/src/tmux.rs +++ b/src/tmux.rs @@ -53,11 +53,6 @@ impl FromStr for Pane { // Pane id must be start with '%' followed by a `u32` let id_str = iter.next().unwrap(); let id = PaneId::from_str(id_str)?; - // if !id_str.starts_with('%') { - // return Err(ParseError::ExpectedPaneIdMarker); - // } - // let id = id_str[1..].parse::()?; - // let id = format!("%{}", id); let is_copy_mode = iter.next().unwrap().parse::()?; @@ -83,6 +78,53 @@ impl FromStr for Pane { } } +impl Pane { + /// Returns the entire Pane content as a `String`. + /// + /// The provided `region` specifies if the visible area is captured, or the + /// entire history. + /// + /// # Note + /// + /// In Tmux, the start line is the line at the top of the pane. The end line + /// is the last line at the bottom of the pane. + /// + /// - In normal mode, the index of the start line is always 0. The index of + /// the end line is always the pane's height minus one. These do not need to + /// be specified when capturing the pane's content. + /// + /// - If navigating history in copy mode, the index of the start line is the + /// opposite of the pane's scroll position. For instance a pane of 40 lines, + /// scrolled up by 3 lines. It is necessarily in copy mode. Its start line + /// index is `-3`. The index of the last line is `(40-1) - 3 = 36`. + /// + pub fn capture(&self, region: &CaptureRegion) -> Result { + let mut args_str = format!("capture-pane -t {pane_id} -J -p", pane_id = self.id); + + let region_str = match region { + CaptureRegion::VisibleArea => { + if self.is_copy_mode && self.scroll_position > 0 { + format!( + " -S {start} -E {end}", + start = -self.scroll_position, + end = self.height - self.scroll_position - 1 + ) + } else { + String::new() + } + } + CaptureRegion::EntireHistory => String::from(" -S - -E -"), + }; + + args_str.push_str(®ion_str); + + let args: Vec<&str> = args_str.split(' ').collect(); + + let output = duct::cmd("tmux", &args).read()?; + Ok(output) + } +} + #[derive(Debug, PartialEq)] pub struct PaneId(String); @@ -90,12 +132,12 @@ impl FromStr for PaneId { type Err = ParseError; /// Parse into PaneId. The `&str` must be start with '%' - /// followed by a `u32`. + /// followed by a `u16`. fn from_str(src: &str) -> Result { if !src.starts_with('%') { return Err(ParseError::ExpectedPaneIdMarker); } - let id = src[1..].parse::()?; + let id = src[1..].parse::()?; let id = format!("%{}", id); Ok(PaneId(id)) } @@ -114,7 +156,7 @@ impl fmt::Display for PaneId { } /// Returns a list of `Pane` from the current tmux session. -pub fn list_panes() -> Result, ParseError> { +pub fn available_panes() -> Result, ParseError> { let args = vec![ "list-panes", "-F", @@ -162,51 +204,6 @@ pub fn get_options(prefix: &str) -> Result, ParseError> Ok(args) } -/// Returns the entire Pane content as a `String`. -/// -/// The provided `region` specifies if the visible area is captured, or the -/// entire history. -/// -/// # Note -/// -/// In Tmux, the start line is the line at the top of the pane. The end line -/// is the last line at the bottom of the pane. -/// -/// - In normal mode, the index of the start line is always 0. The index of -/// the end line is always the pane's height minus one. These do not need to -/// be specified when capturing the pane's content. -/// -/// - If navigating history in copy mode, the index of the start line is the -/// opposite of the pane's scroll position. For instance a pane of 40 lines, -/// scrolled up by 3 lines. It is necessarily in copy mode. Its start line -/// index is `-3`. The index of the last line is `(40-1) - 3 = 36`. -/// -pub fn capture_pane(pane: &Pane, region: &CaptureRegion) -> Result { - let mut args_str = format!("capture-pane -t {pane_id} -J -p", pane_id = pane.id); - - let region_str = match region { - CaptureRegion::VisibleArea => { - if pane.is_copy_mode && pane.scroll_position > 0 { - format!( - " -S {start} -E {end}", - start = -pane.scroll_position, - end = pane.height - pane.scroll_position - 1 - ) - } else { - String::new() - } - } - CaptureRegion::EntireHistory => String::from(" -S - -E -"), - }; - - args_str.push_str(®ion_str); - - let args: Vec<&str> = args_str.split(' ').collect(); - - let output = duct::cmd("tmux", &args).read()?; - Ok(output) -} - /// Ask tmux to swap the current Pane with the target_pane (uses Tmux format). pub fn swap_pane_with(target_pane: &str) -> Result<(), ParseError> { // -Z: keep the window zoomed if it was zoomed.