Skip to main content

yhfp/
main.rs

1//! Copy current Helix file path with line number to clipboard.
2//!
3//! # Errors
4//! - `WezTerm` command or status line parsing fails.
5#![feature(exit_status_error)]
6
7use core::str::FromStr;
8use std::process::Command;
9
10use rootcause::prelude::ResultExt as _;
11use rootcause::report;
12use ytil_editor::Editor;
13use ytil_hx::HxStatusLine;
14use ytil_sys::cli::Args;
15
16/// Formats Helix status line into file path with line number.
17///
18/// # Errors
19/// - UTF-8 conversion fails.
20fn format_hx_status_line(hx_status_line: &HxStatusLine) -> rootcause::Result<String> {
21    let file_path = hx_status_line
22        .file_path
23        .to_str()
24        .ok_or_else(|| report!("cannot convert path to str"))
25        .attach_with(|| format!("path={}", hx_status_line.file_path.display()))?;
26
27    Ok(format!("{file_path}:{}", hx_status_line.position.line))
28}
29
30/// Copy current Helix file path with line number to clipboard.
31#[ytil_sys::main]
32fn main() -> rootcause::Result<()> {
33    let args = ytil_sys::cli::get();
34    if args.has_help() {
35        println!("{}", include_str!("../help.txt"));
36        return Ok(());
37    }
38
39    let hx_pane_id = ytil_wezterm::get_sibling_pane_with_titles(
40        &ytil_wezterm::get_all_panes(&[])?,
41        ytil_wezterm::get_current_pane_id()?,
42        Editor::Hx.pane_titles(),
43    )?
44    .pane_id;
45
46    let wezterm_pane_text = String::from_utf8(
47        Command::new("wezterm")
48            .args(["cli", "get-text", "--pane-id", &hx_pane_id.to_string()])
49            .output()?
50            .stdout,
51    )?;
52
53    let hx_status_line_str = wezterm_pane_text
54        .lines()
55        .nth_back(1)
56        .ok_or_else(|| report!("missing hx status line"))
57        .attach_with(|| format!("pane_id={hx_pane_id} text={wezterm_pane_text:#?}"))?;
58
59    let hx_status_line = HxStatusLine::from_str(hx_status_line_str)?;
60
61    ytil_sys::file::cp_to_system_clipboard(&mut format_hx_status_line(&hx_status_line)?.as_bytes())?;
62
63    Ok(())
64}
65
66#[cfg(test)]
67mod tests {
68    use std::path::PathBuf;
69
70    use rstest::rstest;
71
72    use super::*;
73
74    #[rstest]
75    #[case("src/main.rs", 42, 7, "src/main.rs:42")]
76    #[case("yog/ytil/cmd/src/lib.rs", 1, 1, "yog/ytil/cmd/src/lib.rs:1")]
77    #[case("file.txt", 100, 50, "file.txt:100")]
78    fn format_hx_status_line_returns_path_with_line_number(
79        #[case] path: &str,
80        #[case] line: usize,
81        #[case] column: usize,
82        #[case] expected: &str,
83    ) {
84        let status = HxStatusLine {
85            file_path: PathBuf::from(path),
86            position: ytil_hx::HxCursorPosition { line, column },
87        };
88        assert2::assert!(let Ok(result) = format_hx_status_line(&status));
89        pretty_assertions::assert_eq!(result, expected);
90    }
91}