1use std::process::Command;
7
8use crate::error::{Error, Result};
9
10fn run(args: &[&str]) -> Result<String> {
12 let output = Command::new("tmux").args(args).output().map_err(|e| {
13 if e.kind() == std::io::ErrorKind::NotFound {
14 Error::TmuxMissing
15 } else {
16 Error::Tmux(e.to_string())
17 }
18 })?;
19
20 if !output.status.success() {
21 let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();
22 return Err(Error::Tmux(format!("`tmux {}` → {}", args.join(" "), stderr)));
23 }
24
25 Ok(String::from_utf8_lossy(&output.stdout).into_owned())
26}
27
28pub fn new_session(name: &str, width: u16, height: u16, cwd: &str, command: &str) -> Result<()> {
31 if has_session(name)? {
32 return Err(Error::SessionExists(name.to_string()));
33 }
34 run(&[
35 "new-session",
36 "-d",
37 "-s",
38 name,
39 "-x",
40 &width.to_string(),
41 "-y",
42 &height.to_string(),
43 "-c",
44 cwd,
45 command,
46 ])
47 .map(|_| ())
48}
49
50pub fn send_literal(name: &str, text: &str) -> Result<()> {
54 require_session(name)?;
55 run(&["send-keys", "-t", name, "-l", text]).map(|_| ())
56}
57
58pub fn send_key(name: &str, key: &str) -> Result<()> {
60 require_session(name)?;
61 run(&["send-keys", "-t", name, key]).map(|_| ())
62}
63
64pub fn capture_pane(name: &str) -> Result<String> {
66 require_session(name)?;
67 run(&["capture-pane", "-p", "-t", name])
68}
69
70pub fn has_session(name: &str) -> Result<bool> {
72 let output = Command::new("tmux")
73 .args(["has-session", "-t", name])
74 .output()
75 .map_err(|e| {
76 if e.kind() == std::io::ErrorKind::NotFound {
77 Error::TmuxMissing
78 } else {
79 Error::Tmux(e.to_string())
80 }
81 })?;
82 Ok(output.status.success())
84}
85
86pub fn kill_session(name: &str) -> Result<()> {
88 require_session(name)?;
89 run(&["kill-session", "-t", name]).map(|_| ())
90}
91
92fn require_session(name: &str) -> Result<()> {
93 if !has_session(name)? {
94 return Err(Error::NoSuchSession(name.to_string()));
95 }
96 Ok(())
97}